From 4a3a9218ae186ff1586dfc78da53d12232c23833 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson <43759233+kenzieschmoll@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:37:54 -0800 Subject: [PATCH] Format `devtools_app` and `devtools_test` with the new Dart formatter. (#8537) --- flutter-candidate.txt | 2 +- packages/analysis_options.yaml | 6 +- .../benchmark/devtools_benchmarks_test.dart | 24 +- .../devtools_app/benchmark/scripts/args.dart | 14 +- .../benchmark/scripts/compare_benchmarks.dart | 10 +- .../scripts/dart2wasm_performance_diff.dart | 43 +- .../benchmark/scripts/run_benchmarks.dart | 12 +- .../test_infra/client/client_shared.dart | 9 +- .../benchmark/test_infra/common.dart | 3 +- .../test_infra/devtools_recorder.dart | 2 +- .../test_infra/project_root_directory.dart | 8 +- .../benchmark/web_bundle_size_test.dart | 96 +- .../integration_test/run_tests.dart | 14 +- .../live_connection/debugger_panel_test.dart | 42 +- .../devtools_extensions_test.dart | 139 +- .../live_connection/eval_and_browse_test.dart | 10 +- .../memory_screen_helpers.dart | 4 +- ...rformance_screen_event_recording_test.dart | 176 +- .../service_connection_test.dart | 6 +- .../service_extensions_test.dart | 25 +- .../offline/memory_offline_data_test.dart | 37 +- .../test_infra/run/_in_file_args.dart | 40 +- .../test_infra/run/_test_app_driver.dart | 149 +- .../test_infra/run/run_test.dart | 16 +- packages/devtools_app/lib/devtools.dart | 2 +- packages/devtools_app/lib/src/app.dart | 183 +- .../lib/src/example/conditional_screen.dart | 25 +- .../extensions/embedded/_controller_web.dart | 18 +- .../src/extensions/embedded/_view_web.dart | 44 +- .../lib/src/extensions/extension_screen.dart | 61 +- .../extensions/extension_screen_controls.dart | 41 +- .../lib/src/extensions/extension_service.dart | 65 +- .../extensions/extension_service_helpers.dart | 2 +- .../src/extensions/extension_settings.dart | 81 +- .../lib/src/framework/about_dialog.dart | 50 +- .../lib/src/framework/app_bar.dart | 7 +- .../lib/src/framework/app_error_handling.dart | 30 +- .../src/framework/disconnect_observer.dart | 69 +- .../lib/src/framework/framework_core.dart | 49 +- .../lib/src/framework/home_screen.dart | 68 +- .../lib/src/framework/initializer.dart | 7 +- .../lib/src/framework/notifications_view.dart | 90 +- .../release_notes/release_notes.dart | 29 +- .../src/framework/report_feedback_button.dart | 27 +- .../lib/src/framework/scaffold.dart | 161 +- .../lib/src/framework/settings_dialog.dart | 49 +- .../lib/src/framework/status_line.dart | 89 +- .../lib/src/framework/theme_manager.dart | 21 +- .../screens/app_size/app_size_controller.dart | 75 +- .../src/screens/app_size/app_size_screen.dart | 181 +- .../src/screens/app_size/app_size_table.dart | 53 +- .../app_size/code_size_attribution.dart | 37 +- .../screens/debugger/breakpoint_manager.dart | 89 +- .../lib/src/screens/debugger/breakpoints.dart | 12 +- .../lib/src/screens/debugger/call_stack.dart | 30 +- .../lib/src/screens/debugger/codeview.dart | 370 +- .../screens/debugger/codeview_controller.dart | 99 +- .../lib/src/screens/debugger/controls.dart | 76 +- .../screens/debugger/debugger_controller.dart | 122 +- .../src/screens/debugger/debugger_model.dart | 10 +- .../src/screens/debugger/debugger_screen.dart | 90 +- .../lib/src/screens/debugger/file_search.dart | 104 +- .../lib/src/screens/debugger/key_sets.dart | 14 +- .../screens/debugger/program_explorer.dart | 156 +- .../debugger/program_explorer_controller.dart | 71 +- .../debugger/program_explorer_model.dart | 82 +- .../lib/src/screens/debugger/span_parser.dart | 110 +- .../screens/debugger/syntax_highlighter.dart | 62 +- .../lib/src/screens/debugger/variables.dart | 15 +- .../deep_link_list_view.dart | 144 +- .../deep_links_controller.dart | 187 +- .../deep_links_model.dart | 134 +- .../deep_links_services.dart | 74 +- .../project_root_selection/root_selector.dart | 33 +- .../select_project_view.dart | 9 +- .../validation_details_view.dart | 315 +- .../inspector/inspector_breadcrumbs.dart | 108 +- .../inspector/inspector_controller.dart | 78 +- .../inspector/inspector_data_models.dart | 176 +- .../inspector/inspector_screen_body.dart | 109 +- .../inspector_screen_details_tab.dart | 17 +- .../inspector/inspector_tree_controller.dart | 241 +- .../inspector/layout_explorer/box/box.dart | 20 +- .../inspector/layout_explorer/flex/flex.dart | 198 +- .../inspector/layout_explorer/flex/utils.dart | 12 +- .../inspector/layout_explorer/ui/arrow.dart | 107 +- .../layout_explorer/ui/dimension.dart | 7 +- .../layout_explorer/ui/free_space.dart | 13 +- .../ui/layout_explorer_widget.dart | 22 +- .../ui/overflow_indicator_painter.dart | 17 +- .../inspector/layout_explorer/ui/theme.dart | 7 +- .../inspector/layout_explorer/ui/utils.dart | 98 +- .../ui/widget_constraints.dart | 38 +- .../layout_explorer/ui/widgets_theme.dart | 15 +- .../inspector_shared/inspector_controls.dart | 25 +- .../inspector_shared/inspector_screen.dart | 16 +- .../inspector_settings_dialog.dart | 57 +- .../inspector_v2/inspector_controller.dart | 110 +- .../inspector_v2/inspector_data_models.dart | 228 +- .../inspector_v2/inspector_screen_body.dart | 99 +- .../inspector_tree_controller.dart | 334 +- .../inspector_v2/layout_explorer/box/box.dart | 13 +- .../layout_explorer/flex/flex.dart | 198 +- .../layout_explorer/flex/utils.dart | 12 +- .../layout_explorer/ui/arrow.dart | 107 +- .../layout_explorer/ui/dimension.dart | 7 +- .../layout_explorer/ui/free_space.dart | 13 +- .../ui/layout_explorer_widget.dart | 22 +- .../ui/overflow_indicator_painter.dart | 17 +- .../layout_explorer/ui/theme.dart | 7 +- .../layout_explorer/ui/utils.dart | 148 +- .../ui/widget_constraints.dart | 38 +- .../layout_explorer/ui/widgets_theme.dart | 15 +- .../widget_properties/properties_view.dart | 82 +- .../lib/src/screens/logging/_log_details.dart | 55 +- .../src/screens/logging/_message_column.dart | 5 +- .../lib/src/screens/logging/_when_column.dart | 26 +- .../screens/logging/logging_controller.dart | 123 +- .../src/screens/logging/logging_controls.dart | 32 +- .../src/screens/logging/logging_screen.dart | 7 +- .../lib/src/screens/logging/metadata.dart | 25 +- .../memory/framework/memory_controller.dart | 28 +- .../memory/framework/memory_screen.dart | 4 +- .../screens/memory/framework/memory_tabs.dart | 56 +- .../framework/offline_data/offline_data.dart | 9 +- .../screens/memory/framework/screen_body.dart | 9 +- .../chart/controller/chart_connection.dart | 53 +- .../panes/chart/controller/chart_data.dart | 14 +- .../controller/chart_pane_controller.dart | 12 +- .../charts/android_chart_controller.dart | 15 +- .../charts/event_chart_controller.dart | 31 +- .../charts/vm_chart_controller.dart | 23 +- .../chart/controller/memory_tracker.dart | 32 +- .../memory/panes/chart/data/charts.dart | 96 +- .../chart/widgets/chart_control_pane.dart | 35 +- .../panes/chart/widgets/chart_pane.dart | 146 +- .../chart/widgets/interval_dropdown.dart | 18 +- .../memory/panes/chart/widgets/legend.dart | 94 +- .../panes/chart/widgets/memory_chart.dart | 5 +- .../panes/control/widgets/control_pane.dart | 19 +- .../control/widgets/settings_dialog.dart | 4 +- .../diff/controller/diff_pane_controller.dart | 88 +- .../panes/diff/controller/snapshot_item.dart | 19 +- .../memory/panes/diff/data/classes_diff.dart | 28 +- .../panes/diff/data/heap_diff_data.dart | 21 +- .../panes/diff/data/heap_diff_store.dart | 17 +- .../screens/memory/panes/diff/diff_pane.dart | 19 +- .../widgets/class_details/class_details.dart | 13 +- .../diff/widgets/class_details/path.dart | 64 +- .../diff/widgets/class_details/paths.dart | 82 +- .../diff/widgets/classes_table_diff.dart | 92 +- .../diff/widgets/classes_table_single.dart | 69 +- .../memory/panes/diff/widgets/instances.dart | 56 +- .../diff/widgets/snapshot_control_pane.dart | 87 +- .../panes/diff/widgets/snapshot_list.dart | 88 +- .../panes/diff/widgets/snapshot_view.dart | 21 +- .../memory/panes/profile/instances.dart | 17 +- .../screens/memory/panes/profile/model.dart | 65 +- .../profile/profile_pane_controller.dart | 10 +- .../memory/panes/profile/profile_view.dart | 194 +- .../memory/panes/tracing/class_table.dart | 36 +- .../memory/panes/tracing/tracing_data.dart | 55 +- .../tracing/tracing_pane_controller.dart | 13 +- .../memory/panes/tracing/tracing_tree.dart | 71 +- .../memory/panes/tracing/tracing_view.dart | 20 +- .../memory/shared/heap/class_filter.dart | 54 +- .../screens/memory/shared/heap/sampler.dart | 44 +- .../primitives/instance_context_menu.dart | 7 +- .../shared/primitives/memory_timeline.dart | 36 +- .../memory/shared/primitives/painting.dart | 22 +- .../shared/primitives/simple_elements.dart | 9 +- .../memory/shared/widgets/class_filter.dart | 55 +- .../shared/widgets/shared_memory_widgets.dart | 7 +- .../lib/src/screens/network/constants.dart | 7 +- .../src/screens/network/har_data_entry.dart | 152 +- .../src/screens/network/har_network_data.dart | 20 +- .../screens/network/network_controller.dart | 113 +- .../src/screens/network/network_model.dart | 36 +- .../network/network_request_inspector.dart | 124 +- .../network_request_inspector_views.dart | 361 +- .../src/screens/network/network_screen.dart | 122 +- .../src/screens/network/network_service.dart | 12 +- .../enhance_tracing/enhance_tracing.dart | 145 +- .../enhance_tracing_controller.dart | 32 +- .../controls/more_debugging_options.dart | 9 +- .../panes/controls/performance_controls.dart | 12 +- .../panes/controls/performance_settings.dart | 9 +- .../flutter_frames/flutter_frame_model.dart | 27 +- .../flutter_frames/flutter_frames_chart.dart | 193 +- .../flutter_frames_controller.dart | 12 +- .../panes/frame_analysis/frame_analysis.dart | 16 +- .../frame_analysis/frame_analysis_model.dart | 40 +- .../panes/frame_analysis/frame_hints.dart | 165 +- .../frame_analysis/frame_time_visualizer.dart | 79 +- .../panes/rebuild_stats/rebuild_stats.dart | 38 +- .../rebuild_stats/rebuild_stats_model.dart | 16 +- .../perfetto/_perfetto_controller_web.dart | 16 +- .../perfetto/_perfetto_desktop.dart | 5 +- .../perfetto/_perfetto_web.dart | 49 +- .../timeline_events/perfetto/perfetto.dart | 4 +- .../perfetto/tracing/model.dart | 7 +- .../timeline_event_processor.dart | 3 +- .../timeline_events_controller.dart | 115 +- .../timeline_events/timeline_events_view.dart | 71 +- .../performance/performance_controller.dart | 55 +- .../performance/performance_model.dart | 34 +- .../performance/performance_screen.dart | 15 +- .../performance/tabbed_performance_view.dart | 47 +- .../screens/profiler/cpu_profile_model.dart | 195 +- .../screens/profiler/cpu_profile_service.dart | 35 +- .../profiler/cpu_profile_transformer.dart | 14 +- .../src/screens/profiler/cpu_profiler.dart | 63 +- .../profiler/cpu_profiler_controller.dart | 192 +- .../src/screens/profiler/panes/bottom_up.dart | 38 +- .../src/screens/profiler/panes/call_tree.dart | 10 +- .../panes/controls/cpu_profiler_controls.dart | 36 +- .../controls/profiler_screen_controls.dart | 42 +- .../profiler/panes/cpu_flame_chart.dart | 28 +- .../profiler/panes/cpu_profile_columns.dart | 24 +- .../panes/method_table/method_table.dart | 103 +- .../method_table/method_table_controller.dart | 15 +- .../method_table/method_table_model.dart | 25 +- .../src/screens/profiler/profiler_screen.dart | 20 +- .../profiler/profiler_screen_controller.dart | 29 +- .../src/screens/profiler/profiler_status.dart | 4 +- .../src/screens/provider/provider_screen.dart | 3 +- .../isolate_statistics_view.dart | 134 +- .../class_hierarchy_explorer.dart | 9 +- .../class_hierarchy_explorer_controller.dart | 5 +- .../inbound_references_tree.dart | 21 +- .../object_inspector_view.dart | 41 +- .../object_inspector_view_controller.dart | 80 +- .../object_store_controller.dart | 5 +- .../object_inspector/object_viewport.dart | 71 +- .../object_inspector/vm_class_display.dart | 20 +- .../object_inspector/vm_code_display.dart | 73 +- .../object_inspector/vm_field_display.dart | 9 +- .../object_inspector/vm_function_display.dart | 39 +- .../object_inspector/vm_ic_data_display.dart | 13 +- .../object_inspector/vm_instance_display.dart | 26 +- .../object_inspector/vm_library_display.dart | 31 +- .../object_inspector/vm_object_model.dart | 52 +- .../vm_object_pool_display.dart | 6 +- .../object_inspector/vm_script_display.dart | 14 +- .../vm_simple_list_display.dart | 18 +- .../process_memory_tree_columns.dart | 12 +- .../process_memory/process_memory_view.dart | 36 +- .../process_memory_view_controller.dart | 8 +- .../vm_developer_common_widgets.dart | 254 +- .../vm_developer_tools_controller.dart | 2 +- .../vm_developer_tools_screen.dart | 15 +- .../vm_service_private_extensions.dart | 250 +- .../vm_statistics/vm_statistics_view.dart | 50 +- .../vm_statistics_view_controller.dart | 8 +- .../lib/src/service/editor/api_classes.dart | 237 +- .../lib/src/service/editor/editor_client.dart | 44 +- .../src/service/json_to_service_cache.dart | 50 +- .../service/service_extension_widgets.dart | 176 +- .../lib/src/service/service_extensions.dart | 115 +- .../lib/src/service/service_manager.dart | 108 +- .../lib/src/service/timeline_streams.dart | 47 +- .../lib/src/service/vm_flags.dart | 13 +- .../lib/src/service/vm_service_logger.dart | 5 +- .../lib/src/service/vm_service_wrapper.dart | 64 +- .../src/shared/analytics/_analytics_stub.dart | 5 +- .../src/shared/analytics/_analytics_web.dart | 216 +- .../analytics/analytics_controller.dart | 11 +- .../lib/src/shared/analytics/constants.dart | 6 +- .../constants/_cpu_profiler_constants.dart | 6 +- .../constants/_inspector_constants.dart | 4 +- .../constants/_logging_constants.dart | 5 +- .../constants/_memory_constants.dart | 5 +- .../constants/_network_constants.dart | 4 +- .../lib/src/shared/analytics/metrics.dart | 5 +- .../lib/src/shared/analytics/prompt.dart | 27 +- .../lib/src/shared/banner_messages.dart | 114 +- .../lib/src/shared/charts/chart.dart | 403 +- .../src/shared/charts/chart_controller.dart | 50 +- .../lib/src/shared/charts/chart_trace.dart | 33 +- .../lib/src/shared/charts/flame_chart.dart | 193 +- .../lib/src/shared/charts/treemap.dart | 109 +- .../lib/src/shared/collapsible_mixin.dart | 6 +- .../lib/src/shared/common_widgets.dart | 311 +- .../_copy_to_clipboard_web.dart | 5 +- .../drag_and_drop/drag_and_drop.dart | 38 +- .../_framework_initialize_web.dart | 4 +- .../import_export/_export_desktop.dart | 5 +- .../import_export/_export_web.dart | 5 +- .../import_export/import_export.dart | 28 +- .../shared/config_specific/logger/logger.dart | 6 +- .../notifications/_notifications_web.dart | 5 +- .../post_message/_post_message_web.dart | 6 +- .../post_message/post_message.dart | 5 +- .../lib/src/shared/connection_info.dart | 11 +- .../lib/src/shared/console/console.dart | 25 +- .../src/shared/console/console_service.dart | 31 +- .../shared/console/eval/auto_complete.dart | 87 +- .../src/shared/console/eval/eval_service.dart | 24 +- .../shared/console/eval/inspector_tree.dart | 25 +- .../console/eval/inspector_tree_v2.dart | 15 +- .../shared/console/primitives/assignment.dart | 8 +- .../src/shared/console/primitives/scope.dart | 5 +- .../console/primitives/simple_items.dart | 4 +- .../shared/console/widgets/console_pane.dart | 56 +- .../shared/console/widgets/description.dart | 159 +- .../console/widgets/display_provider.dart | 57 +- .../src/shared/console/widgets/evaluate.dart | 90 +- .../console/widgets/expandable_variable.dart | 20 +- .../shared/console/widgets/help_dialog.dart | 14 +- .../lib/src/shared/development_helpers.dart | 61 +- .../shared/diagnostics/dap_object_node.dart | 13 +- .../shared/diagnostics/dart_object_node.dart | 45 +- .../shared/diagnostics/diagnostics_node.dart | 45 +- .../generic_instance_reference.dart | 15 +- .../shared/diagnostics/inspector_service.dart | 171 +- .../shared/diagnostics/object_group_api.dart | 3 +- .../primitives/source_location.dart | 5 +- .../src/shared/diagnostics/references.dart | 92 +- .../src/shared/diagnostics/tree_builder.dart | 74 +- .../shared/diagnostics/variable_factory.dart | 15 +- .../src/shared/diagnostics_text_styles.dart | 38 +- .../devtools_app/lib/src/shared/dialogs.dart | 38 +- .../src/shared/dtd_manager_extensions.dart | 15 +- .../lib/src/shared/editable_list.dart | 45 +- .../environment_parameters_external.dart | 26 +- .../lib/src/shared/error_badge_manager.dart | 39 +- .../lib/src/shared/feature_flags.dart | 11 +- .../lib/src/shared/file_import.dart | 58 +- .../lib/src/shared/framework_controller.dart | 5 +- .../lib/src/shared/history_viewport.dart | 146 +- .../lib/src/shared/http/_http_exception.dart | 7 +- .../lib/src/shared/http/curl_command.dart | 4 +- .../src/shared/http/http_request_data.dart | 37 +- .../lib/src/shared/http/http_service.dart | 19 +- .../lib/src/shared/memory/class_name.dart | 28 +- .../lib/src/shared/memory/classes.dart | 53 +- .../lib/src/shared/memory/gc_stats.dart | 12 +- .../lib/src/shared/memory/heap_data.dart | 10 +- .../lib/src/shared/memory/retainers.dart | 25 +- .../lib/src/shared/memory/retaining_path.dart | 18 +- .../lib/src/shared/memory/simple_items.dart | 10 +- .../lib/src/shared/notifications.dart | 34 +- .../lib/src/shared/offline_data.dart | 11 +- .../preferences/_extension_preferences.dart | 25 +- .../preferences/_inspector_preferences.dart | 55 +- .../preferences/_logging_preferences.dart | 59 +- .../preferences/_memory_preferences.dart | 67 +- .../preferences/_performance_preferences.dart | 50 +- .../src/shared/preferences/preferences.dart | 17 +- .../lib/src/shared/primitives/byte_utils.dart | 8 +- .../custom_pointer_scroll_view.dart | 133 +- .../lib/src/shared/primitives/encoding.dart | 9 +- .../primitives/extent_delegate_list.dart | 49 +- .../linked_scroll_controller.dart | 13 +- .../src/shared/primitives/trace_event.dart | 19 +- .../lib/src/shared/primitives/trees.dart | 26 +- .../lib/src/shared/primitives/utils.dart | 73 +- .../lib/src/shared/profiler_utils.dart | 40 +- .../devtools_app/lib/src/shared/routing.dart | 50 +- .../devtools_app/lib/src/shared/screen.dart | 133 +- .../src/shared/server/_deep_links_api.dart | 8 +- .../src/shared/server/_preferences_api.dart | 4 +- .../lib/src/shared/server/server.dart | 5 +- .../src/shared/server/server_api_client.dart | 29 +- .../lib/src/shared/side_panel.dart | 21 +- .../devtools_app/lib/src/shared/survey.dart | 42 +- .../lib/src/shared/table/_flat_table.dart | 57 +- .../lib/src/shared/table/_table_column.dart | 47 +- .../lib/src/shared/table/_table_row.dart | 274 +- .../lib/src/shared/table/_tree_table.dart | 40 +- .../lib/src/shared/table/column_widths.dart | 18 +- .../lib/src/shared/table/table.dart | 100 +- .../src/shared/table/table_controller.dart | 41 +- .../lib/src/shared/table/table_data.dart | 36 +- .../devtools_app/lib/src/shared/tree.dart | 31 +- .../lib/src/shared/ui/colors.dart | 45 +- .../lib/src/shared/ui/filter.dart | 205 +- .../devtools_app/lib/src/shared/ui/hover.dart | 67 +- .../devtools_app/lib/src/shared/ui/icons.dart | 54 +- .../lib/src/shared/ui/search.dart | 231 +- .../devtools_app/lib/src/shared/ui/tab.dart | 27 +- .../devtools_app/lib/src/shared/ui/utils.dart | 27 +- .../lib/src/shared/ui/vm_flag_widgets.dart | 54 +- .../devtools_app/lib/src/shared/utils.dart | 38 +- .../devtools_app/lib/src/shared/vm_utils.dart | 11 +- .../src/standalone_ui/standalone_screen.dart | 31 +- .../standalone_ui/vs_code/debug_sessions.dart | 58 +- .../src/standalone_ui/vs_code/devices.dart | 36 +- .../vs_code/devtools/devtools_view.dart | 55 +- .../vs_code/devtools/shared.dart | 39 +- .../sidebar_extensions_controller.dart | 45 +- .../standalone_ui/vs_code/flutter_panel.dart | 15 +- packages/devtools_app/pubspec.yaml | 6 +- .../test/app_size/app_size_screen_test.dart | 654 +- .../app_size/code_size_attribution_test.dart | 87 +- .../cpu_profiler/cpu_profile_model_test.dart | 170 +- .../cpu_profile_transformer_test.dart | 18 +- .../cpu_profiler_controller_test.dart | 142 +- .../test/cpu_profiler/cpu_profiler_test.dart | 714 +- .../method_table/method_table_model_test.dart | 28 +- .../method_table/method_table_test.dart | 151 +- .../profiler_screen_controller_test.dart | 34 +- .../cpu_profiler/profiler_screen_test.dart | 72 +- .../debugger/association_variable_test.dart | 55 +- .../debugger_codeview_statistics_test.dart | 72 +- .../test/debugger/debugger_codeview_test.dart | 139 +- .../test/debugger/debugger_console_test.dart | 15 +- .../debugger/debugger_controller_test.dart | 5 +- .../debugger/debugger_evaluation_test.dart | 495 +- .../test/debugger/debugger_floating_test.dart | 15 +- .../debugger_screen_breakpoints_test.dart | 52 +- .../debugger_screen_call_stack_test.dart | 303 +- .../debugger_screen_dap_variables_test.dart | 154 +- ...ugger_screen_explorer_visibility_test.dart | 174 +- .../debugger/debugger_screen_paused_test.dart | 103 +- .../test/debugger/debugger_screen_test.dart | 206 +- .../debugger_screen_variables_test.dart | 142 +- .../test/debugger/debugger_scripts_test.dart | 192 +- .../test/debugger/eval_field_test.dart | 186 +- .../test/debugger/file_search_test.dart | 515 +- .../test/debugger/program_explorer_test.dart | 141 +- .../test/debugger/records_variable_test.dart | 27 +- .../debugger/typed_data_variable_test.dart | 279 +- .../test/debugger/variables_test.dart | 50 +- .../deep_links_screen_test.dart | 588 +- .../select_project_view_test.dart | 60 +- .../extensions/extension_analytics_test.dart | 142 +- .../extensions/extension_screen_test.dart | 172 +- .../extensions/extension_service_test.dart | 65 +- .../extensions/extension_settings_test.dart | 232 +- .../test/http/curl_command_test.dart | 4 +- .../test/inspector/diagnostics_test.dart | 402 +- .../inspector_error_navigator_test.dart | 5 +- .../inspector/inspector_integration_test.dart | 298 +- .../test/inspector/inspector_screen_test.dart | 222 +- .../test/inspector/inspector_tree_test.dart | 99 +- .../layout_explorer/flex/arrow_test.dart | 172 +- .../layout_explorer/flex/flex_test.dart | 86 +- .../inspector_data_models_test.dart | 130 +- ...ayout_explorer_serialization_delegate.dart | 88 +- .../layout_explorer_test_utils.dart | 15 +- .../test/inspector/utils/inspector_tree.dart | 61 +- .../test/inspector_v2/diagnostics_test.dart | 402 +- .../inspector_error_navigator_test.dart | 5 +- .../inspector_integration_test.dart | 350 +- .../inspector_v2/inspector_screen_test.dart | 241 +- .../inspector_v2/inspector_tree_test.dart | 99 +- .../layout_explorer/flex/arrow_test.dart | 172 +- .../layout_explorer/flex/flex_test.dart | 86 +- .../inspector_data_models_test.dart | 130 +- ...ayout_explorer_serialization_delegate.dart | 88 +- .../layout_explorer_test_utils.dart | 15 +- .../inspector_v2/utils/inspector_tree.dart | 61 +- .../in_file_args_test.dart | 33 +- .../test/legacy_integration_tests/app.dart | 5 +- .../legacy_integration_tests/debugger.dart | 10 +- .../legacy_integration_tests/integration.dart | 40 +- .../legacy_integration_tests/logging.dart | 5 +- .../test/logging/logging_controller_test.dart | 13 +- .../logging/logging_screen_data_test.dart | 271 +- .../test/logging/logging_screen_test.dart | 174 +- .../test/logging/metadata_test.dart | 44 +- .../test/memory/chart/chart_test.dart | 1444 +- .../memory/control/settings_dialog_test.dart | 83 +- .../controller/diff_pane_controller_test.dart | 3 +- .../memory/diff/controller/filter_test.dart | 8 +- .../diff/controller/heap_diff_test.dart | 65 +- .../controller/memory_footprint_test.dart | 6 +- .../diff/controller/snapshot_item_test.dart | 68 +- .../diff/widgets/class_filter_test.dart | 17 +- .../memory/diff/widgets/diff_pane_test.dart | 154 +- .../test/memory/diff/widgets/paths_test.dart | 5 +- .../framework/memory_controller_test.dart | 5 +- .../memory/framework/memory_screen_test.dart | 201 +- .../allocation_profile_table_view_test.dart | 319 +- .../memory/shared/heap/class_filter_test.dart | 24 +- .../heap/heap_analyzer_golden_test.dart | 14 +- .../shared/heap/heap_analyzer_test.dart | 184 +- .../test/memory/shared/heap/heap_test.dart | 108 +- .../shared/primitives/class_name_test.dart | 20 +- .../tracing/tracing_pane_controller_test.dart | 31 +- .../memory/tracing/tracing_view_test.dart | 622 +- .../test/network/network_controller_test.dart | 38 +- .../test/network/network_model_test.dart | 60 +- .../test/network/network_profiler_test.dart | 475 +- .../network_request_inspector_test.dart | 55 +- .../test/network/network_screen_test.dart | 5 +- .../test/network/network_table_test.dart | 6 +- .../controls/enhance_tracing_test.dart | 248 +- .../controls/performance_controls_test.dart | 109 +- .../flutter_frames_chart_test.dart | 161 +- .../flutter_frames_controller_test.dart | 40 +- .../frame_analysis/frame_analysis_test.dart | 122 +- .../frame_analysis/frame_hints_test.dart | 174 +- .../performance_controller_test.dart | 5 +- .../performance/performance_model_test.dart | 6 +- .../performance/performance_screen_test.dart | 135 +- .../tabbed_performance_view_test.dart | 43 +- .../timeline_event_processor_test.dart | 35 +- .../timeline_events_controller_test.dart | 30 +- .../test/shared/about_dialog_test.dart | 20 +- .../test/shared/analytics_prompt_test.dart | 101 +- .../test/shared/ansi_up_test.dart | 111 +- .../test/shared/auto_complete_test.dart | 5 +- .../test/shared/banner_messages_test.dart | 5 +- .../test/shared/common_widgets_test.dart | 5 +- .../test/shared/connection_info_test.dart | 123 +- .../test/shared/console/assignment_test.dart | 8 +- .../diagnostics/diagnostics_node_test.dart | 131 +- .../diagnostics/inspector_service_test.dart | 272 +- .../test/shared/disconnect_observer_test.dart | 157 +- .../test/shared/editable_list_test.dart | 262 +- .../test/shared/enum_utils_test.dart | 7 +- .../test/shared/eval_integration_test.dart | 56 +- .../extent_delegate_list_view_test.dart | 263 +- .../devtools_app/test/shared/filter_test.dart | 104 +- .../test/shared/flame_chart_test.dart | 854 +- .../test/shared/future_work_tracker_test.dart | 96 +- .../test/shared/home_screen_test.dart | 10 +- .../test/shared/import_export_test.dart | 33 +- .../test/shared/initializer_test.dart | 86 +- .../shared/json_to_service_cache_test.dart | 40 +- .../shared/linked_scroll_controller_test.dart | 57 +- .../test/shared/log_storage_test.dart | 108 +- .../shared/memory/retaining_path_test.dart | 33 +- .../test/shared/notifications_test.dart | 87 +- .../shared/preferences_controller_test.dart | 186 +- .../test/shared/primitives/encoding_test.dart | 11 +- .../test/shared/primitives/graph_test.dart | 9 +- .../test/shared/primitives/utils_test.dart | 296 +- .../test/shared/query_parameters_test.dart | 25 +- .../shared/resolved_uri_manager_test.dart | 57 +- .../test/shared/routing_test.dart | 12 +- .../test/shared/scaffold_debugger_test.dart | 36 +- .../scaffold_debugging_controls_test.dart | 118 +- .../test/shared/scaffold_no_app_test.dart | 28 +- .../test/shared/scaffold_profile_test.dart | 106 +- .../test/shared/scaffold_test.dart | 179 +- .../test/shared/screens_test.dart | 79 +- .../service_extension_widgets_test.dart | 165 +- .../test/shared/span_parser_test.dart | 26 +- .../test/shared/syntax_highlighter_test.dart | 794 +- .../devtools_app/test/shared/table_test.dart | 1965 +- .../test/shared/timeline_streams_test.dart | 46 +- .../test/shared/treemap_test.dart | 127 +- .../devtools_app/test/shared/trees_test.dart | 144 +- .../test/shared/ui_utils_test.dart | 108 +- .../test/shared/url_utils_test.dart | 10 +- .../devtools_app/test/shared/utils_test.dart | 89 +- .../test/shared/visible_screens_test.dart | 281 +- .../test/shared/vm_flag_widgets_test.dart | 91 +- .../test/shared/vm_flags_test.dart | 70 +- .../shared/widget_rebuild_counts_test.dart | 5 +- .../vs_code/debug_sessions_test.dart | 68 +- .../standalone_ui/vs_code/devtools_test.dart | 78 +- .../test/test_infra/flutter_test_driver.dart | 114 +- .../test_infra/flutter_test_environment.dart | 14 +- .../inspector_service_node_no_summary.txt | 20 +- .../inspector_service_tree_no_summary.txt | 20 +- ..._inspector_v2_hideable_widget_selected.png | Bin 60590 -> 60522 bytes ...2_hideable_widget_selected_from_search.png | Bin 60590 -> 60522 bytes ...tor_v2_implementation_widgets_expanded.png | Bin 57982 -> 57914 bytes .../string_interpolation.dart.golden | 50 +- .../test/test_infra/matchers/matchers.dart | 3 +- .../scenes/cpu_profiler/default.dart | 20 +- .../test/test_infra/scenes/hello.dart | 6 +- .../test_infra/scenes/memory/default.dart | 52 +- .../scenes/memory/diff_snapshot.dart | 4 +- .../scenes/scene_test_extensions.dart | 8 +- .../editor_service/simulated_editor.dart | 33 +- .../standalone_ui/mock_editor_widget.dart | 164 +- .../scenes/standalone_ui/utils.dart | 5 +- .../test_data/cpu_profiler/cpu_profile.dart | 351 +- .../cpu_profiler/simple_profile_1.dart | 50 +- .../cpu_profiler/simple_profile_2.dart | 50 +- .../debugger/vm_service_object_tree.dart | 49 +- .../test_data/deep_link/fake_responses.dart | 4 +- .../test_data/memory/heap/heap_data.dart | 29 +- .../memory/heap/heap_graph_fakes.dart | 31 +- .../memory/offline/memory_offline_data.dart | 66945 ++++++++-------- .../test/test_infra/test_data/network.dart | 12 +- .../performance/_perfetto_events_raw.dart | 45 +- .../performance/sample_performance_data.dart | 445 +- .../string_interpolation.dart | 16 +- .../test/test_infra/utils/debugger_utils.dart | 11 +- .../test_infra/utils/deep_links_utils.dart | 10 +- .../test_infra/utils/rendering_tester.dart | 14 +- .../test/test_infra/utils/sidebar_utils.dart | 3 +- .../test/test_infra/utils/test_utils.dart | 40 +- .../test/test_infra/utils/tree_utils.dart | 5 +- .../test/test_infra/utils/variable_utils.dart | 50 +- .../class_hierarchy_explorer_test.dart | 77 +- .../object_inspector_view_test.dart | 66 +- .../object_viewport_test.dart | 171 +- .../vm_class_display_test.dart | 58 +- .../vm_code_display_test.dart | 37 +- .../vm_developer_common_widgets_test.dart | 68 +- .../vm_field_display_test.dart | 135 +- .../vm_function_display_test.dart | 138 +- .../vm_ic_data_display_test.dart | 63 +- .../vm_library_display_test.dart | 102 +- .../vm_object_pool_display_test.dart | 104 +- .../vm_script_display_test.dart | 49 +- .../vm_simple_list_display_test.dart | 50 +- .../vm_developer/vm_developer_test_utils.dart | 81 +- .../test_driver/integration_test.dart | 5 +- .../lib/src/helpers/actions.dart | 11 +- .../devtools_test/lib/src/helpers/utils.dart | 39 +- .../lib/src/helpers/wrappers.dart | 34 +- .../integration_test_utils.dart | 18 +- .../lib/src/mocks/fake_isolate_manager.dart | 23 +- .../fake_program_explorer_controller.dart | 4 +- .../mocks/fake_service_extension_manager.dart | 30 +- .../lib/src/mocks/fake_service_manager.dart | 66 +- .../src/mocks/fake_vm_service_wrapper.dart | 104 +- .../src/mocks/generated_mocks_factories.dart | 138 +- .../devtools_test/lib/src/mocks/mocks.dart | 98 +- packages/devtools_test/pubspec.yaml | 4 +- tool/analysis_options.yaml | 3 +- tool/bin/dt.dart | 5 +- tool/cpu_sample_intervals.dart | 6 +- tool/json_to_map.dart | 25 +- tool/lib/commands/build.dart | 44 +- tool/lib/commands/fix_goldens.dart | 35 +- tool/lib/commands/generate_code.dart | 49 +- tool/lib/commands/pub_get.dart | 6 +- tool/lib/commands/release_helper.dart | 71 +- tool/lib/commands/release_notes_helper.dart | 52 +- tool/lib/commands/repo_check.dart | 14 +- tool/lib/commands/rollback.dart | 41 +- tool/lib/commands/serve.dart | 78 +- tool/lib/commands/shared.dart | 9 +- tool/lib/commands/sync.dart | 4 +- tool/lib/commands/tag_version.dart | 6 +- tool/lib/commands/update_dart_sdk_deps.dart | 17 +- tool/lib/commands/update_flutter_sdk.dart | 33 +- tool/lib/commands/update_perfetto.dart | 38 +- tool/lib/commands/update_version.dart | 58 +- tool/lib/devtools_command_runner.dart | 5 +- tool/lib/license_utils.dart | 31 +- tool/lib/model.dart | 4 +- tool/lib/utils.dart | 38 +- tool/pubspec.yaml | 2 +- tool/test/license_utils_test.dart | 155 +- 644 files changed, 56414 insertions(+), 60202 deletions(-) diff --git a/flutter-candidate.txt b/flutter-candidate.txt index 065cd8af8a3..95e8a02d8a2 100644 --- a/flutter-candidate.txt +++ b/flutter-candidate.txt @@ -1 +1 @@ -fe71cadf1959268ca5dd545863a195d78c232b74 +1d01955721fbb5a3cde5beb6e0a0216b457d35ae diff --git a/packages/analysis_options.yaml b/packages/analysis_options.yaml index d4021b8eb7e..7ec8e122e04 100644 --- a/packages/analysis_options.yaml +++ b/packages/analysis_options.yaml @@ -113,7 +113,8 @@ linter: - prefer_relative_imports - prefer_single_quotes - prefer_typing_uninitialized_variables - - require_trailing_commas + # Obsolete with the new Dart formatter. + # - require_trailing_commas - recursive_getters - slash_for_doc_comments - sort_child_properties_last @@ -224,7 +225,8 @@ dart_code_metrics: # - prefer-moving-to-variable: # allowed-duplicated-chains: 2 # - prefer-static-class - - prefer-trailing-comma + # Obsolete with the new Dart formatter. + # - prefer-trailing-comma - always-remove-listener # - avoid-border-all Micro-optimization to avoid a const constructor. # - avoid-returning-widgets This one is nice but has a lot of false positives. diff --git a/packages/devtools_app/benchmark/devtools_benchmarks_test.dart b/packages/devtools_app/benchmark/devtools_benchmarks_test.dart index 1f901430235..1d5111fbda8 100644 --- a/packages/devtools_app/benchmark/devtools_benchmarks_test.dart +++ b/packages/devtools_app/benchmark/devtools_benchmarks_test.dart @@ -18,10 +18,7 @@ import 'test_infra/project_root_directory.dart'; const _isWasmScore = 'isWasm'; -const _extraScores = [ - totalUiFrameAverage, - _isWasmScore, -]; +const _extraScores = [totalUiFrameAverage, _isWasmScore]; /// Tests that the DevTools web benchmarks are run and reported correctly. void main() { @@ -43,23 +40,22 @@ Future _runBenchmarks({bool useWasm = false}) async { final taskResult = await serveWebBenchmark( benchmarkAppDirectory: projectRootDirectory(), entryPoint: generateBenchmarkEntryPoint(useWasm: useWasm), - compilationOptions: useWasm - ? const CompilationOptions.wasm() - : const CompilationOptions.js(), + compilationOptions: + useWasm + ? const CompilationOptions.wasm() + : const CompilationOptions.js(), treeShakeIcons: false, benchmarkPath: benchmarkPath(useWasm: useWasm), ); stdout.writeln('Web benchmark tests finished.'); - expect( - taskResult.scores.keys, - hasLength(DevToolsBenchmark.values.length), - ); + expect(taskResult.scores.keys, hasLength(DevToolsBenchmark.values.length)); for (final benchmarkName in DevToolsBenchmark.values.map((e) => e.id)) { - final expectedMetrics = expectedBenchmarkMetrics(useWasm: useWasm) - .map((BenchmarkMetric metric) => metric.label) - .toList(); + final expectedMetrics = + expectedBenchmarkMetrics( + useWasm: useWasm, + ).map((BenchmarkMetric metric) => metric.label).toList(); const expectedComputations = BenchmarkMetricComputation.values; final scores = taskResult.scores[benchmarkName] ?? []; expect( diff --git a/packages/devtools_app/benchmark/scripts/args.dart b/packages/devtools_app/benchmark/scripts/args.dart index ae699cfa74e..cf007a3960c 100644 --- a/packages/devtools_app/benchmark/scripts/args.dart +++ b/packages/devtools_app/benchmark/scripts/args.dart @@ -29,7 +29,8 @@ extension BenchmarkArgsExtension on ArgParser { void addSaveToFileOption(BenchmarkResultsOutputType type) { addOption( BenchmarkArgument.saveToFile.flagName, - help: 'Saves the benchmark results to a ${type.name} file at the ' + help: + 'Saves the benchmark results to a ${type.name} file at the ' 'provided path (absolute).', valueHelp: '/Users/me/Downloads/output.${type.name}', ); @@ -39,7 +40,8 @@ extension BenchmarkArgsExtension on ArgParser { addOption( BenchmarkArgument.averageOf.flagName, defaultsTo: '1', - help: 'The number of times to run the benchmark. The returned results ' + help: + 'The number of times to run the benchmark. The returned results ' 'will be the average of all the benchmark runs when this value is ' 'greater than 1.', valueHelp: '5', @@ -49,7 +51,8 @@ extension BenchmarkArgsExtension on ArgParser { void addBaselineOption({String? additionalHelp}) { addOption( BenchmarkArgument.baseline.flagName, - help: 'The baseline benchmark data to compare the test benchmark run to. ' + help: + 'The baseline benchmark data to compare the test benchmark run to. ' '${additionalHelp ?? ''}', valueHelp: '/Users/me/Downloads/baseline.json', ); @@ -73,7 +76,4 @@ enum BenchmarkArgument { } /// The file types that benchmark results may be written to. -enum BenchmarkResultsOutputType { - csv, - json, -} +enum BenchmarkResultsOutputType { csv, json } diff --git a/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart b/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart index 515132a1d1d..02369fe7471 100644 --- a/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart +++ b/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart @@ -38,10 +38,12 @@ void main(List args) { } } - final baselineResults = - BenchmarkResults.parse(jsonDecode(baselineFile.readAsStringSync())); - final testResults = - BenchmarkResults.parse(jsonDecode(testFile.readAsStringSync())); + final baselineResults = BenchmarkResults.parse( + jsonDecode(baselineFile.readAsStringSync()), + ); + final testResults = BenchmarkResults.parse( + jsonDecode(testFile.readAsStringSync()), + ); compareBenchmarks( baselineResults, testResults, diff --git a/packages/devtools_app/benchmark/scripts/dart2wasm_performance_diff.dart b/packages/devtools_app/benchmark/scripts/dart2wasm_performance_diff.dart index 3aa2f3cf727..f539d9ff41c 100644 --- a/packages/devtools_app/benchmark/scripts/dart2wasm_performance_diff.dart +++ b/packages/devtools_app/benchmark/scripts/dart2wasm_performance_diff.dart @@ -88,7 +88,7 @@ void main(List args) async { class CsvBuilder { CsvBuilder({this.saveToLocation}) - : assert(saveToLocation == null || saveToLocation.endsWith('.csv')); + : assert(saveToLocation == null || saveToLocation.endsWith('.csv')); final _sb = StringBuffer(); @@ -108,26 +108,22 @@ class CsvBuilder { // TODO(kenz): automatically detect these and write them to the CSV. const flutter = ''; const devtools = ''; - writeLines( - [ - 'Version info:', - 'Flutter: $flutter', - 'DevTools: $devtools', - '', - 'Results:', - ], - ); + writeLines([ + 'Version info:', + 'Flutter: $flutter', + 'DevTools: $devtools', + '', + 'Results:', + ]); // Write the headers. - writeLine( - [ - 'Benchmark Name', - 'Metric', - 'Value (micros)', - 'Delta (micros)', - 'Delta (%)', - ], - ); + writeLine([ + 'Benchmark Name', + 'Metric', + 'Value (micros)', + 'Delta (micros)', + 'Delta (%)', + ]); } void writeLine(List content) { @@ -157,11 +153,7 @@ class CsvBuilder { final downloadsDir = Directory.fromUri( Uri.parse( // We need the leading slash so that this is an absolute path. - '/${p.join( - currentDirectoryParts[0], - currentDirectoryParts[1], - 'Downloads', - )}', + '/${p.join(currentDirectoryParts[0], currentDirectoryParts[1], 'Downloads')}', ), ); if (downloadsDir.existsSync()) { @@ -233,7 +225,8 @@ class _Args extends BenchmarkArgsBase { ) ..addOption( BenchmarkArgument.test.flagName, - help: 'The test benchmark data (dart2wasm) to use for this performance' + help: + 'The test benchmark data (dart2wasm) to use for this performance' ' diff. When specified, this script will use the benchmark data at ' 'the specified path instead of generating a new benchmark run for ' 'the dart2wasm data. This file path should point to a JSON file that ' diff --git a/packages/devtools_app/benchmark/scripts/run_benchmarks.dart b/packages/devtools_app/benchmark/scripts/run_benchmarks.dart index e2c463f4934..ef556eaf37b 100644 --- a/packages/devtools_app/benchmark/scripts/run_benchmarks.dart +++ b/packages/devtools_app/benchmark/scripts/run_benchmarks.dart @@ -56,9 +56,10 @@ Future runBenchmarks({ await serveWebBenchmark( benchmarkAppDirectory: projectRootDirectory(), entryPoint: generateBenchmarkEntryPoint(useWasm: useWasm), - compilationOptions: useWasm - ? const CompilationOptions.wasm() - : const CompilationOptions.js(), + compilationOptions: + useWasm + ? const CompilationOptions.wasm() + : const CompilationOptions.js(), treeShakeIcons: false, benchmarkPath: benchmarkPath(useWasm: useWasm), headless: !useBrowser, @@ -86,8 +87,9 @@ void printAndMaybeSaveResults({ required String? saveToFileLocation, }) { final resultsAsMap = benchmarkResults.toJson(); - final resultsAsJsonString = - const JsonEncoder.withIndent(' ').convert(resultsAsMap); + final resultsAsJsonString = const JsonEncoder.withIndent( + ' ', + ).convert(resultsAsMap); if (saveToFileLocation != null) { final location = Uri.parse(saveToFileLocation); diff --git a/packages/devtools_app/benchmark/test_infra/client/client_shared.dart b/packages/devtools_app/benchmark/test_infra/client/client_shared.dart index 66e86a76d0f..4e584d913b8 100644 --- a/packages/devtools_app/benchmark/test_infra/client/client_shared.dart +++ b/packages/devtools_app/benchmark/test_infra/client/client_shared.dart @@ -10,13 +10,16 @@ import '../devtools_recorder.dart'; typedef RecorderFactory = Recorder Function(); final benchmarks = { - DevToolsBenchmark.navigateThroughOfflineScreens.id: () => DevToolsRecorder( + DevToolsBenchmark.navigateThroughOfflineScreens.id: + () => DevToolsRecorder( benchmark: DevToolsBenchmark.navigateThroughOfflineScreens, ), - DevToolsBenchmark.offlineCpuProfilerScreen.id: () => DevToolsRecorder( + DevToolsBenchmark.offlineCpuProfilerScreen.id: + () => DevToolsRecorder( benchmark: DevToolsBenchmark.offlineCpuProfilerScreen, ), - DevToolsBenchmark.offlinePerformanceScreen.id: () => DevToolsRecorder( + DevToolsBenchmark.offlinePerformanceScreen.id: + () => DevToolsRecorder( benchmark: DevToolsBenchmark.offlinePerformanceScreen, ), }; diff --git a/packages/devtools_app/benchmark/test_infra/common.dart b/packages/devtools_app/benchmark/test_infra/common.dart index 939d881efaa..856905d35b3 100644 --- a/packages/devtools_app/benchmark/test_infra/common.dart +++ b/packages/devtools_app/benchmark/test_infra/common.dart @@ -12,7 +12,8 @@ const _benchmarkInitialPage = ''; const _wasmQueryParameters = {'wasm': 'true'}; -String benchmarkPath({required bool useWasm}) => Uri( +String benchmarkPath({required bool useWasm}) => + Uri( path: _benchmarkInitialPage, queryParameters: useWasm ? _wasmQueryParameters : null, ).toString(); diff --git a/packages/devtools_app/benchmark/test_infra/devtools_recorder.dart b/packages/devtools_app/benchmark/test_infra/devtools_recorder.dart index 7a5d178ff8b..34aba855e5d 100644 --- a/packages/devtools_app/benchmark/test_infra/devtools_recorder.dart +++ b/packages/devtools_app/benchmark/test_infra/devtools_recorder.dart @@ -14,7 +14,7 @@ import 'common.dart'; /// A recorder that measures frame building durations for the DevTools. class DevToolsRecorder extends WidgetRecorder { DevToolsRecorder({required this.benchmark}) - : super(name: benchmark.id, useCustomWarmUp: true); + : super(name: benchmark.id, useCustomWarmUp: true); /// The name of the DevTools benchmark to be run. /// diff --git a/packages/devtools_app/benchmark/test_infra/project_root_directory.dart b/packages/devtools_app/benchmark/test_infra/project_root_directory.dart index 968cd23ed02..ee0f8c4aadb 100644 --- a/packages/devtools_app/benchmark/test_infra/project_root_directory.dart +++ b/packages/devtools_app/benchmark/test_infra/project_root_directory.dart @@ -10,10 +10,10 @@ import 'package:path/path.dart' as path; bool _hasPubspec(Directory directory) { return directory.listSync().any( - (entity) => - FileSystemEntity.isFileSync(entity.path) && - path.basename(entity.path) == 'pubspec.yaml', - ); + (entity) => + FileSystemEntity.isFileSync(entity.path) && + path.basename(entity.path) == 'pubspec.yaml', + ); } Directory projectRootDirectory() { diff --git a/packages/devtools_app/benchmark/web_bundle_size_test.dart b/packages/devtools_app/benchmark/web_bundle_size_test.dart index 4cd93fccbd4..31029ee4f9d 100644 --- a/packages/devtools_app/benchmark/web_bundle_size_test.dart +++ b/packages/devtools_app/benchmark/web_bundle_size_test.dart @@ -12,62 +12,58 @@ import 'package:test/test.dart'; // Benchmark size in kB. const bundleSizeBenchmark = 5200; -const gzipBundleSizeBenchmark = 1500; +const gzipBundleSizeBenchmark = 1550; void main() { group('Web Compile', () { - test( - 'bundle size', - () async { - final js = path.join( - Directory.current.path, - 'build', - 'web', - 'main.dart.js', - ); + test('bundle size', () async { + final js = path.join( + Directory.current.path, + 'build', + 'web', + 'main.dart.js', + ); - _logStatus('Building DevTools web app in release mode...'); - // These build arguments match the arguments used in the - // tool/lib/commands/build_release.dart command, which is how we build - // DevTools for release. - await _runProcess('flutter', [ - 'build', - 'web', - '--web-renderer', - 'canvaskit', - '--pwa-strategy=offline-first', - '--release', - '--no-tree-shake-icons', - ]); + _logStatus('Building DevTools web app in release mode...'); + // These build arguments match the arguments used in the + // tool/lib/commands/build_release.dart command, which is how we build + // DevTools for release. + await _runProcess('flutter', [ + 'build', + 'web', + '--web-renderer', + 'canvaskit', + '--pwa-strategy=offline-first', + '--release', + '--no-tree-shake-icons', + ]); - _logStatus('Zipping bundle with gzip...'); - await _runProcess('gzip', ['-k', '-f', js]); + _logStatus('Zipping bundle with gzip...'); + await _runProcess('gzip', ['-k', '-f', js]); - final bundleSize = await _measureSize(js); - final gzipBundleSize = await _measureSize('$js.gz'); - if (bundleSize > bundleSizeBenchmark) { - fail( - 'The size the compiled web build "$js" was $bundleSize kB. This is ' - 'larger than the benchmark that was set at $bundleSizeBenchmark kB.' - '\n\n' - 'The build size should be as minimal as possible to reduce the web ' - 'app\'s initial startup time. If this change is intentional, and' - ' expected, please increase the constant "bundleSizeBenchmark".', - ); - } else if (gzipBundleSize > gzipBundleSizeBenchmark) { - fail( - 'The size the compiled and gzipped web build "$js" was' - ' $gzipBundleSize kB. This is larger than the benchmark that was ' - 'set at $gzipBundleSizeBenchmark kB.\n\n' - 'The build size should be as minimal as possible to reduce the ' - 'web app\'s initial startup time. If this change is intentional, ' - 'and expected, please increase the constant ' - '"gzipBundleSizeBenchmark".', - ); - } - }, - timeout: const Timeout(Duration(minutes: 5)), - ); + final bundleSize = await _measureSize(js); + final gzipBundleSize = await _measureSize('$js.gz'); + if (bundleSize > bundleSizeBenchmark) { + fail( + 'The size the compiled web build "$js" was $bundleSize kB. This is ' + 'larger than the benchmark that was set at $bundleSizeBenchmark kB.' + '\n\n' + 'The build size should be as minimal as possible to reduce the web ' + 'app\'s initial startup time. If this change is intentional, and' + ' expected, please increase the constant "bundleSizeBenchmark".', + ); + } else if (gzipBundleSize > gzipBundleSizeBenchmark) { + fail( + 'The size the compiled and gzipped web build "$js" was' + ' $gzipBundleSize kB. This is larger than the benchmark that was ' + 'set at $gzipBundleSizeBenchmark kB.\n\n' + 'The build size should be as minimal as possible to reduce the ' + 'web app\'s initial startup time. If this change is intentional, ' + 'and expected, please increase the constant ' + '"gzipBundleSizeBenchmark".', + ); + } + }, timeout: const Timeout(Duration(minutes: 5))); }); } diff --git a/packages/devtools_app/integration_test/run_tests.dart b/packages/devtools_app/integration_test/run_tests.dart index df7ec9aefe6..e22a58f3a52 100644 --- a/packages/devtools_app/integration_test/run_tests.dart +++ b/packages/devtools_app/integration_test/run_tests.dart @@ -55,22 +55,22 @@ void main(List args) async { testRunnerArgs: testRunnerArgs, runTest: _runTest, newArgsGenerator: (args) => DevToolsAppTestRunnerArgs(args), - testIsSupported: (testFile) => - testRunnerArgs.testAppDevice.supportsTest(testFile.path), + testIsSupported: + (testFile) => testRunnerArgs.testAppDevice.supportsTest(testFile.path), debugLogging: debugTestScript, ); } -Future _runTest( - DevToolsAppTestRunnerArgs testRunnerArgs, -) async { +Future _runTest(DevToolsAppTestRunnerArgs testRunnerArgs) async { final testTarget = testRunnerArgs.testTarget!; final testDevice = testRunnerArgs.testAppDevice.name; final disabledForAllDevices = _disabledTestsForDevice[_testDeviceAll]!; final disabledForDevice = _disabledTestsForDevice[testDevice] ?? {}; - final disabled = {...disabledForAllDevices, ...disabledForDevice} - .any((t) => testTarget.endsWith(t)); + final disabled = { + ...disabledForAllDevices, + ...disabledForDevice, + }.any((t) => testTarget.endsWith(t)); if (disabled) { debugLog('Disabled test - skipping $testTarget for $testDevice.'); return; diff --git a/packages/devtools_app/integration_test/test/live_connection/debugger_panel_test.dart b/packages/devtools_app/integration_test/test/live_connection/debugger_panel_test.dart index 0035177cfcd..b2978864259 100644 --- a/packages/devtools_app/integration_test/test/live_connection/debugger_panel_test.dart +++ b/packages/devtools_app/integration_test/test/live_connection/debugger_panel_test.dart @@ -78,11 +78,7 @@ void main() { // Verify that the gutter item and line item are aligned: expect( - areHorizontallyAligned( - gutter57Finder, - line57Finder, - tester: tester, - ), + areHorizontallyAligned(gutter57Finder, line57Finder, tester: tester), isTrue, ); @@ -113,11 +109,7 @@ void main() { // Verify that the gutter item and line item are aligned: expect( - areHorizontallyAligned( - gutter30Finder, - line30Finder, - tester: tester, - ), + areHorizontallyAligned(gutter30Finder, line30Finder, tester: tester), isTrue, ); @@ -177,11 +169,7 @@ void main() { // Verify that the gutter item and line item are aligned: expect( - areHorizontallyAligned( - gutter46Finder, - line46Finder, - tester: tester, - ), + areHorizontallyAligned(gutter46Finder, line46Finder, tester: tester), isTrue, ); @@ -229,14 +217,12 @@ T getWidgetFromFinder(Finder finder) => finder.first.evaluate().first.widget as T; Finder findLineItemWithText(String text) => find.ancestor( - of: find.textContaining(text), - matching: find.byType(LineItem), - ); + of: find.textContaining(text), + matching: find.byType(LineItem), +); -Finder findGutterItemWithText(String text) => find.ancestor( - of: find.text(text), - matching: find.byType(GutterItem), - ); +Finder findGutterItemWithText(String text) => + find.ancestor(of: find.text(text), matching: find.byType(GutterItem)); bool isLineFocused(Finder lineItemFinder) { final lineWidget = getWidgetFromFinder(lineItemFinder); @@ -244,11 +230,11 @@ bool isLineFocused(Finder lineItemFinder) { } Finder findStackFrameWithText(String text) => find.descendant( - of: find.byType(CallStack), - matching: find.richTextContaining(text), - ); + of: find.byType(CallStack), + matching: find.richTextContaining(text), +); Finder findBreakpointWithText(String text) => find.descendant( - of: find.byType(Breakpoints), - matching: find.richTextContaining(text), - ); + of: find.byType(Breakpoints), + matching: find.richTextContaining(text), +); diff --git a/packages/devtools_app/integration_test/test/live_connection/devtools_extensions_test.dart b/packages/devtools_app/integration_test/test/live_connection/devtools_extensions_test.dart index 728e79f28a6..8dbc10bc1ca 100644 --- a/packages/devtools_app/integration_test/test/live_connection/devtools_extensions_test.dart +++ b/packages/devtools_app/integration_test/test/live_connection/devtools_extensions_test.dart @@ -45,30 +45,23 @@ void main() { ); expect(extensionService.availableExtensions.length, 3); expect(extensionService.visibleExtensions.length, 3); - await _verifyExtensionsSettingsMenu( - tester, - [ - ExtensionEnabledState.none, // bar - ExtensionEnabledState.none, // baz - ExtensionEnabledState.none, // foo - ], - ); + await _verifyExtensionsSettingsMenu(tester, [ + ExtensionEnabledState.none, // bar + ExtensionEnabledState.none, // baz + ExtensionEnabledState.none, // foo + ]); await connectToTestApp(tester, testApp); expect(extensionService.availableExtensions.length, 5); expect(extensionService.visibleExtensions.length, 5); - await _verifyExtensionsSettingsMenu( - tester, - [ - ExtensionEnabledState.none, // bar - ExtensionEnabledState.none, // baz - ExtensionEnabledState.none, // foo - ExtensionEnabledState.none, // provider - ExtensionEnabledState.none, // some_tool - ], - closeMenuWhenDone: false, - ); + await _verifyExtensionsSettingsMenu(tester, [ + ExtensionEnabledState.none, // bar + ExtensionEnabledState.none, // baz + ExtensionEnabledState.none, // foo + ExtensionEnabledState.none, // provider + ExtensionEnabledState.none, // some_tool + ], closeMenuWhenDone: false); await _verifyExtensionVisibilitySetting(tester); @@ -80,16 +73,13 @@ void main() { initialLoad: true, ); await _answerEnableExtensionPrompt(tester, enable: true); - await _verifyExtensionsSettingsMenu( - tester, - [ - ExtensionEnabledState.enabled, // bar - ExtensionEnabledState.none, // baz - ExtensionEnabledState.none, // foo - ExtensionEnabledState.none, // provider - ExtensionEnabledState.none, // some_tool - ], - ); + await _verifyExtensionsSettingsMenu(tester, [ + ExtensionEnabledState.enabled, // bar + ExtensionEnabledState.none, // baz + ExtensionEnabledState.none, // foo + ExtensionEnabledState.none, // provider + ExtensionEnabledState.none, // some_tool + ]); await _verifyContextMenuActionsAndDisable(tester); @@ -100,16 +90,13 @@ void main() { extensionIndex: 0, visible: false, ); - await _verifyExtensionsSettingsMenu( - tester, - [ - ExtensionEnabledState.disabled, // bar - ExtensionEnabledState.none, // baz - ExtensionEnabledState.none, // foo - ExtensionEnabledState.none, // provider - ExtensionEnabledState.none, // some_tool - ], - ); + await _verifyExtensionsSettingsMenu(tester, [ + ExtensionEnabledState.disabled, // bar + ExtensionEnabledState.none, // baz + ExtensionEnabledState.none, // foo + ExtensionEnabledState.none, // provider + ExtensionEnabledState.none, // some_tool + ]); // Baz extension. Hide immediately. await _switchToExtensionScreen( @@ -126,16 +113,13 @@ void main() { extensionIndex: 1, visible: false, ); - await _verifyExtensionsSettingsMenu( - tester, - [ - ExtensionEnabledState.disabled, // bar - ExtensionEnabledState.disabled, // baz - ExtensionEnabledState.none, // foo - ExtensionEnabledState.none, // provider - ExtensionEnabledState.none, // some_tool - ], - ); + await _verifyExtensionsSettingsMenu(tester, [ + ExtensionEnabledState.disabled, // bar + ExtensionEnabledState.disabled, // baz + ExtensionEnabledState.none, // foo + ExtensionEnabledState.none, // provider + ExtensionEnabledState.none, // some_tool + ]); // Re-enable Baz extension from the extensions settings menu. logStatus('verify we can re-enable an extension from the settings menu'); @@ -147,16 +131,13 @@ void main() { expect(find.byType(EnableExtensionPrompt), findsNothing); expect(find.byType(EmbeddedExtensionView), findsOneWidget); expect(find.byType(HtmlElementView), findsOneWidget); - await _verifyExtensionsSettingsMenu( - tester, - [ - ExtensionEnabledState.disabled, // bar - ExtensionEnabledState.enabled, // baz - ExtensionEnabledState.none, // foo - ExtensionEnabledState.none, // provider - ExtensionEnabledState.none, // some_tool - ], - ); + await _verifyExtensionsSettingsMenu(tester, [ + ExtensionEnabledState.disabled, // bar + ExtensionEnabledState.enabled, // baz + ExtensionEnabledState.none, // foo + ExtensionEnabledState.none, // provider + ExtensionEnabledState.none, // some_tool + ]); // Foo extension. Disable directly from settings menu. logStatus( @@ -177,16 +158,13 @@ void main() { extensionIndex: 2, visible: false, ); - await _verifyExtensionsSettingsMenu( - tester, - [ - ExtensionEnabledState.disabled, // bar - ExtensionEnabledState.enabled, // baz - ExtensionEnabledState.disabled, // foo - ExtensionEnabledState.none, // provider - ExtensionEnabledState.none, // some_tool - ], - ); + await _verifyExtensionsSettingsMenu(tester, [ + ExtensionEnabledState.disabled, // bar + ExtensionEnabledState.enabled, // baz + ExtensionEnabledState.disabled, // foo + ExtensionEnabledState.none, // provider + ExtensionEnabledState.none, // some_tool + ]); }); } @@ -251,10 +229,7 @@ Future _answerEnableExtensionPrompt( find.byType(EmbeddedExtensionView), enable ? findsOneWidget : findsNothing, ); - expect( - find.byType(HtmlElementView), - enable ? findsOneWidget : findsNothing, - ); + expect(find.byType(HtmlElementView), enable ? findsOneWidget : findsNothing); } Future _verifyContextMenuActionsAndDisable(WidgetTester tester) async { @@ -293,10 +268,11 @@ Future _verifyExtensionsSettingsMenu( await _openExtensionSettingsMenu(tester); expect(find.byType(ExtensionSetting), findsNWidgets(enabledStates.length)); - final toggleButtonGroups = tester - .widgetList(find.byType(DevToolsToggleButtonGroup)) - .cast() - .toList(); + final toggleButtonGroups = + tester + .widgetList(find.byType(DevToolsToggleButtonGroup)) + .cast() + .toList(); for (int i = 0; i < toggleButtonGroups.length; i++) { logStatus('verify extension settings toggle button states (index $i)'); final group = toggleButtonGroups[i]; @@ -337,10 +313,11 @@ Future _changeExtensionSetting( 'changing the extension setting at index $extensionIndex to value $settingValue', ); await _openExtensionSettingsMenu(tester); - final extensionSetting = tester - .widgetList(find.byType(DevToolsToggleButtonGroup)) - .cast() - .toList()[extensionIndex]; + final extensionSetting = + tester + .widgetList(find.byType(DevToolsToggleButtonGroup)) + .cast() + .toList()[extensionIndex]; await tester.tap( find.descendant( of: find.byWidget(extensionSetting), diff --git a/packages/devtools_app/integration_test/test/live_connection/eval_and_browse_test.dart b/packages/devtools_app/integration_test/test/live_connection/eval_and_browse_test.dart index ecabad1d9da..5678d455d38 100644 --- a/packages/devtools_app/integration_test/test/live_connection/eval_and_browse_test.dart +++ b/packages/devtools_app/integration_test/test/live_connection/eval_and_browse_test.dart @@ -86,17 +86,11 @@ Future _inboundReferencesAreListed(EvalTester tester) async { find.textContaining('MyApp, retained size '), next: find.text('references'), ); - next = await tester.tapAndPump( - next!, - next: find.textContaining('static ('), - ); + next = await tester.tapAndPump(next!, next: find.textContaining('static (')); next = await tester.tapAndPump( next!, description: 'text containing "static ("', next: find.text('inbound'), ); - next = await tester.tapAndPump( - next!, - next: find.text('View'), - ); + next = await tester.tapAndPump(next!, next: find.text('View')); } diff --git a/packages/devtools_app/integration_test/test/live_connection/memory_screen_helpers.dart b/packages/devtools_app/integration_test/test/live_connection/memory_screen_helpers.dart index fa32d982e73..7fc53ef7c80 100644 --- a/packages/devtools_app/integration_test/test/live_connection/memory_screen_helpers.dart +++ b/packages/devtools_app/integration_test/test/live_connection/memory_screen_helpers.dart @@ -57,9 +57,7 @@ Future prepareMemoryUI( } } -Future takeHeapSnapshot( - WidgetTester tester, -) async { +Future takeHeapSnapshot(WidgetTester tester) async { logStatus('Started taking snapshot.'); // Take snapshot. const snapshotDuration = Duration(seconds: 20); diff --git a/packages/devtools_app/integration_test/test/live_connection/performance_screen_event_recording_test.dart b/packages/devtools_app/integration_test/test/live_connection/performance_screen_event_recording_test.dart index dcc82cb440b..fc2841f8007 100644 --- a/packages/devtools_app/integration_test/test/live_connection/performance_screen_event_recording_test.dart +++ b/packages/devtools_app/integration_test/test/live_connection/performance_screen_event_recording_test.dart @@ -24,88 +24,96 @@ void main() { expect(testApp.vmServiceUri, isNotNull); }); - testWidgets( - 'can process and refresh timeline data', - (tester) async { - await pumpAndConnectDevTools(tester, testApp); - - logStatus( - 'Open the Performance screen and switch to the Timeline Events tab', - ); - - await switchToScreen( - tester, - tabIcon: ScreenMetaData.performance.icon, - tabIconAsset: ScreenMetaData.performance.iconAsset, - screenId: ScreenMetaData.performance.id, - ); - await tester.pump(safePumpDuration); - - await tester.tap(find.widgetWithText(InkWell, 'Timeline Events')); - await tester.pumpAndSettle(longPumpDuration); - - // Find the [PerformanceController] to access its data. - final performanceScreenFinder = find.byType(PerformanceScreenBody); - expect(performanceScreenFinder, findsOneWidget); - final screenState = - tester.state(performanceScreenFinder); - final performanceController = screenState.controller; - - logStatus('Verifying that data is processed upon first load'); - final initialTrace = Trace.fromBuffer( - performanceController.timelineEventsController.fullPerfettoTrace, - ); - final initialTracePacket = List.of(initialTrace.packet, growable: false); - final initialTrackDescriptors = - initialTracePacket.where((e) => e.hasTrackDescriptor()); - expect(initialTracePacket, isNotEmpty); - expect(initialTrackDescriptors, isNotEmpty); - - final trackEvents = initialTracePacket.where((e) => e.hasTrackEvent()); - expect(trackEvents, isNotEmpty); - - expect( - performanceController - .timelineEventsController.perfettoController.processor.uiTrackId, - isNotNull, - reason: 'Expected uiTrackId to be non-null', - ); - expect( - performanceController.timelineEventsController.perfettoController - .processor.rasterTrackId, - isNotNull, - reason: 'Expected rasterTrackId to be non-null', - ); - expect( - performanceController.timelineEventsController.perfettoController - .processor.frameRangeFromTimelineEvents, - isNotNull, - reason: 'Expected frameRangeFromTimelineEvents to be non-null', - ); - - logStatus( - 'toggling the Performance Overlay to trigger new Flutter frames', - ); - final performanceOverlayFinder = find.text('Performance Overlay'); - expect(performanceOverlayFinder, findsOneWidget); - await tester.tap(performanceOverlayFinder); - await tester.pump(longPumpDuration); - - logStatus('Refreshing the timeline to load new events'); - await tester.tap(find.byType(RefreshTimelineEventsButton)); - await tester.pump(longPumpDuration); - - logStatus('Verifying that we have recorded new events'); - final refreshedTrace = Trace.fromBuffer( - performanceController.timelineEventsController.fullPerfettoTrace, - ); - final refreshedTracePacket = - List.of(refreshedTrace.packet, growable: false); - expect( - refreshedTracePacket.length, - greaterThan(initialTracePacket.length), - reason: 'Expected new events to have been recorded, but none were.', - ); - }, - ); + testWidgets('can process and refresh timeline data', (tester) async { + await pumpAndConnectDevTools(tester, testApp); + + logStatus( + 'Open the Performance screen and switch to the Timeline Events tab', + ); + + await switchToScreen( + tester, + tabIcon: ScreenMetaData.performance.icon, + tabIconAsset: ScreenMetaData.performance.iconAsset, + screenId: ScreenMetaData.performance.id, + ); + await tester.pump(safePumpDuration); + + await tester.tap(find.widgetWithText(InkWell, 'Timeline Events')); + await tester.pumpAndSettle(longPumpDuration); + + // Find the [PerformanceController] to access its data. + final performanceScreenFinder = find.byType(PerformanceScreenBody); + expect(performanceScreenFinder, findsOneWidget); + final screenState = tester.state( + performanceScreenFinder, + ); + final performanceController = screenState.controller; + + logStatus('Verifying that data is processed upon first load'); + final initialTrace = Trace.fromBuffer( + performanceController.timelineEventsController.fullPerfettoTrace, + ); + final initialTracePacket = List.of(initialTrace.packet, growable: false); + final initialTrackDescriptors = initialTracePacket.where( + (e) => e.hasTrackDescriptor(), + ); + expect(initialTracePacket, isNotEmpty); + expect(initialTrackDescriptors, isNotEmpty); + + final trackEvents = initialTracePacket.where((e) => e.hasTrackEvent()); + expect(trackEvents, isNotEmpty); + + expect( + performanceController + .timelineEventsController + .perfettoController + .processor + .uiTrackId, + isNotNull, + reason: 'Expected uiTrackId to be non-null', + ); + expect( + performanceController + .timelineEventsController + .perfettoController + .processor + .rasterTrackId, + isNotNull, + reason: 'Expected rasterTrackId to be non-null', + ); + expect( + performanceController + .timelineEventsController + .perfettoController + .processor + .frameRangeFromTimelineEvents, + isNotNull, + reason: 'Expected frameRangeFromTimelineEvents to be non-null', + ); + + logStatus('toggling the Performance Overlay to trigger new Flutter frames'); + final performanceOverlayFinder = find.text('Performance Overlay'); + expect(performanceOverlayFinder, findsOneWidget); + await tester.tap(performanceOverlayFinder); + await tester.pump(longPumpDuration); + + logStatus('Refreshing the timeline to load new events'); + await tester.tap(find.byType(RefreshTimelineEventsButton)); + await tester.pump(longPumpDuration); + + logStatus('Verifying that we have recorded new events'); + final refreshedTrace = Trace.fromBuffer( + performanceController.timelineEventsController.fullPerfettoTrace, + ); + final refreshedTracePacket = List.of( + refreshedTrace.packet, + growable: false, + ); + expect( + refreshedTracePacket.length, + greaterThan(initialTracePacket.length), + reason: 'Expected new events to have been recorded, but none were.', + ); + }); } diff --git a/packages/devtools_app/integration_test/test/live_connection/service_connection_test.dart b/packages/devtools_app/integration_test/test/live_connection/service_connection_test.dart index d24793dbb61..e60c1eb3fba 100644 --- a/packages/devtools_app/integration_test/test/live_connection/service_connection_test.dart +++ b/packages/devtools_app/integration_test/test/live_connection/service_connection_test.dart @@ -47,7 +47,8 @@ void main() { // that are unintentionally added at start up. const Range(35, 70).contains(vmServiceCallCount), isTrue, - reason: 'Unexpected number of vm service calls upon connection: ' + reason: + 'Unexpected number of vm service calls upon connection: ' '$vmServiceCallCount. If this is expected, please update this test ' 'to the new expected number of calls. Here are the calls for this ' 'test run:\n ${serviceConnection.serviceManager.service!.vmServiceCalls.toString()}', @@ -71,7 +72,8 @@ void main() { 'getDartDevelopmentServiceVersion', 'getVM', ]), - reason: 'Unexpected order of vm service calls upon connection. ' + reason: + 'Unexpected order of vm service calls upon connection. ' 'Here are the calls for this test run:\n ' '${serviceConnection.serviceManager.service!.vmServiceCalls.toString()}', ); diff --git a/packages/devtools_app/integration_test/test/live_connection/service_extensions_test.dart b/packages/devtools_app/integration_test/test/live_connection/service_extensions_test.dart index 9b89f4734aa..5cfaae80540 100644 --- a/packages/devtools_app/integration_test/test/live_connection/service_extensions_test.dart +++ b/packages/devtools_app/integration_test/test/live_connection/service_extensions_test.dart @@ -61,10 +61,7 @@ void main() { await _verifyStringExtension(tester); logStatus('verify Flutter engine service extensions'); - expect( - await serviceConnection.queryDisplayRefreshRate, - equals(60), - ); + expect(await serviceConnection.queryDisplayRefreshRate, equals(60)); logStatus('verify services that are registered to exactly one client'); await _verifyHotReloadAndHotRestart(); @@ -96,11 +93,7 @@ void main() { // Enable a service extension of each type (boolean, numeric, string). for (final ext in serviceExtensionsToEnable) { await serviceConnection.serviceManager.serviceExtensionManager - .setServiceExtensionState( - ext.$1, - enabled: true, - value: ext.$2, - ); + .setServiceExtensionState(ext.$1, enabled: true, value: ext.$2); } logStatus('disconnecting from the test device'); @@ -264,11 +257,7 @@ Future _verifyExtension( // Enable the service extension state from the service manager. await serviceConnection.serviceManager.serviceExtensionManager - .setServiceExtensionState( - extensionName, - enabled: true, - value: newValue, - ); + .setServiceExtensionState(extensionName, enabled: true, value: newValue); await _verifyExtensionStateOnTestDevice( evalExpression: evalExpression, @@ -302,8 +291,9 @@ Future _changeServiceExtensionFromButton( required (bool, Object?) expectedResultInServiceManager, required WidgetTester tester, }) async { - final serviceExtensionButtons = tester - .widgetList(find.byType(ServiceExtensionButton)); + final serviceExtensionButtons = tester.widgetList( + find.byType(ServiceExtensionButton), + ); final button = serviceExtensionButtons.firstWhereOrNull( (b) => b.extensionState.description.extension == extensionName, ); @@ -358,7 +348,8 @@ Future _verifyExtensionStateInServiceManager( required Object? value, }) async { final stateListenable = serviceConnection - .serviceManager.serviceExtensionManager + .serviceManager + .serviceExtensionManager .getServiceExtensionState(extensionName); // Wait for the service extension state to match the expected value. diff --git a/packages/devtools_app/integration_test/test/offline/memory_offline_data_test.dart b/packages/devtools_app/integration_test/test/offline/memory_offline_data_test.dart index f8ab910cd22..a224503247b 100644 --- a/packages/devtools_app/integration_test/test/offline/memory_offline_data_test.dart +++ b/packages/devtools_app/integration_test/test/offline/memory_offline_data_test.dart @@ -14,27 +14,24 @@ import 'package:integration_test/integration_test.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - testWidgets( - 'Memory screen can load offline data', - (tester) async { - await pumpDevTools(tester); - logStatus('1 - pumped devtools'); - await loadSampleData(tester, memoryFileName); - logStatus('2 - loaded sample data'); - await tester.pumpAndSettle(longPumpDuration); - logStatus('3 - pumped and settled'); + testWidgets('Memory screen can load offline data', (tester) async { + await pumpDevTools(tester); + logStatus('1 - pumped devtools'); + await loadSampleData(tester, memoryFileName); + logStatus('2 - loaded sample data'); + await tester.pumpAndSettle(longPumpDuration); + logStatus('3 - pumped and settled'); - const diffTab = 'Diff Snapshots'; - const profileTab = 'Profile Memory'; - const traceTab = 'Trace Instances'; + const diffTab = 'Diff Snapshots'; + const profileTab = 'Profile Memory'; + const traceTab = 'Trace Instances'; - expect(find.text('_MyClass'), findsOneWidget); - logStatus('5 - found _MyClass'); + expect(find.text('_MyClass'), findsOneWidget); + logStatus('5 - found _MyClass'); - for (final tab in [diffTab, profileTab, traceTab]) { - expect(find.text(tab), findsOneWidget); - logStatus('6.$tab - found'); - } - }, - ); + for (final tab in [diffTab, profileTab, traceTab]) { + expect(find.text(tab), findsOneWidget); + logStatus('6.$tab - found'); + } + }); } diff --git a/packages/devtools_app/integration_test/test_infra/run/_in_file_args.dart b/packages/devtools_app/integration_test/test_infra/run/_in_file_args.dart index dd6685e264a..137579df824 100644 --- a/packages/devtools_app/integration_test/test_infra/run/_in_file_args.dart +++ b/packages/devtools_app/integration_test/test_infra/run/_in_file_args.dart @@ -7,10 +7,7 @@ import 'dart:io'; import '_test_app_driver.dart'; -enum TestFileArgItems { - experimentsOn, - appPath, -} +enum TestFileArgItems { experimentsOn, appPath } const _defaultFlutterAppPath = 'test/test_infra/fixtures/flutter_app'; const _defaultDartCliAppPath = 'test/test_infra/fixtures/empty_app.dart'; @@ -41,11 +38,12 @@ class TestFileArgs { TestFileArgs.parse( Map map, { required TestAppDevice testAppDevice, - }) : experimentsOn = map[TestFileArgItems.experimentsOn] ?? false, - appPath = map[TestFileArgItems.appPath] ?? - (testAppDevice == TestAppDevice.cli - ? _defaultDartCliAppPath - : _defaultFlutterAppPath); + }) : experimentsOn = map[TestFileArgItems.experimentsOn] ?? false, + appPath = + map[TestFileArgItems.appPath] ?? + (testAppDevice == TestAppDevice.cli + ? _defaultDartCliAppPath + : _defaultFlutterAppPath); /// If true, experiments will be enabled in the test. final bool experimentsOn; @@ -62,18 +60,18 @@ final _argRegex = RegExp( Map _parseFileContent(String fileContent) { final matches = _argRegex.allMatches(fileContent); - final entries = matches.map>( - (RegExpMatch m) { - final name = m.group(1) ?? ''; - if (name.isEmpty) { - throw ArgumentError( - 'Name of test argument should be provided: [${m.group(0)}].', - ); - } - final value = m.group(2) ?? ''; - return MapEntry(TestFileArgItems.values.byName(name), jsonDecode(value)); - }, - ); + final entries = matches.map>(( + RegExpMatch m, + ) { + final name = m.group(1) ?? ''; + if (name.isEmpty) { + throw ArgumentError( + 'Name of test argument should be provided: [${m.group(0)}].', + ); + } + final value = m.group(2) ?? ''; + return MapEntry(TestFileArgItems.values.byName(name), jsonDecode(value)); + }); return Map.fromEntries(entries); } 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 26dc0439133..7a8e45d3d80 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 @@ -23,18 +23,14 @@ class TestFlutterApp extends IntegrationTestApp { @override Future startProcess() async { - runProcess = await Process.start( - 'flutter', - [ - 'run', - '--machine', - '-d', - testAppDevice.argName, - // Do not serve DevTools from Flutter Tools. - '--no-devtools', - ], - workingDirectory: testAppPath, - ); + runProcess = await Process.start('flutter', [ + 'run', + '--machine', + '-d', + testAppDevice.argName, + // Do not serve DevTools from Flutter Tools. + '--no-devtools', + ], workingDirectory: testAppPath); } @override @@ -50,19 +46,23 @@ class TestFlutterApp extends IntegrationTestApp { event: FlutterDaemonConstants.appDebugPort.key, timeout: IntegrationTestApp._appStartTimeout, ); - final wsUriString = (debugPort[FlutterDaemonConstants.params.key]! - as Map)[FlutterDaemonConstants.wsUri.key] as String; + final wsUriString = + (debugPort[FlutterDaemonConstants.params.key]! + as Map)[FlutterDaemonConstants.wsUri.key] + as String; _vmServiceWsUri = Uri.parse(wsUriString); // Map to WS URI. - _vmServiceWsUri = - convertToWebSocketUrl(serviceProtocolUrl: _vmServiceWsUri); + _vmServiceWsUri = convertToWebSocketUrl( + serviceProtocolUrl: _vmServiceWsUri, + ); // Now await the started event; if it had already happened the future will // have already completed. final startedResult = await started; - final params = startedResult[FlutterDaemonConstants.params.key]! - as Map; + final params = + startedResult[FlutterDaemonConstants.params.key]! + as Map; _currentRunningAppId = params[FlutterDaemonConstants.appId.key] as String?; } @@ -72,10 +72,9 @@ class TestFlutterApp extends IntegrationTestApp { _debugPrint('Stopping app'); await Future.any(>[ runProcess!.exitCode, - _sendFlutterDaemonRequest( - 'app.stop', - {'appId': _currentRunningAppId}, - ), + _sendFlutterDaemonRequest('app.stop', { + 'appId': _currentRunningAppId, + }), ]).timeout( IOMixin.killTimeout, onTimeout: () { @@ -140,9 +139,10 @@ class TestFlutterApp extends IntegrationTestApp { return _timeoutWithMessages>( () => response.future, timeout: timeout, - message: event != null - ? 'Did not receive expected $event event.' - : 'Did not receive response to request "$id".', + message: + event != null + ? 'Did not receive expected $event event.' + : 'Did not receive response to request "$id".', ).whenComplete(() => sub.cancel()); } @@ -171,13 +171,15 @@ class TestFlutterApp extends IntegrationTestApp { error.write( '${event != null ? '$event event' : 'response to request $id.'}.\n\n', ); - final errorFromJson = (json[FlutterDaemonConstants.params.key] - as Map?)?[FlutterDaemonConstants.error.key]; + final errorFromJson = + (json[FlutterDaemonConstants.params.key] + as Map?)?[FlutterDaemonConstants.error.key]; if (errorFromJson != null) { error.write('$errorFromJson\n\n'); } - final traceFromJson = (json[FlutterDaemonConstants.params.key] - as Map?)?[FlutterDaemonConstants.trace.key]; + final traceFromJson = + (json[FlutterDaemonConstants.params.key] + as Map?)?[FlutterDaemonConstants.trace.key]; if (traceFromJson != null) { error.write('$traceFromJson\n\n'); } @@ -200,9 +202,8 @@ class TestFlutterApp extends IntegrationTestApp { } class TestDartCliApp extends IntegrationTestApp { - TestDartCliApp({ - String appPath = 'test/test_infra/fixtures/empty_app.dart', - }) : super(appPath, TestAppDevice.cli); + TestDartCliApp({String appPath = 'test/test_infra/fixtures/empty_app.dart'}) + : super(appPath, TestAppDevice.cli); static const vmServicePrefix = 'The Dart VM service is listening on '; @@ -212,15 +213,11 @@ class TestDartCliApp extends IntegrationTestApp { final parts = testAppPath.split(separator); final scriptName = parts.removeLast(); final workingDir = parts.join(separator); - runProcess = await Process.start( - 'dart', - [ - '--observe=0', - 'run', - scriptName, - ], - workingDirectory: workingDir, - ); + runProcess = await Process.start('dart', [ + '--observe=0', + 'run', + scriptName, + ], workingDirectory: workingDir); } @override @@ -232,8 +229,9 @@ class TestDartCliApp extends IntegrationTestApp { final parsedVmServiceUri = Uri.parse(vmServiceUri); // Map to WS URI. - _vmServiceWsUri = - convertToWebSocketUrl(serviceProtocolUrl: parsedVmServiceUri); + _vmServiceWsUri = convertToWebSocketUrl( + serviceProtocolUrl: parsedVmServiceUri, + ); } Future waitFor({required String message, Duration? timeout}) { @@ -262,8 +260,9 @@ class TestDartCliApp extends IntegrationTestApp { required String message, }) async { if (message == vmServicePrefix && line.startsWith(vmServicePrefix)) { - final vmServiceUri = line - .substring(line.indexOf(vmServicePrefix) + vmServicePrefix.length); + final vmServiceUri = line.substring( + line.indexOf(vmServicePrefix) + vmServicePrefix.length, + ); await subscription.cancel(); response.complete(vmServiceUri); } @@ -331,10 +330,8 @@ abstract class IntegrationTestApp with IOMixin { _debugPrint('Waiting for process to end'); return runProcess!.exitCode.timeout( IOMixin.killTimeout, - onTimeout: () => killGracefully( - runProcess!, - debugLogging: debugTestScript, - ), + onTimeout: + () => killGracefully(runProcess!, debugLogging: debugTestScript), ); } @@ -354,15 +351,18 @@ abstract class IntegrationTestApp with IOMixin { final sub = _allMessages.stream.listen(logMessage); - return f().timeout( - timeout ?? _defaultTimeout, - onTimeout: () { - logMessage(''); - throw '$message'; - }, - ).catchError((Object? error) { - throw '$error\nReceived:\n${messages.toString()}'; - }).whenComplete(() => sub.cancel()); + return f() + .timeout( + timeout ?? _defaultTimeout, + onTimeout: () { + logMessage(''); + throw '$message'; + }, + ) + .catchError((Object? error) { + throw '$error\nReceived:\n${messages.toString()}'; + }) + .whenComplete(() => sub.cancel()); } String _debugPrint(String msg) { @@ -379,15 +379,17 @@ abstract class IntegrationTestApp with IOMixin { /// /// If the URI is already a VM Service WebSocket URI it will not be modified. Uri convertToWebSocketUrl({required Uri serviceProtocolUrl}) { - final isSecure = serviceProtocolUrl.isScheme('wss') || + final isSecure = + serviceProtocolUrl.isScheme('wss') || serviceProtocolUrl.isScheme('https'); final scheme = isSecure ? 'wss' : 'ws'; - final path = serviceProtocolUrl.path.endsWith('/ws') - ? serviceProtocolUrl.path - : (serviceProtocolUrl.path.endsWith('/') - ? '${serviceProtocolUrl.path}ws' - : '${serviceProtocolUrl.path}/ws'); + final path = + serviceProtocolUrl.path.endsWith('/ws') + ? serviceProtocolUrl.path + : (serviceProtocolUrl.path.endsWith('/') + ? '${serviceProtocolUrl.path}ws' + : '${serviceProtocolUrl.path}/ws'); return serviceProtocolUrl.replace(scheme: scheme, path: path); } @@ -410,7 +412,7 @@ enum FlutterDaemonConstants { daemonConnected(nameOverride: 'daemon.connected'); const FlutterDaemonConstants({String? nameOverride}) - : _nameOverride = nameOverride; + : _nameOverride = nameOverride; final String? _nameOverride; @@ -447,11 +449,13 @@ enum TestAppDevice { ], }; - static final _argNameToDeviceMap = - TestAppDevice.values.fold({}, (map, device) { - map[device.argName] = device; - return map; - }); + static final _argNameToDeviceMap = TestAppDevice.values.fold( + {}, + (map, device) { + map[device.argName] = device; + return map; + }, + ); static TestAppDevice? fromArgName(String argName) { return _argNameToDeviceMap[argName]; @@ -459,7 +463,8 @@ enum TestAppDevice { bool supportsTest(String testPath) { final unsupportedTests = _unsupportedTestsForDevice[this] ?? []; - return unsupportedTests - .none((unsupportedTestPath) => testPath.endsWith(unsupportedTestPath)); + return unsupportedTests.none( + (unsupportedTestPath) => testPath.endsWith(unsupportedTestPath), + ); } } diff --git a/packages/devtools_app/integration_test/test_infra/run/run_test.dart b/packages/devtools_app/integration_test/test_infra/run/run_test.dart index 653bcf8527b..2de64e3e116 100644 --- a/packages/devtools_app/integration_test/test_infra/run/run_test.dart +++ b/packages/devtools_app/integration_test/test_infra/run/run_test.dart @@ -60,9 +60,7 @@ Future runFlutterIntegrationTest( // Run the flutter integration test. final testRunner = IntegrationTestRunner(); try { - final testArgs = { - if (!offline) 'service_uri': testAppUri, - }; + final testArgs = {if (!offline) 'service_uri': testAppUri}; final testTarget = testRunnerArgs.testTarget!; debugLog('starting test run for $testTarget'); await testRunner.run( @@ -89,10 +87,11 @@ Future runFlutterIntegrationTest( class DevToolsAppTestRunnerArgs extends IntegrationTestRunnerArgs { DevToolsAppTestRunnerArgs(super.args, {super.verifyValidTarget = true}) - : super(addExtraArgs: _addExtraArgs) { - testAppDevice = TestAppDevice.fromArgName( - argResults[_testAppDeviceArg] ?? TestAppDevice.flutterTester.argName, - )!; + : super(addExtraArgs: _addExtraArgs) { + testAppDevice = + TestAppDevice.fromArgName( + argResults[_testAppDeviceArg] ?? TestAppDevice.flutterTester.argName, + )!; } /// The type of device for the test app to run on. @@ -116,7 +115,8 @@ class DevToolsAppTestRunnerArgs extends IntegrationTestRunnerArgs { argParser ..addOption( _testAppUriArg, - help: 'The vm service connection to use for the app that DevTools will ' + help: + 'The vm service connection to use for the app that DevTools will ' 'connect to during the integration test. If left empty, a sample app ' 'will be spun up as part of the integration test process.', ) diff --git a/packages/devtools_app/lib/devtools.dart b/packages/devtools_app/lib/devtools.dart index 76afe20dbc2..00c8be34c09 100644 --- a/packages/devtools_app/lib/devtools.dart +++ b/packages/devtools_app/lib/devtools.dart @@ -10,4 +10,4 @@ /// Note: a regexp in the `dt update-version' command logic matches the constant /// declaration `const version =`. If you change the declaration you must also /// modify the regex in the `dt update-version' command logic. -const version = '2.41.0-dev.2'; +const version = '2.41.0-dev.3'; diff --git a/packages/devtools_app/lib/src/app.dart b/packages/devtools_app/lib/src/app.dart index 5cdcda109e2..b03b6798ca3 100644 --- a/packages/devtools_app/lib/src/app.dart +++ b/packages/devtools_app/lib/src/app.dart @@ -88,15 +88,16 @@ class DevToolsAppState extends State with AutoDisposeMixin { if (FeatureFlags.devToolsExtensions) { // TODO(https://github.com/flutter/devtools/issues/6273): stop special // casing the package:provider extension. - final containsProviderExtension = extensionService - .currentExtensions.value.visibleExtensions - .where((e) => e.name == 'provider') - .isNotEmpty; - final devToolsScreens = containsProviderExtension - ? _originalScreens - .where((s) => s.screenId != ScreenMetaData.provider.id) - .toList() - : _originalScreens; + final containsProviderExtension = + extensionService.currentExtensions.value.visibleExtensions + .where((e) => e.name == 'provider') + .isNotEmpty; + final devToolsScreens = + containsProviderExtension + ? _originalScreens + .where((s) => s.screenId != ScreenMetaData.provider.id) + .toList() + : _originalScreens; return [...devToolsScreens, ..._extensionScreens]; } return _originalScreens; @@ -105,10 +106,8 @@ class DevToolsAppState extends State with AutoDisposeMixin { List get _originalScreens => widget.originalScreens.map((s) => s.screen).toList(); - Iterable get _extensionScreens => - extensionService.visibleExtensions.map( - (e) => DevToolsScreen(ExtensionScreen(e)).screen, - ); + Iterable get _extensionScreens => extensionService.visibleExtensions + .map((e) => DevToolsScreen(ExtensionScreen(e)).screen); final hoverCardController = HoverCardController(); @@ -197,25 +196,13 @@ class DevToolsAppState extends State with AutoDisposeMixin { // Provide the appropriate page route. if (pages.containsKey(page)) { - Widget widget = pages[page]!( - context, - page, - params, - state, - ); - assert( - () { - widget = _AlternateCheckedModeBanner( - builder: (context) => pages[page]!( - context, - page, - params, - state, - ), - ); - return true; - }(), - ); + Widget widget = pages[page]!(context, page, params, state); + assert(() { + widget = _AlternateCheckedModeBanner( + builder: (context) => pages[page]!(context, page, params, state), + ); + return true; + }()); return MaterialPage(child: widget); } @@ -261,25 +248,28 @@ class DevToolsAppState extends State with AutoDisposeMixin { extensionService.currentExtensions, ], builder: (_, _, child) { - final screensInScaffold = _visibleScreens() - .where( - (s) => maybeIncludeOnlyEmbeddedScreen( - s, - page: page, - embedMode: embedMode, - ), - ) - .toList(); + final screensInScaffold = + _visibleScreens() + .where( + (s) => maybeIncludeOnlyEmbeddedScreen( + s, + page: page, + embedMode: embedMode, + ), + ) + .toList(); removeHiddenScreens(screensInScaffold, queryParams); DevToolsScaffold scaffold; - final originalScreen = - _screens.firstWhereOrNull((s) => s.screenId == page); + final originalScreen = _screens.firstWhereOrNull( + (s) => s.screenId == page, + ); final screenInOriginalScreens = originalScreen != null; - final screenInScaffoldScreens = - screensInScaffold.any((s) => s.screenId == page); + final screenInScaffoldScreens = screensInScaffold.any( + (s) => s.screenId == page, + ); if (page != null && screenInOriginalScreens && !screenInScaffoldScreens) { @@ -302,41 +292,49 @@ class DevToolsAppState extends State with AutoDisposeMixin { scaffold = DevToolsScaffold.withChild( embedMode: embedMode, child: CenteredMessage( - message: 'No DevTools ' + message: + 'No DevTools ' '${queryParams.hideAllExceptExtensions ? 'extensions' : 'screens'} ' 'available for your project.', ), ); } else { - final connectedToFlutterApp = serviceConnection - .serviceManager.connectedApp?.isFlutterAppNow ?? + final connectedToFlutterApp = + serviceConnection + .serviceManager + .connectedApp + ?.isFlutterAppNow ?? false; - final connectedToDartWebApp = serviceConnection - .serviceManager.connectedApp?.isDartWebAppNow ?? + final connectedToDartWebApp = + serviceConnection + .serviceManager + .connectedApp + ?.isDartWebAppNow ?? false; scaffold = DevToolsScaffold( embedMode: embedMode, page: page, screens: screensInScaffold, - actions: isEmbedded() - ? [] - : [ - if (paramsContainVmServiceUri) ...[ - // Hide the hot reload button for Dart web apps, where the - // hot reload service extension is not avilable and where the - // [service.reloadServices] RPC is not implemented. - // TODO(https://github.com/flutter/devtools/issues/6441): find - // a way to show this for Dart web apps when supported. - if (!connectedToDartWebApp) - HotReloadButton( - callOnVmServiceDirectly: !connectedToFlutterApp, - ), - // This button will hide itself based on whether the - // hot restart service is available for the connected app. - const HotRestartButton(), + actions: + isEmbedded() + ? [] + : [ + if (paramsContainVmServiceUri) ...[ + // Hide the hot reload button for Dart web apps, where the + // hot reload service extension is not avilable and where the + // [service.reloadServices] RPC is not implemented. + // TODO(https://github.com/flutter/devtools/issues/6441): find + // a way to show this for Dart web apps when supported. + if (!connectedToDartWebApp) + HotReloadButton( + callOnVmServiceDirectly: !connectedToFlutterApp, + ), + // This button will hide itself based on whether the + // hot restart service is available for the connected app. + const HotRestartButton(), + ], + ...DevToolsScaffold.defaultActions(), ], - ...DevToolsScaffold.defaultActions(), - ], ); } return MultiProvider( @@ -432,9 +430,7 @@ class DevToolsAppState extends State with AutoDisposeMixin { Provider.value( value: widget.analyticsController, ), - Provider.value( - value: hoverCardController, - ), + Provider.value(value: hoverCardController), Provider.value( value: releaseNotesController, ), @@ -454,8 +450,9 @@ class DevToolsAppState extends State with AutoDisposeMixin { routeInformationParser: DevToolsRouteInformationParser(), // Disable default scrollbar behavior on web to fix duplicate scrollbars // bug, see https://github.com/flutter/flutter/issues/90697: - scrollBehavior: - const MaterialScrollBehavior().copyWith(scrollbars: !kIsWeb), + scrollBehavior: const MaterialScrollBehavior().copyWith( + scrollbars: !kIsWeb, + ), ); } @@ -505,7 +502,8 @@ class DevToolsAppState extends State with AutoDisposeMixin { if (reason == ScreenDisabledReason.requiresDartLibrary) { // Special case for screens that require a library since the message // needs to be generated dynamically. - disabledMessage = 'The ${screen.title} screen requires library ' + disabledMessage = + 'The ${screen.title} screen requires library ' '${screen.requiresLibrary}, but the library was not detected.'; } else if (reason?.message case final String message) { disabledMessage = 'The ${screen.title} screen $message'; @@ -561,12 +559,13 @@ class DevToolsScreen { /// A [WidgetBuilder] that takes an additional map of URL query parameters and /// args, as well a state not included in the URL. -typedef UrlParametersBuilder = Widget Function( - BuildContext, - String?, - DevToolsQueryParams, - DevToolsNavigationState?, -); +typedef UrlParametersBuilder = + Widget Function( + BuildContext, + String?, + DevToolsQueryParams, + DevToolsNavigationState?, + ); /// Displays the checked mode banner in the bottom end corner instead of the /// top end corner. @@ -583,9 +582,7 @@ class _AlternateCheckedModeBanner extends StatelessWidget { message: 'DEBUG', textDirection: TextDirection.ltr, location: BannerLocation.bottomEnd, - child: Builder( - builder: builder, - ), + child: Builder(builder: builder), ); } } @@ -611,21 +608,15 @@ class ScreenUnavailable extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Text( - title, - style: theme.textTheme.titleLarge, - ), + Text(title, style: theme.textTheme.titleLarge), const SizedBox(height: denseSpacing), if (description != null) - Text( - description!, - style: theme.regularTextStyle, - ), + Text(description!, style: theme.regularTextStyle), if (embedMode == EmbedMode.none) ...[ const SizedBox(height: defaultSpacing), ElevatedButton( - onPressed: () => - routerDelegate.navigateHome(clearScreenParam: true), + onPressed: + () => routerDelegate.navigateHome(clearScreenParam: true), child: const Text('Go to Home screen'), ), ], @@ -667,9 +658,9 @@ List defaultScreens({ ), DevToolsScreen( DebuggerScreen(), - createController: (routerDelegate) => DebuggerController( - routerDelegate: routerDelegate, - ), + createController: + (routerDelegate) => + DebuggerController(routerDelegate: routerDelegate), ), DevToolsScreen( NetworkScreen(), diff --git a/packages/devtools_app/lib/src/example/conditional_screen.dart b/packages/devtools_app/lib/src/example/conditional_screen.dart index 5d53d0bcca5..91597e09b25 100644 --- a/packages/devtools_app/lib/src/example/conditional_screen.dart +++ b/packages/devtools_app/lib/src/example/conditional_screen.dart @@ -19,13 +19,13 @@ import '../shared/utils.dart'; /// DevTools app. class ExampleConditionalScreen extends Screen { const ExampleConditionalScreen() - : super.conditional( - id: id, - requiresLibrary: 'package:flutter/', - title: 'Example', - icon: Icons.palette, - worksWithOfflineData: true, - ); + : super.conditional( + id: id, + requiresLibrary: 'package:flutter/', + title: 'Example', + icon: Icons.palette, + worksWithOfflineData: true, + ); static const id = 'example'; @@ -46,8 +46,10 @@ class _ExampleConditionalScreenBody extends StatefulWidget { class _ExampleConditionalScreenBodyState extends State<_ExampleConditionalScreenBody> with - ProvidedControllerMixin { + ProvidedControllerMixin< + ExampleController, + _ExampleConditionalScreenBody + > { @override void didChangeDependencies() { super.didChangeDependencies(); @@ -73,8 +75,9 @@ class ExampleController extends DisposableController unawaited(_init()); } - final data = - ValueNotifier(ExampleScreenData('Example screen')); + final data = ValueNotifier( + ExampleScreenData('Example screen'), + ); final _initialized = Completer(); 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 f016f3e9a1e..a3154d7f526 100644 --- a/packages/devtools_app/lib/src/extensions/embedded/_controller_web.dart +++ b/packages/devtools_app/lib/src/extensions/embedded/_controller_web.dart @@ -57,9 +57,10 @@ class EmbeddedExtensionControllerImpl extends EmbeddedExtensionController ); final queryParams = { ...DevToolsQueryParams.load().params, - ExtensionEventParameters.theme: isDarkThemeEnabled() - ? ExtensionEventParameters.themeValueDark - : ExtensionEventParameters.themeValueLight, + ExtensionEventParameters.theme: + isDarkThemeEnabled() + ? ExtensionEventParameters.themeValueDark + : ExtensionEventParameters.themeValueLight, if (dtdManager.uri != null) 'dtdUri': dtdManager.uri.toString(), }; return Uri.parse(baseUri).copyWith(queryParameters: queryParams).toString(); @@ -84,11 +85,12 @@ class EmbeddedExtensionControllerImpl extends EmbeddedExtensionController ); _initialized = true; - _extensionIFrame = HTMLIFrameElement() - // This url is safe because we built it ourselves and it does not include - // any user input. - ..src = extensionUrl - ..allow = 'usb'; + _extensionIFrame = + HTMLIFrameElement() + // This url is safe because we built it ourselves and it does not include + // any user input. + ..src = extensionUrl + ..allow = 'usb'; _extensionIFrame.style ..border = 'none' ..height = '100%' diff --git a/packages/devtools_app/lib/src/extensions/embedded/_view_web.dart b/packages/devtools_app/lib/src/extensions/embedded/_view_web.dart index 7b5e63aca6e..431c4359a66 100644 --- a/packages/devtools_app/lib/src/extensions/embedded/_view_web.dart +++ b/packages/devtools_app/lib/src/extensions/embedded/_view_web.dart @@ -60,9 +60,7 @@ class _EmbeddedExtensionState extends State if (refreshing) { return const CenteredCircularProgressIndicator(); } - return HtmlElementView( - viewType: _embeddedExtensionController.viewId, - ); + return HtmlElementView(viewType: _embeddedExtensionController.viewId); }, ), ); @@ -118,8 +116,9 @@ class _ExtensionIFrameController extends DisposableController ); autoDisposeStreamSubscription( - embeddedExtensionController.extensionPostEventStream.stream - .listen((event) async { + embeddedExtensionController.extensionPostEventStream.stream.listen(( + event, + ) async { final ready = await _pingExtensionUntilReady(); if (ready) { switch (event.type) { @@ -137,7 +136,8 @@ class _ExtensionIFrameController extends DisposableController 'Something went wrong. The ' '${embeddedExtensionController.extensionConfig.name} extension is ' 'not ready.', - reportExplanation: 'The extension did not respond to multiple ' + reportExplanation: + 'The extension did not respond to multiple ' 'DevToolsExtensionEventType.ping events with the expected ' 'DevToolsExtensionEventType.pong event.', ); @@ -147,9 +147,10 @@ class _ExtensionIFrameController extends DisposableController addAutoDisposeListener(preferences.darkModeEnabled, () { updateTheme( - theme: isDarkThemeEnabled() - ? ExtensionEventParameters.themeValueDark - : ExtensionEventParameters.themeValueLight, + theme: + isDarkThemeEnabled() + ? ExtensionEventParameters.themeValueDark + : ExtensionEventParameters.themeValueLight, ); }); } @@ -182,9 +183,10 @@ class _ExtensionIFrameController extends DisposableController if (extensionEvent != null) { onEventReceived( extensionEvent, - onUnknownEvent: () => notificationService.push( - 'Unknown event received from extension: $extensionEvent}', - ), + onUnknownEvent: + () => notificationService.push( + 'Unknown event received from extension: $extensionEvent}', + ), ); } } @@ -197,13 +199,15 @@ class _ExtensionIFrameController extends DisposableController Future _pingExtensionUntilReady() async { var ready = true; if (!_extensionHandlerReady.isCompleted) { - _pollForExtensionHandlerReady = - Timer.periodic(const Duration(milliseconds: 200), (_) { - // Once the extension UI is ready, the extension will receive this - // [DevToolsExtensionEventType.ping] message and return a - // [DevToolsExtensionEventType.pong] message, handled in [_handleMessage]. - ping(); - }); + _pollForExtensionHandlerReady = Timer.periodic( + const Duration(milliseconds: 200), + (_) { + // Once the extension UI is ready, the extension will receive this + // [DevToolsExtensionEventType.ping] message and return a + // [DevToolsExtensionEventType.pong] message, handled in [_handleMessage]. + ping(); + }, + ); await _extensionHandlerReady.future.timeout( _pollUntilReadyTimeout, @@ -301,7 +305,7 @@ class _ExtensionIFrameController extends DisposableController final showBannerMessageEvent = ShowBannerMessageExtensionEvent.from(event); final bannerMessageType = BannerMessageType.parse(showBannerMessageEvent.bannerMessageType) ?? - BannerMessageType.warning; + BannerMessageType.warning; final bannerMessage = BannerMessage( messageType: bannerMessageType, key: Key( diff --git a/packages/devtools_app/lib/src/extensions/extension_screen.dart b/packages/devtools_app/lib/src/extensions/extension_screen.dart index 0c3a9d86c19..558bf5432d5 100644 --- a/packages/devtools_app/lib/src/extensions/extension_screen.dart +++ b/packages/devtools_app/lib/src/extensions/extension_screen.dart @@ -18,21 +18,21 @@ import 'extension_screen_controls.dart'; class ExtensionScreen extends Screen { ExtensionScreen(this.extensionConfig) - : super.conditional( - // TODO(kenz): we may need to ensure this is a unique id. - id: extensionConfig.screenId, - title: extensionConfig.name, - icon: extensionConfig.icon, - requiresConnection: - // We set this to false all the time when embedded because the - // available extensions are displayed in a tool window (IntelliJ - // and Android Studio) with or without any active debug sessions. - // This prevents a "DevTools Extensions" tool window in IntelliJ - // and Android Studio that appears to be missing extensions. When - // a connection is still required to use the extension, messaging - // for this is provided by the [EmbeddedExtensionView] widget. - isEmbedded() ? false : extensionConfig.requiresConnection, - ); + : super.conditional( + // TODO(kenz): we may need to ensure this is a unique id. + id: extensionConfig.screenId, + title: extensionConfig.name, + icon: extensionConfig.icon, + requiresConnection: + // We set this to false all the time when embedded because the + // available extensions are displayed in a tool window (IntelliJ + // and Android Studio) with or without any active debug sessions. + // This prevents a "DevTools Extensions" tool window in IntelliJ + // and Android Studio that appears to be missing extensions. When + // a connection is still required to use the extension, messaging + // for this is provided by the [EmbeddedExtensionView] widget. + isEmbedded() ? false : extensionConfig.requiresConnection, + ); final DevToolsExtensionConfig extensionConfig; @@ -63,8 +63,9 @@ class _ExtensionScreenBodyState extends State<_ExtensionScreenBody> { ga.screen( gac.DevToolsExtensionEvents.extensionScreenName(widget.extensionConfig), ); - extensionController = - createEmbeddedExtensionController(widget.extensionConfig)..init(); + extensionController = createEmbeddedExtensionController( + widget.extensionConfig, + )..init(); } @override @@ -92,11 +93,7 @@ class _ExtensionScreenBodyState extends State<_ExtensionScreenBody> { } class ExtensionView extends StatelessWidget { - const ExtensionView({ - super.key, - required this.controller, - required this.ext, - }); + const ExtensionView({super.key, required this.controller, required this.ext}); final EmbeddedExtensionController controller; @@ -109,15 +106,15 @@ class ExtensionView extends StatelessWidget { children: [ EmbeddedExtensionHeader( ext: ext, - onForceReload: () => - controller.postMessage(DevToolsExtensionEventType.forceReload), + onForceReload: + () => controller.postMessage( + DevToolsExtensionEventType.forceReload, + ), ), const SizedBox(height: intermediateSpacing), Expanded( child: ValueListenableBuilder( - valueListenable: extensionService.enabledStateListenable( - ext.name, - ), + valueListenable: extensionService.enabledStateListenable(ext.name), builder: (context, activationState, _) { if (activationState == ExtensionEnabledState.enabled) { return KeepAliveWrapper( @@ -126,9 +123,7 @@ class ExtensionView extends StatelessWidget { ), ); } - return EnableExtensionPrompt( - ext: controller.extensionConfig, - ); + return EnableExtensionPrompt(ext: controller.extensionConfig); }, ), ), @@ -138,10 +133,8 @@ class ExtensionView extends StatelessWidget { } extension ExtensionConfigExtension on DevToolsExtensionConfig { - IconData get icon => IconData( - materialIconCodePoint, - fontFamily: 'MaterialIcons', - ); + IconData get icon => + IconData(materialIconCodePoint, fontFamily: 'MaterialIcons'); String get screenId => '${name}_ext'; } diff --git a/packages/devtools_app/lib/src/extensions/extension_screen_controls.dart b/packages/devtools_app/lib/src/extensions/extension_screen_controls.dart index 8c3afac63c0..3d4cf7c42a4 100644 --- a/packages/devtools_app/lib/src/extensions/extension_screen_controls.dart +++ b/packages/devtools_app/lib/src/extensions/extension_screen_controls.dart @@ -41,8 +41,9 @@ class EmbeddedExtensionHeader extends StatelessWidget { child: RichText( text: TextSpan( text: 'package:$extensionName extension', - style: theme.regularTextStyle - .copyWith(fontWeight: FontWeight.bold), + style: theme.regularTextStyle.copyWith( + fontWeight: FontWeight.bold, + ), children: [ TextSpan( text: ' (v${ext.version})', @@ -63,8 +64,8 @@ class EmbeddedExtensionHeader extends StatelessWidget { url: ext.issueTrackerLink, gaScreenName: gac.DevToolsExtensionEvents.extensionScreenId.name, - gaSelectedItemDescription: - gac.DevToolsExtensionEvents.extensionFeedback(ext), + gaSelectedItemDescription: gac + .DevToolsExtensionEvents.extensionFeedback(ext), ), context: context, ), @@ -167,10 +168,7 @@ class DisableExtensionDialog extends StatelessWidget { text: 'Are you sure you want to disable the ', style: theme.regularTextStyle, children: [ - TextSpan( - text: ext.displayName, - style: theme.fixedFontStyle, - ), + TextSpan(text: ext.displayName, style: theme.fixedFontStyle), const TextSpan(text: ' extension?'), ], ), @@ -186,10 +184,7 @@ class DisableExtensionDialog extends StatelessWidget { style: theme.boldTextStyle, ), WidgetSpan( - child: Icon( - Icons.extension_rounded, - size: defaultIconSize, - ), + child: Icon(Icons.extension_rounded, size: defaultIconSize), ), const TextSpan(text: ' menu.'), ], @@ -208,8 +203,9 @@ class DisableExtensionDialog extends StatelessWidget { extensionService.setExtensionEnabledState(ext, enable: false), ); Navigator.of(context).pop(dialogDefaultContext); - DevToolsRouterDelegate.of(context) - .navigateHome(clearScreenParam: true); + DevToolsRouterDelegate.of( + context, + ).navigateHome(clearScreenParam: true); }, child: const Text('YES, DISABLE'), ), @@ -237,12 +233,10 @@ class EnableExtensionPrompt extends StatelessWidget { text: 'The ', style: theme.regularTextStyle, children: [ - TextSpan( - text: ext.name, - style: theme.fixedFontStyle, - ), + TextSpan(text: ext.name, style: theme.fixedFontStyle), const TextSpan( - text: ' extension has not been enabled. Do you want to enable' + text: + ' extension has not been enabled. Do you want to enable' ' this extension?\nYou can always change this setting ' 'later from the DevTools Extensions ', ), @@ -252,9 +246,7 @@ class EnableExtensionPrompt extends StatelessWidget { color: theme.colorScheme.onSurface, ), ), - const TextSpan( - text: ' menu. ', - ), + const TextSpan(text: ' menu. '), ], ), ), @@ -292,8 +284,9 @@ class EnableExtensionPrompt extends StatelessWidget { enable: false, ), ); - DevToolsRouterDelegate.of(context) - .navigateHome(clearScreenParam: true); + DevToolsRouterDelegate.of( + context, + ).navigateHome(clearScreenParam: true); }, ), ], diff --git a/packages/devtools_app/lib/src/extensions/extension_service.dart b/packages/devtools_app/lib/src/extensions/extension_service.dart index e393c1f3f7d..d27a29ee866 100644 --- a/packages/devtools_app/lib/src/extensions/extension_service.dart +++ b/packages/devtools_app/lib/src/extensions/extension_service.dart @@ -18,20 +18,21 @@ final _log = Logger('ExtensionService'); /// Data pattern containing a [List] of available extensions and a [List] of /// visible extensions. -typedef DevToolsExtensionsGroup = ({ - /// All the DevTools extensions, runtime and static, that are available for - /// the connected application, regardless of whether they have been enabled or - /// disabled by the user. - /// - /// This set of extensions will include one version of a DevTools extension - /// per package and will exclude any duplicates that have been marked as - /// ignored in [_maybeIgnoreExtensions]. - List availableExtensions, - - /// DevTools extensions that are visible in their own DevTools screen (i.e. - /// extensions that have not been manually disabled by the user). - List visibleExtensions, -}); +typedef DevToolsExtensionsGroup = + ({ + /// All the DevTools extensions, runtime and static, that are available for + /// the connected application, regardless of whether they have been enabled or + /// disabled by the user. + /// + /// This set of extensions will include one version of a DevTools extension + /// per package and will exclude any duplicates that have been marked as + /// ignored in [_maybeIgnoreExtensions]. + List availableExtensions, + + /// DevTools extensions that are visible in their own DevTools screen (i.e. + /// extensions that have not been manually disabled by the user). + List visibleExtensions, + }); class ExtensionService extends DisposableController with AutoDisposeControllerMixin { @@ -60,12 +61,10 @@ class ExtensionService extends DisposableController /// from having to listen to two separate notifiers. ValueListenable get currentExtensions => _currentExtensions; - final _currentExtensions = ValueNotifier( - ( - availableExtensions: [], - visibleExtensions: [], - ), - ); + final _currentExtensions = ValueNotifier(( + availableExtensions: [], + visibleExtensions: [], + )); /// All the DevTools extensions, runtime and static, that are available for /// the connected application, regardless of whether they have been enabled or @@ -120,9 +119,7 @@ class ExtensionService extends DisposableController ) { return _extensionEnabledStates.putIfAbsent( extensionName.toLowerCase(), - () => ValueNotifier( - ExtensionEnabledState.none, - ), + () => ValueNotifier(ExtensionEnabledState.none), ); } @@ -183,8 +180,9 @@ class ExtensionService extends DisposableController serviceConnection.serviceManager.connectedState.value.connected && serviceConnection.serviceManager.isolateManager.mainIsolate.value != null) { - _appRoot = await serviceConnection.serviceManager - .connectedAppPackageRoot(dtdManager); + _appRoot = await serviceConnection.serviceManager.connectedAppPackageRoot( + dtdManager, + ); } // TODO(kenz): gracefully handle app connections / disconnects when there @@ -226,14 +224,16 @@ class ExtensionService extends DisposableController // ignoring the static extension when there is a duplicate. void _deduplicateStaticExtensionsWithRuntimeExtensions() { if (runtimeExtensions.isEmpty) return; - for (final staticExtension - in staticExtensions.where((ext) => !isExtensionIgnored(ext))) { + for (final staticExtension in staticExtensions.where( + (ext) => !isExtensionIgnored(ext), + )) { // TODO(kenz): do we need to match on something other than name? Names // _should_ be unique since they match a pub package name, but this may // not always be true for extensions that are not published on pub or // extensions that do not follow best practices for naming. - final isRuntimeDuplicate = - runtimeExtensions.any((ext) => ext.name == staticExtension.name); + final isRuntimeDuplicate = runtimeExtensions.any( + (ext) => ext.name == staticExtension.name, + ); if (isRuntimeDuplicate) { _log.fine( 'ignoring duplicate static extension ${staticExtension.identifier} ' @@ -263,9 +263,10 @@ class ExtensionService extends DisposableController ); stateNotifier.value = stateFromOptionsFile; - final shouldIncludeInVisible = onlyIncludeEnabled - ? stateFromOptionsFile == ExtensionEnabledState.enabled - : stateFromOptionsFile != ExtensionEnabledState.disabled; + final shouldIncludeInVisible = + onlyIncludeEnabled + ? stateFromOptionsFile == ExtensionEnabledState.enabled + : stateFromOptionsFile != ExtensionEnabledState.disabled; if (shouldIncludeInVisible) { visible.add(extension); } diff --git a/packages/devtools_app/lib/src/extensions/extension_service_helpers.dart b/packages/devtools_app/lib/src/extensions/extension_service_helpers.dart index 0a607b3c3e2..48e3df0d912 100644 --- a/packages/devtools_app/lib/src/extensions/extension_service_helpers.dart +++ b/packages/devtools_app/lib/src/extensions/extension_service_helpers.dart @@ -13,7 +13,7 @@ import 'package:logging/logging.dart'; void deduplicateExtensionsAndTakeLatest( List extensions, { required void Function(DevToolsExtensionConfig ext, {required bool ignore}) - onSetIgnored, + onSetIgnored, Logger? logger, String extensionType = '', }) { diff --git a/packages/devtools_app/lib/src/extensions/extension_settings.dart b/packages/devtools_app/lib/src/extensions/extension_settings.dart index 1962410d9f2..15c40ff8d59 100644 --- a/packages/devtools_app/lib/src/extensions/extension_settings.dart +++ b/packages/devtools_app/lib/src/extensions/extension_settings.dart @@ -19,21 +19,25 @@ import 'extension_screen.dart'; /// managing DevTools extension states. class ExtensionSettingsAction extends ScaffoldAction { ExtensionSettingsAction({super.key, super.color}) - : super( - iconAsset: 'icons/app_bar/devtools_extensions.png', - tooltip: 'DevTools Extensions', - onPressed: (context) { - unawaited( - showDialog( - context: context, - builder: (context) => ExtensionSettingsDialog( - extensions: extensionService - .currentExtensions.value.availableExtensions, - ), - ), - ); - }, - ); + : super( + iconAsset: 'icons/app_bar/devtools_extensions.png', + tooltip: 'DevTools Extensions', + onPressed: (context) { + unawaited( + showDialog( + context: context, + builder: + (context) => ExtensionSettingsDialog( + extensions: + extensionService + .currentExtensions + .value + .availableExtensions, + ), + ), + ); + }, + ); } @visibleForTesting @@ -72,21 +76,20 @@ class ExtensionSettingsDialog extends StatelessWidget { ), const PaddedDivider(), Expanded( - child: extensions.isEmpty - ? Center( - child: Text( - 'No extensions available.', - style: theme.subtleTextStyle, - ), - ) - : _ExtensionsList(extensions: extensions), + child: + extensions.isEmpty + ? Center( + child: Text( + 'No extensions available.', + style: theme.subtleTextStyle, + ), + ) + : _ExtensionsList(extensions: extensions), ), ], ), ), - actions: const [ - DialogCloseButton(), - ], + actions: const [DialogCloseButton()], ); } } @@ -123,9 +126,9 @@ class __ExtensionsListState extends State<_ExtensionsList> { child: ListView.builder( controller: scrollController, itemCount: widget.extensions.length, - itemBuilder: (context, index) => ExtensionSetting( - extension: widget.extensions[index], - ), + itemBuilder: + (context, index) => + ExtensionSetting(extension: widget.extensions[index]), ), ); } @@ -142,35 +145,31 @@ class ExtensionSetting extends StatelessWidget { final buttonStates = [ ( title: 'Enabled', - isSelected: (ExtensionEnabledState state) => - state == ExtensionEnabledState.enabled, + isSelected: + (ExtensionEnabledState state) => + state == ExtensionEnabledState.enabled, onPressed: () { ga.select( gac.DevToolsExtensionEvents.extensionSettingsId.name, gac.DevToolsExtensionEvents.extensionEnableManual(extension), ); unawaited( - extensionService.setExtensionEnabledState( - extension, - enable: true, - ), + extensionService.setExtensionEnabledState(extension, enable: true), ); }, ), ( title: 'Disabled', - isSelected: (ExtensionEnabledState state) => - state == ExtensionEnabledState.disabled, + isSelected: + (ExtensionEnabledState state) => + state == ExtensionEnabledState.disabled, onPressed: () { ga.select( gac.DevToolsExtensionEvents.extensionSettingsId.name, gac.DevToolsExtensionEvents.extensionDisableManual(extension), ); unawaited( - extensionService.setExtensionEnabledState( - extension, - enable: false, - ), + extensionService.setExtensionEnabledState(extension, enable: false), ); final router = DevToolsRouterDelegate.of(context); if (router.currentConfiguration?.page == extension.screenId) { diff --git a/packages/devtools_app/lib/src/framework/about_dialog.dart b/packages/devtools_app/lib/src/framework/about_dialog.dart index 815b199939e..2546c7ff441 100644 --- a/packages/devtools_app/lib/src/framework/about_dialog.dart +++ b/packages/devtools_app/lib/src/framework/about_dialog.dart @@ -33,12 +33,11 @@ class DevToolsAboutDialog extends StatelessWidget { SelectableText('DevTools version $devToolsVersion'), const Text(' - '), InkWell( - child: Text( - 'release notes', - style: theme.linkTextStyle, - ), - onTap: () => - unawaited(releaseNotesController.openLatestReleaseNotes()), + child: Text('release notes', style: theme.linkTextStyle), + onTap: + () => unawaited( + releaseNotesController.openLatestReleaseNotes(), + ), ), ], ), @@ -60,17 +59,11 @@ class DevToolsAboutDialog extends StatelessWidget { ], ), const Wrap( - children: [ - Text('connect with us on '), - _DiscordLink(), - Text('.'), - ], + children: [Text('connect with us on '), _DiscordLink(), Text('.')], ), ], ), - actions: const [ - DialogCloseButton(), - ], + actions: const [DialogCloseButton()], ); } } @@ -135,18 +128,19 @@ class _DiscordLink extends StatelessWidget { class OpenAboutAction extends ScaffoldAction { OpenAboutAction({super.key, super.color}) - : super( - icon: Icons.help_outline, - tooltip: 'About DevTools', - onPressed: (context) { - unawaited( - showDialog( - context: context, - builder: (context) => DevToolsAboutDialog( - Provider.of(context), - ), - ), - ); - }, - ); + : super( + icon: Icons.help_outline, + tooltip: 'About DevTools', + onPressed: (context) { + unawaited( + showDialog( + context: context, + builder: + (context) => DevToolsAboutDialog( + Provider.of(context), + ), + ), + ); + }, + ); } diff --git a/packages/devtools_app/lib/src/framework/app_bar.dart b/packages/devtools_app/lib/src/framework/app_bar.dart index 64c3a3e3545..121f5ca7cbd 100644 --- a/packages/devtools_app/lib/src/framework/app_bar.dart +++ b/packages/devtools_app/lib/src/framework/app_bar.dart @@ -93,10 +93,7 @@ class DevToolsAppBar extends StatelessWidget { flexibleSpace = Align( alignment: Alignment.centerLeft, child: Padding( - padding: EdgeInsets.only( - top: densePadding, - right: rightPadding, - ), + padding: EdgeInsets.only(top: densePadding, right: rightPadding), child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -223,7 +220,7 @@ class TabOverflowButton extends StatelessWidget { @visibleForTesting class SelectedTabWrapper extends StatelessWidget { SelectedTabWrapper({super.key, required this.child, double? width}) - : width = width ?? buttonMinWidth; + : width = width ?? buttonMinWidth; final Widget child; diff --git a/packages/devtools_app/lib/src/framework/app_error_handling.dart b/packages/devtools_app/lib/src/framework/app_error_handling.dart index aef89753ddc..6230adae751 100644 --- a/packages/devtools_app/lib/src/framework/app_error_handling.dart +++ b/packages/devtools_app/lib/src/framework/app_error_handling.dart @@ -103,12 +103,13 @@ Future _reportError( // Split the stack trace up into substrings of size // [ga4ParamValueCharacterLimit] so that we can send the stack trace in chunks // to GA4 through unified_analytics. - final stackTraceSubstrings = stackTrace - .toString() - .characters - .slices(ga4ParamValueCharacterLimit) - .map((slice) => slice.join()) - .toList(); + final stackTraceSubstrings = + stackTrace + .toString() + .characters + .slices(ga4ParamValueCharacterLimit) + .map((slice) => slice.join()) + .toList(); ga.reportError('$error', stackTraceSubstrings: stackTraceSubstrings); // Show error message in a notification pop-up: @@ -133,9 +134,7 @@ Future _fetchSourceMapping() async { Future _initializeSourceMapping() async { if (!kIsWeb) return null; try { - final sourceMapUri = Uri.parse( - 'main.dart.${kIsWasm ? 'wasm' : 'js'}.map', - ); + final sourceMapUri = Uri.parse('main.dart.${kIsWasm ? 'wasm' : 'js'}.map'); final sourceMapFile = await get(sourceMapUri); return SingleMapping.fromJson( @@ -154,19 +153,16 @@ Future _mapAndTersify(StackTrace? stack) async { final mappedStackTrace = await _maybeMapStackTrace(originalStackTrace); // If mapping fails, revert back to the original stack trace: - final stackTrace = mappedStackTrace.toString().isEmpty - ? originalStackTrace - : mappedStackTrace; + final stackTrace = + mappedStackTrace.toString().isEmpty + ? originalStackTrace + : mappedStackTrace; return stack_trace.Trace.from(stackTrace); } Future _maybeMapStackTrace(StackTrace stack) async { final sourceMapping = await _fetchSourceMapping(); return sourceMapping != null - ? mapStackTrace( - sourceMapping, - stack, - minified: true, - ) + ? mapStackTrace(sourceMapping, stack, minified: true) : stack; } diff --git a/packages/devtools_app/lib/src/framework/disconnect_observer.dart b/packages/devtools_app/lib/src/framework/disconnect_observer.dart index 9b2152e181d..60cb4151193 100644 --- a/packages/devtools_app/lib/src/framework/disconnect_observer.dart +++ b/packages/devtools_app/lib/src/framework/disconnect_observer.dart @@ -85,10 +85,7 @@ class DisconnectObserverState extends State return; } WidgetsBinding.instance.scheduleFrameCallback((_) { - ga.select( - gac.devToolsMain, - gac.appDisconnected, - ); + ga.select(gac.devToolsMain, gac.appDisconnected); Overlay.of(context).insert(_createDisconnectedOverlay()); }); } @@ -107,8 +104,11 @@ class DisconnectObserverState extends State hideDisconnectedOverlay(); final args = { DevToolsQueryParams.vmServiceUriKey: null, - DevToolsQueryParams.offlineScreenIdKey: offlineDataController - .offlineDataJson[DevToolsExportKeys.activeScreenId.name] as String, + DevToolsQueryParams.offlineScreenIdKey: + offlineDataController.offlineDataJson[DevToolsExportKeys + .activeScreenId + .name] + as String, }; await widget.routerDelegate.popRoute(); widget.routerDelegate.navigate(snapshotScreenId, args); @@ -117,36 +117,37 @@ class DisconnectObserverState extends State OverlayEntry _createDisconnectedOverlay() { final theme = Theme.of(context); currentDisconnectedOverlay = OverlayEntry( - builder: (context) => Material( - child: Container( - color: theme.colorScheme.surface, - child: Center( - child: Column( - children: [ - const Spacer(), - Text('Disconnected', style: theme.textTheme.headlineMedium), - const SizedBox(height: defaultSpacing), - if (!isEmbedded()) - ConnectToNewAppButton( - routerDelegate: widget.routerDelegate, - onPressed: hideDisconnectedOverlay, - gaScreen: gac.devToolsMain, - ) - else - const Text('Run a new debug session to reconnect.'), - const Spacer(), - if (offlineDataController.offlineDataJson.isNotEmpty) ...[ - ElevatedButton( - onPressed: _reviewHistory, - child: const Text('Review recent data (offline)'), - ), - const Spacer(), - ], - ], + builder: + (context) => Material( + child: Container( + color: theme.colorScheme.surface, + child: Center( + child: Column( + children: [ + const Spacer(), + Text('Disconnected', style: theme.textTheme.headlineMedium), + const SizedBox(height: defaultSpacing), + if (!isEmbedded()) + ConnectToNewAppButton( + routerDelegate: widget.routerDelegate, + onPressed: hideDisconnectedOverlay, + gaScreen: gac.devToolsMain, + ) + else + const Text('Run a new debug session to reconnect.'), + const Spacer(), + if (offlineDataController.offlineDataJson.isNotEmpty) ...[ + ElevatedButton( + onPressed: _reviewHistory, + child: const Text('Review recent data (offline)'), + ), + const Spacer(), + ], + ], + ), + ), ), ), - ), - ), ); return currentDisconnectedOverlay!; } diff --git a/packages/devtools_app/lib/src/framework/framework_core.dart b/packages/devtools_app/lib/src/framework/framework_core.dart index c8aa1150762..7651e6cd74a 100644 --- a/packages/devtools_app/lib/src/framework/framework_core.dart +++ b/packages/devtools_app/lib/src/framework/framework_core.dart @@ -119,25 +119,25 @@ abstract class FrameworkCore { final service = await connect( uri: uri, finishedCompleter: finishedCompleter, - serviceFactory: ({ - // ignore: avoid-dynamic, mirrors types of [VmServiceFactory]. - required Stream /*String|List*/ inStream, - required void Function(String message) writeMessage, - Log? log, - DisposeHandler? disposeHandler, - Future? streamClosed, - String? wsUri, - bool trackFutures = false, - }) => - VmServiceWrapper.defaultFactory( - inStream: inStream, - writeMessage: writeMessage, - log: log, - disposeHandler: disposeHandler, - streamClosed: streamClosed, - wsUri: wsUri, - trackFutures: integrationTestMode, - ), + serviceFactory: + ({ + // ignore: avoid-dynamic, mirrors types of [VmServiceFactory]. + required Stream /*String|List*/ inStream, + required void Function(String message) writeMessage, + Log? log, + DisposeHandler? disposeHandler, + Future? streamClosed, + String? wsUri, + bool trackFutures = false, + }) => VmServiceWrapper.defaultFactory( + inStream: inStream, + writeMessage: writeMessage, + log: log, + disposeHandler: disposeHandler, + streamClosed: streamClosed, + wsUri: wsUri, + trackFutures: integrationTestMode, + ), ); await serviceConnection.serviceManager.vmServiceOpened( @@ -162,10 +162,7 @@ abstract class FrameworkCore { } static void _defaultErrorReporter(String title, Object error) { - notificationService.pushError( - '$title, $error', - isReportable: false, - ); + notificationService.pushError('$title, $error', isReportable: false); } } @@ -191,9 +188,9 @@ Future _initDTDConnection() async { ); if (dtdManager.connection.value != null) { - FrameworkCore._themeManager = - EditorThemeManager(dtdManager.connection.value!) - ..listenForThemeChanges(); + FrameworkCore._themeManager = EditorThemeManager( + dtdManager.connection.value!, + )..listenForThemeChanges(); } } else { _log.info('No DTD uri provided from the server during initialization.'); diff --git a/packages/devtools_app/lib/src/framework/home_screen.dart b/packages/devtools_app/lib/src/framework/home_screen.dart index 136a65331dd..2a0ca507d21 100644 --- a/packages/devtools_app/lib/src/framework/home_screen.dart +++ b/packages/devtools_app/lib/src/framework/home_screen.dart @@ -27,10 +27,10 @@ import 'framework_core.dart'; class HomeScreen extends Screen { HomeScreen({this.sampleData = const []}) - : super.fromMetaData( - ScreenMetaData.home, - titleGenerator: () => devToolsTitle.value, - ); + : super.fromMetaData( + ScreenMetaData.home, + titleGenerator: () => devToolsTitle.value, + ); static final id = ScreenMetaData.home.id; @@ -64,7 +64,7 @@ class _HomeScreenBodyState extends State with AutoDisposeMixin { Widget build(BuildContext context) { final connected = serviceConnection.serviceManager.connectedState.value.connected && - serviceConnection.serviceManager.connectedAppInitialized; + serviceConnection.serviceManager.connectedAppInitialized; return Scrollbar( child: ListView( children: [ @@ -104,8 +104,8 @@ class ConnectionSection extends StatelessWidget { minScreenWidthForTextBeforeScaling: _primaryMinScreenWidthForTextBeforeScaling, routerDelegate: DevToolsRouterDelegate.of(context), - onPressed: () => - Navigator.of(context, rootNavigator: true).pop('dialog'), + onPressed: + () => Navigator.of(context, rootNavigator: true).pop('dialog'), ), ], child: const ConnectedAppSummary(narrowView: false), @@ -137,12 +137,7 @@ class LandingScreenSection extends StatelessWidget { children: [ Row( children: [ - Expanded( - child: Text( - title, - style: textTheme.headlineMedium, - ), - ), + Expanded(child: Text(title, style: textTheme.headlineMedium)), ...actions, ], ), @@ -239,10 +234,7 @@ class _ConnectInputState extends State with BlockingActionMixin { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - 'Connect to a Running App', - style: textTheme.titleMedium, - ), + Text('Connect to a Running App', style: textTheme.titleMedium), const SizedBox(height: denseRowSpacing), Text( 'Enter a URL to a running Dart or Flutter application', @@ -261,10 +253,7 @@ class _ConnectInputState extends State with BlockingActionMixin { } Future _connectHelper() async { - ga.select( - gac.home, - gac.HomeScreenEvents.connectToApp.name, - ); + ga.select(gac.home, gac.HomeScreenEvents.connectToApp.name); final uri = connectDialogController.text; if (uri.isEmpty) { @@ -286,11 +275,13 @@ class _ConnectInputState extends State with BlockingActionMixin { // intuitive that we don't want to just cancel the route change or // notification if we are already on a different screen. final routerDelegate = DevToolsRouterDelegate.of(context); - final connected = - await FrameworkCore.initVmService(serviceUriAsString: uri); + final connected = await FrameworkCore.initVmService( + serviceUriAsString: uri, + ); if (connected) { - final connectedUri = - Uri.parse(serviceConnection.serviceManager.serviceUri!); + final connectedUri = Uri.parse( + serviceConnection.serviceManager.serviceUri!, + ); await routerDelegate.updateArgsIfChanged({'uri': '$connectedUri'}); final shortUri = connectedUri.replace(path: ''); notificationService.push('Successfully connected to $shortUri.'); @@ -304,10 +295,7 @@ class _ConnectInputState extends State with BlockingActionMixin { } class SampleDataDropDownButton extends StatefulWidget { - const SampleDataDropDownButton({ - super.key, - this.sampleData = const [], - }); + const SampleDataDropDownButton({super.key, this.sampleData = const []}); final List sampleData; @@ -325,19 +313,21 @@ class _SampleDataDropDownButtonState extends State { children: [ RoundedDropDownButton( value: value, - items: [ - for (final data in widget.sampleData) _buildMenuItem(data), - ], - onChanged: (file) => setState(() { - value = file; - }), + items: [for (final data in widget.sampleData) _buildMenuItem(data)], + onChanged: + (file) => setState(() { + value = file; + }), ), const SizedBox(width: defaultSpacing), ElevatedButton( - onPressed: value == null - ? null - : () => Provider.of(context, listen: false) - .importData(value!), + onPressed: + value == null + ? null + : () => Provider.of( + context, + listen: false, + ).importData(value!), child: const MaterialIconLabel( label: 'Load sample data', iconData: Icons.file_upload, diff --git a/packages/devtools_app/lib/src/framework/initializer.dart b/packages/devtools_app/lib/src/framework/initializer.dart index fd16af6d931..ffc9fb0d1f8 100644 --- a/packages/devtools_app/lib/src/framework/initializer.dart +++ b/packages/devtools_app/lib/src/framework/initializer.dart @@ -79,9 +79,10 @@ class _InitializerState extends State children: [ const Spacer(), CenteredMessage( - message: _showConnectToNewAppButton - ? 'Cannot connect to VM service.' - : 'Waiting for VM service connection...', + message: + _showConnectToNewAppButton + ? 'Cannot connect to VM service.' + : 'Waiting for VM service connection...', ), if (_showConnectToNewAppButton) ...[ const SizedBox(height: defaultSpacing), diff --git a/packages/devtools_app/lib/src/framework/notifications_view.dart b/packages/devtools_app/lib/src/framework/notifications_view.dart index 43f4f7c1e6b..6c819b23fdb 100644 --- a/packages/devtools_app/lib/src/framework/notifications_view.dart +++ b/packages/devtools_app/lib/src/framework/notifications_view.dart @@ -69,10 +69,7 @@ class _NotificationsState extends State<_Notifications> with AutoDisposeMixin { Overlay.of(context).insert(_overlayEntry!); }); - addAutoDisposeListener( - notificationService.newTasks, - _processQueues, - ); + addAutoDisposeListener(notificationService.newTasks, _processQueues); } _processQueues(); @@ -99,10 +96,7 @@ class _NotificationsState extends State<_Notifications> with AutoDisposeMixin { void _push(NotificationMessage message) { setState(() { _notifications.add( - _Notification( - message: message, - remove: _removeNotification, - ), + _Notification(message: message, remove: _removeNotification), ); _overlayEntry?.markNeedsBuild(); }); @@ -145,9 +139,8 @@ class _NotificationsState extends State<_Notifications> with AutoDisposeMixin { } class _NotificationOverlay extends StatelessWidget { - const _NotificationOverlay({ - required List<_Notification> notifications, - }) : _notifications = notifications; + const _NotificationOverlay({required List<_Notification> notifications}) + : _notifications = notifications; final List<_Notification> _notifications; @@ -179,10 +172,7 @@ class _NotificationOverlay extends StatelessWidget { } class _Notification extends StatefulWidget { - const _Notification({ - required this.message, - required this.remove, - }); + const _Notification({required this.message, required this.remove}); final NotificationMessage message; final void Function(_Notification) remove; @@ -204,10 +194,7 @@ class _NotificationState extends State<_Notification> duration: const Duration(milliseconds: 400), vsync: this, ); - curve = CurvedAnimation( - parent: controller, - curve: Curves.easeInOutCirc, - ); + curve = CurvedAnimation(parent: controller, curve: Curves.easeInOutCirc); // Set up a timer that reverses the entrance animation, and tells the widget // to remove itself when the exit animation is completed. @@ -239,16 +226,14 @@ class _NotificationState extends State<_Notification> return AnimatedBuilder( animation: controller, builder: (context, child) { - return Opacity( - opacity: curve.value, - child: child, - ); + return Opacity(opacity: curve.value, child: child); }, child: Card( color: theme.colorScheme.secondaryContainer, margin: const EdgeInsets.only(bottom: densePadding), child: DefaultTextStyle( - style: theme.snackBarTheme.contentTextStyle ?? + style: + theme.snackBarTheme.contentTextStyle ?? theme.textTheme.titleMedium!, child: Padding( padding: const EdgeInsets.all(denseSpacing), @@ -257,24 +242,18 @@ class _NotificationState extends State<_Notification> children: [ widget.message.isDismissible ? Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Flexible( - child: _NotificationMessage( - widget: widget, - ), - ), - _DismissAction( - onPressed: () { - widget.remove(widget); - }, - ), - ], - ) - : _NotificationMessage( - widget: widget, - ), + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible(child: _NotificationMessage(widget: widget)), + _DismissAction( + onPressed: () { + widget.remove(widget); + }, + ), + ], + ) + : _NotificationMessage(widget: widget), const SizedBox(height: defaultSpacing), _NotificationActions(actions: widget.message.actions), ], @@ -287,9 +266,7 @@ class _NotificationState extends State<_Notification> } class _DismissAction extends StatelessWidget { - const _DismissAction({ - required this.onPressed, - }); + const _DismissAction({required this.onPressed}); final void Function() onPressed; @@ -297,28 +274,22 @@ class _DismissAction extends StatelessWidget { Widget build(BuildContext context) { return Align( alignment: Alignment.topRight, - child: IconButton( - icon: const Icon( - Icons.close, - ), - onPressed: onPressed, - ), + child: IconButton(icon: const Icon(Icons.close), onPressed: onPressed), ); } } class _NotificationMessage extends StatelessWidget { - const _NotificationMessage({ - required this.widget, - }); + const _NotificationMessage({required this.widget}); final _Notification widget; @override Widget build(BuildContext context) { final theme = Theme.of(context); - final textStyle = - theme.regularTextStyleWithColor(theme.colorScheme.onSecondaryContainer); + final textStyle = theme.regularTextStyleWithColor( + theme.colorScheme.onSecondaryContainer, + ); return Padding( padding: const EdgeInsets.only( left: denseSpacing, @@ -327,9 +298,10 @@ class _NotificationMessage extends StatelessWidget { ), child: Text( widget.message.text, - style: widget.message.isError - ? textStyle.copyWith(color: theme.colorScheme.error) - : textStyle, + style: + widget.message.isError + ? textStyle.copyWith(color: theme.colorScheme.error) + : textStyle, overflow: TextOverflow.visible, maxLines: 10, ), diff --git a/packages/devtools_app/lib/src/framework/release_notes/release_notes.dart b/packages/devtools_app/lib/src/framework/release_notes/release_notes.dart index b7740342432..03ba3928119 100644 --- a/packages/devtools_app/lib/src/framework/release_notes/release_notes.dart +++ b/packages/devtools_app/lib/src/framework/release_notes/release_notes.dart @@ -39,14 +39,12 @@ const _releaseNotesPath = '/f/devtools-releases.json'; final _flutterDocsSite = Uri.https('docs.flutter.dev'); class ReleaseNotesViewer extends SidePanelViewer { - const ReleaseNotesViewer({ - required super.controller, - super.child, - }) : super( - key: releaseNotesKey, - title: 'What\'s new in DevTools?', - textIfMarkdownDataEmpty: 'Stay tuned for updates.', - ); + const ReleaseNotesViewer({required super.controller, super.child}) + : super( + key: releaseNotesKey, + title: 'What\'s new in DevTools?', + textIfMarkdownDataEmpty: 'Stay tuned for updates.', + ); } class ReleaseNotesController extends SidePanelController { @@ -121,8 +119,9 @@ class ReleaseNotesController extends SidePanelController { // Release notes will be hosted on the Flutter website with a version number // that does not contain any build metadata. final parsedDevToolsVersion = SemanticVersion.parse(devToolsVersion); - final checkVersion = - latestVersionToCheckForReleaseNotes(parsedDevToolsVersion); + final checkVersion = latestVersionToCheckForReleaseNotes( + parsedDevToolsVersion, + ); _log.fine( 'attempting to fetch and show release notes for DevTools $checkVersion ' @@ -174,8 +173,10 @@ class ReleaseNotesController extends SidePanelController { } catch (_) { // This can very infrequently fail due to CDN or caching issues, // or if the upstream file has an incorrect link. - _log.info('Failed to retrieve release notes for v$releaseToCheck, ' - 'despite indication it is live at $releaseNotePath.'); + _log.info( + 'Failed to retrieve release notes for v$releaseToCheck, ' + 'despite indication it is live at $releaseNotePath.', + ); // If we couldn't retrieve this page, keep going to // try with earlier patch versions. continue; @@ -190,9 +191,7 @@ class ReleaseNotesController extends SidePanelController { toggleVisibility(true); if (server.isDevToolsServerAvailable) { // Only set the last release notes version if we are not debugging. - unawaited( - server.setLastShownReleaseNotesVersion(releaseToCheck), - ); + unawaited(server.setLastShownReleaseNotesVersion(releaseToCheck)); } return; } diff --git a/packages/devtools_app/lib/src/framework/report_feedback_button.dart b/packages/devtools_app/lib/src/framework/report_feedback_button.dart index e1e63cdd400..28af2736afc 100644 --- a/packages/devtools_app/lib/src/framework/report_feedback_button.dart +++ b/packages/devtools_app/lib/src/framework/report_feedback_button.dart @@ -16,19 +16,16 @@ import '../shared/utils.dart'; /// browser. class ReportFeedbackButton extends ScaffoldAction { ReportFeedbackButton({super.key, super.color}) - : super( - icon: Icons.bug_report_outlined, - tooltip: 'Report feedback', - onPressed: (_) { - ga.select( - gac.devToolsMain, - gac.feedbackButton, - ); - unawaited( - launchUrlWithErrorHandling( - devToolsEnvironmentParameters.issueTrackerLink().url, - ), - ); - }, - ); + : super( + icon: Icons.bug_report_outlined, + tooltip: 'Report feedback', + onPressed: (_) { + ga.select(gac.devToolsMain, gac.feedbackButton); + unawaited( + launchUrlWithErrorHandling( + devToolsEnvironmentParameters.issueTrackerLink().url, + ), + ); + }, + ); } diff --git a/packages/devtools_app/lib/src/framework/scaffold.dart b/packages/devtools_app/lib/src/framework/scaffold.dart index d8a441b2458..9181290011f 100644 --- a/packages/devtools_app/lib/src/framework/scaffold.dart +++ b/packages/devtools_app/lib/src/framework/scaffold.dart @@ -50,33 +50,33 @@ class DevToolsScaffold extends StatefulWidget { EmbedMode embedMode = EmbedMode.none, List? actions, }) : this( - key: key, - screens: [SimpleScreen(child)], - actions: actions, - embedMode: embedMode, - ); + key: key, + screens: [SimpleScreen(child)], + actions: actions, + embedMode: embedMode, + ); static List defaultActions({Color? color}) => [ - OpenSettingsAction(color: color), - if (FeatureFlags.devToolsExtensions && - !DevToolsQueryParams.load().hideExtensions) - ExtensionSettingsAction(color: color), - ReportFeedbackButton(color: color), - OpenAboutAction(color: color), - ]; + OpenSettingsAction(color: color), + if (FeatureFlags.devToolsExtensions && + !DevToolsQueryParams.load().hideExtensions) + ExtensionSettingsAction(color: color), + ReportFeedbackButton(color: color), + OpenAboutAction(color: color), + ]; /// The padding around the content in the DevTools UI. EdgeInsets get appPadding => EdgeInsets.fromLTRB( - horizontalPadding.left, - isEmbedded() ? 2.0 : intermediateSpacing, - horizontalPadding.right, - isEmbedded() ? 2.0 : intermediateSpacing, - ); + horizontalPadding.left, + isEmbedded() ? 2.0 : intermediateSpacing, + horizontalPadding.right, + isEmbedded() ? 2.0 : intermediateSpacing, + ); /// Horizontal padding around the content in the DevTools UI. static EdgeInsets get horizontalPadding => EdgeInsets.symmetric( - horizontal: isEmbedded() ? densePadding : largeSpacing, - ); + horizontal: isEmbedded() ? densePadding : largeSpacing, + ); /// All of the [Screen]s that it's possible to navigate to from this Scaffold. final List screens; @@ -138,17 +138,19 @@ class DevToolsScaffoldState extends State // Stay on the current tab if possible when the collection of tabs changes. if (_tabController != null && widget.screens.contains(oldWidget.screens[_tabController!.index])) { - newIndex = - widget.screens.indexOf(oldWidget.screens[_tabController!.index]); + newIndex = widget.screens.indexOf( + oldWidget.screens[_tabController!.index], + ); } // Create a new tab controller to reflect the changed tabs. _setupTabController(startingIndex: newIndex); } else if (widget.screens[_tabController!.index].screenId != widget.page) { // If the page changed (eg. the route was modified by pressing back in the // browser), animate to the new one. - var newIndex = widget.page == null - ? 0 // When there's no supplied page, we show the first one. - : widget.screens.indexWhere((t) => t.screenId == widget.page); + var newIndex = + widget.page == null + ? 0 // When there's no supplied page, we show the first one. + : widget.screens.indexWhere((t) => t.screenId == widget.page); // Ensure the returned index is in range, otherwise set to 0. if (newIndex == -1) { newIndex = 0; @@ -182,8 +184,9 @@ class DevToolsScaffoldState extends State ); if (widget.page != null) { - final initialIndex = - widget.screens.indexWhere((screen) => screen.screenId == widget.page); + final initialIndex = widget.screens.indexWhere( + (screen) => screen.screenId == widget.page, + ); if (initialIndex != -1) { _tabController!.index = initialIndex; } @@ -243,8 +246,9 @@ class DevToolsScaffoldState extends State void _showPageById(String pageId) { final existingTabIndex = _tabController!.index; - final newIndex = - widget.screens.indexWhere((screen) => screen.screenId == pageId); + final newIndex = widget.screens.indexWhere( + (screen) => screen.screenId == pageId, + ); if (newIndex != -1 && newIndex != existingTabIndex) { DevToolsRouterDelegate.of(context).navigateIfNotCurrent(pageId); @@ -278,11 +282,7 @@ class DevToolsScaffoldState extends State Align( alignment: Alignment.topLeft, child: FocusScope( - child: AnalyticsPrompt( - child: BannerMessages( - screen: screen, - ), - ), + child: AnalyticsPrompt(child: BannerMessages(screen: screen)), ), ), ]; @@ -296,7 +296,9 @@ class DevToolsScaffoldState extends State ), if (serviceConnection.serviceManager.connectedAppInitialized && !serviceConnection - .serviceManager.connectedApp!.isProfileBuildNow! && + .serviceManager + .connectedApp! + .isProfileBuildNow! && !offlineDataController.showingOfflineData.value && _currentScreen.showFloatingDebuggerControls) Container( @@ -311,65 +313,68 @@ class DevToolsScaffoldState extends State builder: (context, _) { final showConsole = serviceConnection.serviceManager.connectedAppInitialized && - !offlineDataController.showingOfflineData.value && - _currentScreen.showConsole(widget.embedMode); + !offlineDataController.showingOfflineData.value && + _currentScreen.showConsole(widget.embedMode); final containsSingleSimpleScreen = widget.screens.length == 1 && widget.screens.first is SimpleScreen; - final showAppBar = widget.embedMode == EmbedMode.none || + final showAppBar = + widget.embedMode == EmbedMode.none || (widget.embedMode == EmbedMode.embedMany && !containsSingleSimpleScreen); return DragAndDrop( handleDrop: _importController.importData, child: KeyboardShortcuts( - keyboardShortcuts: _currentScreen.buildKeyboardShortcuts( - context, - ), + keyboardShortcuts: _currentScreen.buildKeyboardShortcuts(context), child: Scaffold( - appBar: showAppBar - ? PreferredSize( - preferredSize: Size.fromHeight(defaultToolbarHeight), - // Place the AppBar inside of a Hero widget to keep it the same across - // route transitions. - child: Hero( - tag: _appBarTag, - child: DevToolsAppBar( - tabController: _tabController, - screens: widget.screens, - actions: widget.actions, + appBar: + showAppBar + ? PreferredSize( + preferredSize: Size.fromHeight(defaultToolbarHeight), + // Place the AppBar inside of a Hero widget to keep it the same across + // route transitions. + child: Hero( + tag: _appBarTag, + child: DevToolsAppBar( + tabController: _tabController, + screens: widget.screens, + actions: widget.actions, + ), ), - ), - ) - : null, + ) + : null, body: OutlineDecoration.onlyTop( child: Padding( padding: widget.appPadding, - child: showConsole - ? SplitPane( - axis: Axis.vertical, - splitters: [ - ConsolePaneHeader(), - ], - initialFractions: const [0.8, 0.2], - children: [ - Padding( - padding: const EdgeInsets.only( - bottom: intermediateSpacing, + child: + showConsole + ? SplitPane( + axis: Axis.vertical, + splitters: [ConsolePaneHeader()], + initialFractions: const [0.8, 0.2], + children: [ + Padding( + padding: const EdgeInsets.only( + bottom: intermediateSpacing, + ), + child: content, + ), + RoundedOutlinedBorder.onlyBottom( + child: const ConsolePane(), ), - child: content, - ), - RoundedOutlinedBorder.onlyBottom( - child: const ConsolePane(), - ), - ], - ) - : content, + ], + ) + : content, ), ), bottomNavigationBar: StatusLine( currentScreen: _currentScreen, isEmbedded: widget.embedMode.embedded, - isConnected: serviceConnection - .serviceManager.connectedState.value.connected && + isConnected: + serviceConnection + .serviceManager + .connectedState + .value + .connected && serviceConnection.serviceManager.connectedAppInitialized, ), ), @@ -426,11 +431,7 @@ class KeyboardShortcutsState extends State } class SimpleScreen extends Screen { - SimpleScreen(this.child) - : super( - id, - showFloatingDebuggerControls: false, - ); + SimpleScreen(this.child) : super(id, showFloatingDebuggerControls: false); static final id = ScreenMetaData.simple.id; diff --git a/packages/devtools_app/lib/src/framework/settings_dialog.dart b/packages/devtools_app/lib/src/framework/settings_dialog.dart index becc6981818..6eff9d691aa 100644 --- a/packages/devtools_app/lib/src/framework/settings_dialog.dart +++ b/packages/devtools_app/lib/src/framework/settings_dialog.dart @@ -19,18 +19,18 @@ import '../shared/server/server.dart'; class OpenSettingsAction extends ScaffoldAction { OpenSettingsAction({super.key, super.color}) - : super( - icon: Icons.settings_outlined, - tooltip: 'Settings', - onPressed: (context) { - unawaited( - showDialog( - context: context, - builder: (context) => const SettingsDialog(), - ), - ); - }, - ); + : super( + icon: Icons.settings_outlined, + tooltip: 'Settings', + onPressed: (context) { + unawaited( + showDialog( + context: context, + builder: (context) => const SettingsDialog(), + ), + ); + }, + ); } class SettingsDialog extends StatelessWidget { @@ -61,9 +61,10 @@ class SettingsDialog extends StatelessWidget { child: CheckboxSetting( title: 'Enable analytics', notifier: analyticsController.analyticsEnabled, - onChanged: (enable) => unawaited( - analyticsController.toggleAnalyticsEnabled(enable), - ), + onChanged: + (enable) => unawaited( + analyticsController.toggleAnalyticsEnabled(enable), + ), gaScreen: gac.settingsDialog, gaItem: gac.analytics, ), @@ -98,8 +99,9 @@ class SettingsDialog extends StatelessWidget { if (FeatureFlags.inspectorV2) Flexible( child: CheckboxSetting( - notifier: preferences.inspector.inspectorV2Enabled - as ValueNotifier, + notifier: + preferences.inspector.inspectorV2Enabled + as ValueNotifier, title: 'Enable the new Inspector', description: 'Try out the redesigned Flutter Inspector.', gaItem: gac.inspectorV2Enabled, @@ -111,9 +113,7 @@ class SettingsDialog extends StatelessWidget { const _VerboseLoggingSetting(), ], ), - actions: const [ - DialogCloseButton(), - ], + actions: const [DialogCloseButton()], ); } } @@ -146,10 +146,11 @@ class _VerboseLoggingSetting extends StatelessWidget { gaSelection: gac.copyLogs, minScreenWidthForTextBeforeScaling: _minScreenWidthForTextBeforeScaling, - onPressed: () async => await copyToClipboard( - LogStorage.root.toString(), - successMessage: 'Successfully copied logs', - ), + onPressed: + () async => await copyToClipboard( + LogStorage.root.toString(), + successMessage: 'Successfully copied logs', + ), ), const SizedBox(width: denseSpacing), ClearButton( diff --git a/packages/devtools_app/lib/src/framework/status_line.dart b/packages/devtools_app/lib/src/framework/status_line.dart index 298d92181c7..f89656a7374 100644 --- a/packages/devtools_app/lib/src/framework/status_line.dart +++ b/packages/devtools_app/lib/src/framework/status_line.dart @@ -38,9 +38,9 @@ class StatusLine extends StatelessWidget { /// The padding around the footer in the DevTools UI. EdgeInsets get padding => const EdgeInsets.symmetric( - horizontal: defaultSpacing, - vertical: densePadding, - ); + horizontal: defaultSpacing, + vertical: densePadding, + ); @override Widget build(BuildContext context) { @@ -136,9 +136,10 @@ class StatusLine extends StatelessWidget { description = vm.deviceDisplay; } - final color = highlightForConnection - ? theme.colorScheme.onPrimary - : theme.regularTextStyle.color; + final color = + highlightForConnection + ? theme.colorScheme.onPrimary + : theme.regularTextStyle.color; return Row( mainAxisAlignment: MainAxisAlignment.end, @@ -149,11 +150,12 @@ class StatusLine extends StatelessWidget { return SizedBox( width: smallProgressSize, height: smallProgressSize, - child: isBusy - ? SmallCircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(color), - ) - : const SizedBox(), + child: + isBusy + ? SmallCircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(color), + ) + : const SizedBox(), ); }, ), @@ -162,10 +164,12 @@ class StatusLine extends StatelessWidget { message: 'Connected device', child: Text( description, - style: highlightForConnection - ? theme.regularTextStyle - .copyWith(color: theme.colorScheme.onPrimary) - : theme.regularTextStyle, + style: + highlightForConnection + ? theme.regularTextStyle.copyWith( + color: theme.colorScheme.onPrimary, + ) + : theme.regularTextStyle, overflow: TextOverflow.clip, ), ), @@ -175,18 +179,13 @@ class StatusLine extends StatelessWidget { return child!; } }, - child: screenWidth <= MediaSize.xxs - ? DevToolsTooltip( - message: noConnectionMsg, - child: Icon( - Icons.warning_amber_rounded, - size: actionsIconSize, - ), - ) - : Text( - noConnectionMsg, - style: theme.regularTextStyle, - ), + child: + screenWidth <= MediaSize.xxs + ? DevToolsTooltip( + message: noConnectionMsg, + child: Icon(Icons.warning_amber_rounded, size: actionsIconSize), + ) + : Text(noConnectionMsg, style: theme.regularTextStyle), ); } } @@ -216,7 +215,8 @@ class DocumentationLink extends StatelessWidget { icon: Icons.library_books_outlined, link: GaLink( display: screenWidth <= MediaSize.xs ? 'Docs' : 'Read docs', - url: screen.docsUrl ?? + url: + screen.docsUrl ?? 'https://docs.flutter.dev/tools/devtools/$docPageId', gaScreenName: screen.screenId, gaSelectedItemDescription: gac.documentationLink, @@ -270,10 +270,7 @@ class IsolateSelector extends StatelessWidget { Widget build(BuildContext context) { final isolateManager = serviceConnection.serviceManager.isolateManager; return MultiValueListenableBuilder( - listenables: [ - isolateManager.isolates, - isolateManager.selectedIsolate, - ], + listenables: [isolateManager.isolates, isolateManager.selectedIsolate], builder: (context, values, _) { final theme = Theme.of(context); final isolates = values.first as List; @@ -282,17 +279,17 @@ class IsolateSelector extends StatelessWidget { tooltip: 'Selected Isolate', initialValue: selectedIsolateRef, onSelected: isolateManager.selectIsolate, - itemBuilder: (BuildContext context) => isolates.map( - (ref) { - return PopupMenuItem( - value: ref, - child: IsolateOption( - ref, - color: theme.colorScheme.onSurface, - ), - ); - }, - ).toList(), + itemBuilder: + (BuildContext context) => + isolates.map((ref) { + return PopupMenuItem( + value: ref, + child: IsolateOption( + ref, + color: theme.colorScheme.onSurface, + ), + ); + }).toList(), child: IsolateOption( isolateManager.selectedIsolate.value, color: theme.colorScheme.onPrimary, @@ -304,11 +301,7 @@ class IsolateSelector extends StatelessWidget { } class IsolateOption extends StatelessWidget { - const IsolateOption( - this.ref, { - required this.color, - super.key, - }); + const IsolateOption(this.ref, {required this.color, super.key}); final IsolateRef? ref; diff --git a/packages/devtools_app/lib/src/framework/theme_manager.dart b/packages/devtools_app/lib/src/framework/theme_manager.dart index 4e582ef279a..54951f02c1f 100644 --- a/packages/devtools_app/lib/src/framework/theme_manager.dart +++ b/packages/devtools_app/lib/src/framework/theme_manager.dart @@ -44,11 +44,10 @@ class EditorThemeManager extends DisposableController // Handle themeChanged from postMessage. autoDisposeStreamSubscription( onPostMessage.listen((event) { - if (event.data - case { - 'method': 'editor.themeChanged', - 'params': {'theme': final Map themeJson} - }) { + if (event.data case { + 'method': 'editor.themeChanged', + 'params': {'theme': final Map themeJson}, + }) { try { _updateTheme( EditorTheme.fromJson(themeJson.cast()), @@ -73,8 +72,10 @@ class EditorThemeManager extends DisposableController } if (newTheme.backgroundColor != null) { - final newBackgroundColor = - tryParseColor(newTheme.backgroundColor!, logger: _log); + final newBackgroundColor = tryParseColor( + newTheme.backgroundColor!, + logger: _log, + ); if (newBackgroundColor != null && newBackgroundColor != currentTheme.backgroundColor) { updateQueryParameter( @@ -85,8 +86,10 @@ class EditorThemeManager extends DisposableController } if (newTheme.foregroundColor != null) { - final newForegroundColor = - tryParseColor(newTheme.foregroundColor!, logger: _log); + final newForegroundColor = tryParseColor( + newTheme.foregroundColor!, + logger: _log, + ); if (newForegroundColor != null && newForegroundColor != currentTheme.foregroundColor) { updateQueryParameter( diff --git a/packages/devtools_app/lib/src/screens/app_size/app_size_controller.dart b/packages/devtools_app/lib/src/screens/app_size/app_size_controller.dart index 237fdd156e4..36be9945f1a 100644 --- a/packages/devtools_app/lib/src/screens/app_size/app_size_controller.dart +++ b/packages/devtools_app/lib/src/screens/app_size/app_size_controller.dart @@ -101,8 +101,9 @@ class AppSizeController { /// The node set as the analysis tab root. /// /// Used to build the treemap and the tree table for the analysis tab. - final analysisRoot = - ValueNotifier>(Selection.empty()); + final analysisRoot = ValueNotifier>( + Selection.empty(), + ); ValueListenable get isDeferredApp => _isDeferredApp; final _isDeferredApp = ValueNotifier(false); @@ -121,13 +122,14 @@ class AppSizeController { final programInfoNode = _analysisCallGraph?.program.lookup(newAnalysisRoot.packagePath()) ?? - _analysisCallGraph?.program.root; + _analysisCallGraph?.program.root; // If [programInfoNode is null, we don't have any call graph information // about [newRoot]. if (programInfoNode != null) { - _analysisCallGraphRoot.value = - _analysisCallGraph!.lookup(programInfoNode); + _analysisCallGraphRoot.value = _analysisCallGraph!.lookup( + programInfoNode, + ); } } @@ -169,8 +171,9 @@ class AppSizeController { } else if (oldProgramInfoNode != null) { _diffCallGraphRoot.value = _oldDiffCallGraph!.lookup(oldProgramInfoNode); } else if (newProgramInfoNodeRoot != null) { - _diffCallGraphRoot.value = - _newDiffCallGraph!.lookup(newProgramInfoNodeRoot); + _diffCallGraphRoot.value = _newDiffCallGraph!.lookup( + newProgramInfoNodeRoot, + ); } } @@ -272,8 +275,9 @@ class AppSizeController { return _activeDiffTreeType; } - final _activeDiffTreeType = - ValueNotifier(DiffTreeType.combined); + final _activeDiffTreeType = ValueNotifier( + DiffTreeType.combined, + ); void changeActiveDiffTreeType(DiffTreeType newDiffTreeType) { _activeDiffTreeType.value = newDiffTreeType; @@ -374,13 +378,12 @@ class AppSizeController { return jsonFile; } - Map _extractDeferredUnits( - Map jsonFile, - ) { + Map _extractDeferredUnits(Map jsonFile) { if (_hasDeferredInfo(jsonFile)) { - jsonFile['children'] = _extractChildren(jsonFile) - .where((child) => child['isDeferred'] == true) - .toList(); + jsonFile['children'] = + _extractChildren( + jsonFile, + ).where((child) => child['isDeferred'] == true).toList(); jsonFile['n'] = _deferredNodeName; } return jsonFile; @@ -445,15 +448,19 @@ class AppSizeController { newEntireAppFileJson = _wrapInArtificialRoot(newFileJson); } - final oldMainOnlyFileJson = - _extractMainUnit(Map.from(oldEntireAppFileJson)); - final newMainOnlyFileJson = - _extractMainUnit(Map.from(newEntireAppFileJson)); + final oldMainOnlyFileJson = _extractMainUnit( + Map.from(oldEntireAppFileJson), + ); + final newMainOnlyFileJson = _extractMainUnit( + Map.from(newEntireAppFileJson), + ); - final oldDeferredOnlyFileJson = - _extractDeferredUnits(Map.from(oldEntireAppFileJson)); - final newDeferredOnlyFileJson = - _extractDeferredUnits(Map.from(newEntireAppFileJson)); + final oldDeferredOnlyFileJson = _extractDeferredUnits( + Map.from(oldEntireAppFileJson), + ); + final newDeferredOnlyFileJson = _extractDeferredUnits( + Map.from(newEntireAppFileJson), + ); diffMap = _generateDiffMapFromAnalyzeSizeFiles( oldFileJson: oldEntireAppFileJson, @@ -683,9 +690,10 @@ class AppSizeController { // Given a child, build its subtree. for (final child in rawChildren) { - final childTreemapNode = showDiff - ? generateDiffTree(child, diffTreeType!) - : generateTree(child); + final childTreemapNode = + showDiff + ? generateDiffTree(child, diffTreeType!) + : generateTree(child); if (childTreemapNode == null) { continue; } @@ -697,11 +705,11 @@ class AppSizeController { return totalByteSize == 0 && skipNodesWithNoByteSizeChange ? null : _buildNode( - treeJson, - totalByteSize, - children: treemapNodeChildren, - showDiff: showDiff, - ); + treeJson, + totalByteSize, + children: treemapNodeChildren, + showDiff: showDiff, + ); } TreemapNode _buildNode( @@ -748,8 +756,9 @@ extension AppSizeJsonFileExtension on DevToolsJsonFile { final data = this.data; if (data is Map) { final type = data['type'] as String?; - return AppSizeJsonFileExtension._supportedAnalyzeSizePlatforms - .contains(type); + return AppSizeJsonFileExtension._supportedAnalyzeSizePlatforms.contains( + type, + ); } return false; } 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 037ae701777..c32c75d15e1 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 @@ -203,14 +203,12 @@ class _AppSizeBodyState extends State AppUnitDropdown( value: controller.selectedAppUnit.value, onChanged: (newAppUnit) { - setState( - () { - controller.changeSelectedAppUnit( - newAppUnit!, - currentTab.key!, - ); - }, - ); + setState(() { + controller.changeSelectedAppUnit( + newAppUnit!, + currentTab.key!, + ); + }); }, ), if (currentTab.key == AppSizeScreen.diffTabKey) ...[ @@ -226,9 +224,7 @@ class _AppSizeBodyState extends State ClearButton( gaScreen: gac.appSize, gaSelection: gac.clear, - onPressed: () => controller.clear( - currentTab.key!, - ), + onPressed: () => controller.clear(currentTab.key!), ), ], ), @@ -236,10 +232,7 @@ class _AppSizeBodyState extends State child: TabBarView( physics: defaultTabBarViewPhysics, controller: _tabController, - children: const [ - AnalysisView(), - DiffView(), - ], + children: const [AnalysisView(), DiffView()], ), ), ], @@ -327,7 +320,8 @@ class AnalysisView extends StatefulWidget { // TODO(kenz): add links to documentation on how to generate these files, and // mention the import file button once it is hooked up to a file picker. - static const importInstructions = 'Drag and drop an AOT snapshot or' + static const importInstructions = + 'Drag and drop an AOT snapshot or' ' size analysis file for debugging'; @override @@ -362,19 +356,20 @@ class _AnalysisViewState extends State return Column( children: [ Expanded( - child: analysisRootLocal == null - ? _buildImportFileView() - : _AppSizeView( - title: _generateSingleFileHeaderText(), - treemapKey: AppSizeScreen.analysisViewTreemapKey, - treemapRoot: analysisRootLocal, - onRootChangedCallback: controller.changeAnalysisRoot, - analysisTable: AppSizeAnalysisTable( - rootNode: analysisRootLocal.root, - controller: controller, + child: + analysisRootLocal == null + ? _buildImportFileView() + : _AppSizeView( + title: _generateSingleFileHeaderText(), + treemapKey: AppSizeScreen.analysisViewTreemapKey, + treemapRoot: analysisRootLocal, + onRootChangedCallback: controller.changeAnalysisRoot, + analysisTable: AppSizeAnalysisTable( + rootNode: analysisRootLocal.root, + controller: controller, + ), + callGraphRoot: controller.analysisCallGraphRoot.value, ), - callGraphRoot: controller.analysisCallGraphRoot.value, - ), ), ], ); @@ -382,9 +377,10 @@ class _AnalysisViewState extends State String _generateSingleFileHeaderText() { final analysisFile = controller.analysisJsonFile.value!; - String output = analysisFile.isAnalyzeSizeFile - ? 'Total size analysis: ' - : 'Dart AOT snapshot: '; + String output = + analysisFile.isAnalyzeSizeFile + ? 'Total size analysis: ' + : 'Dart AOT snapshot: '; output += analysisFile.displayText; return output; } @@ -396,26 +392,26 @@ class _AnalysisViewState extends State return processing ? const CenteredMessage(message: AppSizeScreen.loadingMessage) : Column( - children: [ - Flexible( - child: FileImportContainer( - instructions: AnalysisView.importInstructions, - actionText: 'Analyze Size', - gaScreen: gac.appSize, - gaSelectionImport: gac.importFileSingle, - gaSelectionAction: gac.analyzeSingle, - onAction: (jsonFile) { - controller.loadTreeFromJsonFile( - jsonFile: jsonFile, - onError: (error) { - if (mounted) notificationService.push(error); - }, - ); - }, - ), + children: [ + Flexible( + child: FileImportContainer( + instructions: AnalysisView.importInstructions, + actionText: 'Analyze Size', + gaScreen: gac.appSize, + gaSelectionImport: gac.importFileSingle, + gaSelectionAction: gac.analyzeSingle, + onAction: (jsonFile) { + controller.loadTreeFromJsonFile( + jsonFile: jsonFile, + onError: (error) { + if (mounted) notificationService.push(error); + }, + ); + }, ), - ], - ); + ), + ], + ); }, ); } @@ -426,9 +422,11 @@ class DiffView extends StatefulWidget { // TODO(kenz): add links to documentation on how to generate these files, and // mention the import file button once it is hooked up to a file picker. - static const importOldInstructions = 'Drag and drop an original (old) AOT ' + static const importOldInstructions = + 'Drag and drop an original (old) AOT ' 'snapshot or size analysis file for debugging'; - static const importNewInstructions = 'Drag and drop a modified (new) AOT ' + static const importNewInstructions = + 'Drag and drop a modified (new) AOT ' 'snapshot or size analysis file for debugging'; @override @@ -465,16 +463,17 @@ class _DiffViewState extends State return Column( children: [ Expanded( - child: diffRootLocal == null - ? _buildImportDiffView() - : _AppSizeView( - title: _generateDualFileHeaderText(), - treemapKey: AppSizeScreen.diffViewTreemapKey, - treemapRoot: diffRootLocal, - onRootChangedCallback: controller.changeDiffRoot, - analysisTable: AppSizeDiffTable(rootNode: diffRootLocal), - callGraphRoot: controller.diffCallGraphRoot.value, - ), + child: + diffRootLocal == null + ? _buildImportDiffView() + : _AppSizeView( + title: _generateDualFileHeaderText(), + treemapKey: AppSizeScreen.diffViewTreemapKey, + treemapRoot: diffRootLocal, + onRootChangedCallback: controller.changeDiffRoot, + analysisTable: AppSizeDiffTable(rootNode: diffRootLocal), + callGraphRoot: controller.diffCallGraphRoot.value, + ), ), ], ); @@ -484,9 +483,10 @@ class _DiffViewState extends State final oldFile = controller.oldDiffJsonFile.value!; final newFile = controller.newDiffJsonFile.value!; String output = 'Diffing '; - output += oldFile.isAnalyzeSizeFile - ? 'total size analyses: ' - : 'Dart AOT snapshots: '; + output += + oldFile.isAnalyzeSizeFile + ? 'total size analyses: ' + : 'Dart AOT snapshots: '; output += oldFile.displayText; output += ' (OLD) vs (NEW) '; output += newFile.displayText; @@ -500,30 +500,31 @@ class _DiffViewState extends State return processing ? const CenteredMessage(message: AppSizeScreen.loadingMessage) : Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: DualFileImportContainer( - firstFileTitle: 'Old', - secondFileTitle: 'New', - // TODO(kenz): perhaps bold "original" and "modified". - firstInstructions: DiffView.importOldInstructions, - secondInstructions: DiffView.importNewInstructions, - actionText: 'Analyze Diff', - gaScreen: gac.appSize, - gaSelectionImportFirst: gac.importFileDiffFirst, - gaSelectionImportSecond: gac.importFileDiffSecond, - gaSelectionAction: gac.analyzeDiff, - onAction: (oldFile, newFile, onError) => - controller.loadDiffTreeFromJsonFiles( - oldFile: oldFile, - newFile: newFile, - onError: onError, - ), - ), + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: DualFileImportContainer( + firstFileTitle: 'Old', + secondFileTitle: 'New', + // TODO(kenz): perhaps bold "original" and "modified". + firstInstructions: DiffView.importOldInstructions, + secondInstructions: DiffView.importNewInstructions, + actionText: 'Analyze Diff', + gaScreen: gac.appSize, + gaSelectionImportFirst: gac.importFileDiffFirst, + gaSelectionImportSecond: gac.importFileDiffSecond, + gaSelectionAction: gac.analyzeDiff, + onAction: + (oldFile, newFile, onError) => + controller.loadDiffTreeFromJsonFiles( + oldFile: oldFile, + newFile: newFile, + onError: onError, + ), ), - ], - ); + ), + ], + ); }, ); } @@ -589,9 +590,7 @@ class _AppSizeView extends StatelessWidget { OutlineDecoration.onlyTop( child: Row( children: [ - Flexible( - child: analysisTable, - ), + Flexible(child: analysisTable), if (callGraphRoot != null) Flexible( child: OutlineDecoration.onlyLeft( diff --git a/packages/devtools_app/lib/src/screens/app_size/app_size_table.dart b/packages/devtools_app/lib/src/screens/app_size/app_size_table.dart index 17807d66dd7..a6eeb2c9852 100644 --- a/packages/devtools_app/lib/src/screens/app_size/app_size_table.dart +++ b/packages/devtools_app/lib/src/screens/app_size/app_size_table.dart @@ -19,18 +19,20 @@ class AppSizeAnalysisTable extends StatelessWidget { required AppSizeController controller, }) { final treeColumn = _NameColumn( - currentRootLevel: controller.isDeferredApp.value - ? rootNode.children.first.level - : rootNode.level, + currentRootLevel: + controller.isDeferredApp.value + ? rootNode.children.first.level + : rootNode.level, ); final sizeColumn = _SizeColumn(); final columns = List>.unmodifiable([ treeColumn, sizeColumn, _SizePercentageColumn( - totalSize: controller.isDeferredApp.value - ? rootNode.children[0].root.byteSize - : rootNode.root.byteSize, + totalSize: + controller.isDeferredApp.value + ? rootNode.children[0].root.byteSize + : rootNode.root.byteSize, ), ]); @@ -99,11 +101,11 @@ class _NameColumn extends TreeColumnData { class _SizeColumn extends ColumnData { _SizeColumn() - : super( - 'Size', - alignment: ColumnAlignment.right, - fixedWidthPx: scaleByFontFactor(100.0), - ); + : super( + 'Size', + alignment: ColumnAlignment.right, + fixedWidthPx: scaleByFontFactor(100.0), + ); @override Comparable getValue(TreemapNode dataObject) => dataObject.byteSize; @@ -123,11 +125,11 @@ class _SizeColumn extends ColumnData { class _SizePercentageColumn extends ColumnData { _SizePercentageColumn({required this.totalSize}) - : super( - '% of Total Size', - alignment: ColumnAlignment.right, - fixedWidthPx: scaleByFontFactor(100.0), - ); + : super( + '% of Total Size', + alignment: ColumnAlignment.right, + fixedWidthPx: scaleByFontFactor(100.0), + ); final int totalSize; @@ -156,12 +158,7 @@ class AppSizeDiffTable extends StatelessWidget { diffColumn, ]); - return AppSizeDiffTable._( - rootNode, - treeColumn, - diffColumn, - columns, - ); + return AppSizeDiffTable._(rootNode, treeColumn, diffColumn, columns); } const AppSizeDiffTable._( @@ -198,17 +195,17 @@ class AppSizeDiffTable extends StatelessWidget { // other columns. class _DiffColumn extends ColumnData { _DiffColumn() - : super( - 'Change', - alignment: ColumnAlignment.right, - fixedWidthPx: scaleByFontFactor(100.0), - ); + : super( + 'Change', + alignment: ColumnAlignment.right, + fixedWidthPx: scaleByFontFactor(100.0), + ); // Ensure sort by absolute size. @override int getValue(TreemapNode dataObject) => dataObject.unsignedByteSize; -// TODO(peterdjlee): Add up or down arrows indicating increase or decrease for display value. + // TODO(peterdjlee): Add up or down arrows indicating increase or decrease for display value. @override String getDisplayValue(TreemapNode dataObject) => dataObject.prettyByteSize(); diff --git a/packages/devtools_app/lib/src/screens/app_size/code_size_attribution.dart b/packages/devtools_app/lib/src/screens/app_size/code_size_attribution.dart index ad5573904b3..3989f65110c 100644 --- a/packages/devtools_app/lib/src/screens/app_size/code_size_attribution.dart +++ b/packages/devtools_app/lib/src/screens/app_size/code_size_attribution.dart @@ -31,16 +31,18 @@ class _CallGraphWithDominatorsState extends State { @override void initState() { super.initState(); - dominatorTreeRoot = - DominatorTreeNode.from(widget.callGraphRoot.dominatorRoot); + dominatorTreeRoot = DominatorTreeNode.from( + widget.callGraphRoot.dominatorRoot, + ); } @override void didUpdateWidget(covariant CallGraphWithDominators oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.callGraphRoot != widget.callGraphRoot) { - dominatorTreeRoot = - DominatorTreeNode.from(widget.callGraphRoot.dominatorRoot); + dominatorTreeRoot = DominatorTreeNode.from( + widget.callGraphRoot.dominatorRoot, + ); } } @@ -62,12 +64,13 @@ class _CallGraphWithDominatorsState extends State { ], ), Expanded( - child: showCallGraph - ? CallGraphView(node: widget.callGraphRoot) - : DominatorTree( - dominatorTreeRoot: dominatorTreeRoot, - selectedNode: widget.callGraphRoot, - ), + child: + showCallGraph + ? CallGraphView(node: widget.callGraphRoot) + : DominatorTree( + dominatorTreeRoot: dominatorTreeRoot, + selectedNode: widget.callGraphRoot, + ), ), ], ); @@ -225,9 +228,10 @@ class _CallGraphTable extends StatelessWidget { Widget build(BuildContext context) { return FlatTable( keyFactory: (CallGraphNode node) => ValueKey(node), - data: tableType == _CallGraphTableType.from - ? selectedNode.pred - : selectedNode.succ, + data: + tableType == _CallGraphTableType.from + ? selectedNode.pred + : selectedNode.succ, dataKey: tableType.dataKey, columns: [tableColumn], onItemSelected: onNodeSelected, @@ -311,9 +315,10 @@ class _PackageColumn extends TreeColumnData { extension CallGraphNodeDisplay on CallGraphNode { String get display { - final displayText = data is ProgramInfoNode - ? (data as ProgramInfoNode).qualifiedName - : data.toString(); + final displayText = + data is ProgramInfoNode + ? (data as ProgramInfoNode).qualifiedName + : data.toString(); if (displayText == '@shared') { // Special case '@shared' because this is the name of the call graph root, // and '@root' has a more intuitive meaning. 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 962b07459b8..45c3e56bdc6 100644 --- a/packages/devtools_app/lib/src/screens/debugger/breakpoint_manager.dart +++ b/packages/devtools_app/lib/src/screens/debugger/breakpoint_manager.dart @@ -27,7 +27,7 @@ class BreakpointManager with DisposerMixin { final _breakpoints = ValueNotifier>([]); ValueListenable> - get breakpointsWithLocation => _breakpointsWithLocation; + get breakpointsWithLocation => _breakpointsWithLocation; final _breakpointsWithLocation = ValueNotifier>([]); @@ -70,8 +70,9 @@ class BreakpointManager with DisposerMixin { return; } - final breakpointsForIsolate = - await _getBreakpointsForIsolate(_isolateRefId); + final breakpointsForIsolate = await _getBreakpointsForIsolate( + _isolateRefId, + ); if (breakpointsForIsolate.isNotEmpty) { // If the isolate already has breakpoints, then update them: await _updateBreakpoints( @@ -87,8 +88,9 @@ class BreakpointManager with DisposerMixin { } // Resume the isolate now that the breakpoints have been set: - await serviceConnection.serviceManager.isolateManager - .resumeIsolate(isolateRef); + await serviceConnection.serviceManager.isolateManager.resumeIsolate( + isolateRef, + ); } void clearCache({required bool isServiceShutdown}) { @@ -152,19 +154,20 @@ class BreakpointManager with DisposerMixin { _breakpointsWithLocation.value = []; } - void _updateAfterIsolateReload( - Event _, - ) async { + void _updateAfterIsolateReload(Event _) async { // TODO(devoncarew): We need to coordinate this with other debugger clients // as well as pause before re-setting the breakpoints. // Refresh the list of scripts. final previousScriptRefs = scriptManager.sortedScripts.value; - final currentScriptRefs = - await scriptManager.retrieveAndSortScripts(_isolateRef!); - final removedScripts = Set.of(previousScriptRefs) - .difference(Set.of(currentScriptRefs)); - final addedScripts = Set.of(currentScriptRefs) - .difference(Set.of(previousScriptRefs)); + final currentScriptRefs = await scriptManager.retrieveAndSortScripts( + _isolateRef!, + ); + final removedScripts = Set.of( + previousScriptRefs, + ).difference(Set.of(currentScriptRefs)); + final addedScripts = Set.of( + currentScriptRefs, + ).difference(Set.of(previousScriptRefs)); final breakpointsToRemove = []; // Find all breakpoints set in files where we have newer versions of those @@ -246,20 +249,19 @@ class BreakpointManager with DisposerMixin { required List breakpoints, required IsolateRef isolateRef, }) async { - final bpScriptUris = breakpoints.fold( - {}, - (scriptSet, breakpoint) { - final scriptUri = breakpoint.scriptUri; - if (scriptUri != null) { - scriptSet.add(scriptUri); - } - return scriptSet; - }, - ); + final bpScriptUris = breakpoints.fold({}, (scriptSet, breakpoint) { + final scriptUri = breakpoint.scriptUri; + if (scriptUri != null) { + scriptSet.add(scriptUri); + } + return scriptSet; + }); final newScripts = await scriptManager.retrieveAndSortScripts(isolateRef); - final scriptUriToRef = - newScripts.fold({}, (scriptMap, script) { + final scriptUriToRef = newScripts.fold({}, ( + scriptMap, + script, + ) { final scriptUri = script.uri; if (scriptUri != null && bpScriptUris.contains(scriptUri)) { scriptMap[scriptUri] = script; @@ -278,8 +280,10 @@ class BreakpointManager with DisposerMixin { final key = script.id; if (key == null) return []; if (!_breakPositionsMap.containsKey(key)) { - _breakPositionsMap[key] = - await _getBreakablePositions(isolateRef, script); + _breakPositionsMap[key] = await _getBreakablePositions( + isolateRef, + script, + ); } return _breakPositionsMap[key] ?? []; @@ -342,18 +346,16 @@ class BreakpointManager with DisposerMixin { // that knows how to notify when performing a list edit operation. case EventKind.kBreakpointAdded: final breakpoint = event.breakpoint!; - final isDuplicate = - _breakpoints.value.any((bp) => bp.id == breakpoint.id); + final isDuplicate = _breakpoints.value.any( + (bp) => bp.id == breakpoint.id, + ); if (isDuplicate) break; _breakpoints.value = [..._breakpoints.value, breakpoint]; - await breakpointManager - .createBreakpointWithLocation(breakpoint) - .then((bp) { - final list = [ - ..._breakpointsWithLocation.value, - bp, - ]..sort(); + await breakpointManager.createBreakpointWithLocation(breakpoint).then(( + bp, + ) { + final list = [..._breakpointsWithLocation.value, bp]..sort(); _breakpointsWithLocation.value = list; }); @@ -366,9 +368,9 @@ class BreakpointManager with DisposerMixin { breakpoint, ]; - await breakpointManager - .createBreakpointWithLocation(breakpoint) - .then((bp) { + await breakpointManager.createBreakpointWithLocation(breakpoint).then(( + bp, + ) { final list = _breakpointsWithLocation.value; // Remove the bp with the older, unresolved information from the list. list.removeWhere((breakpoint) => breakpoint.id == bp.id); @@ -386,8 +388,11 @@ class BreakpointManager with DisposerMixin { // the restart. Note we only track hot restarts triggered by DevTools, // if a hot-restart was triggered by another client we won't know. // See https://github.com/flutter/flutter/issues/134470 - final hotRestartInProgress = serviceConnection - .serviceManager.isolateManager.hotRestartInProgress; + final hotRestartInProgress = + serviceConnection + .serviceManager + .isolateManager + .hotRestartInProgress; if (hotRestartInProgress) break; final breakpoint = event.breakpoint; diff --git a/packages/devtools_app/lib/src/screens/debugger/breakpoints.dart b/packages/devtools_app/lib/src/screens/debugger/breakpoints.dart index 85dd39b01e7..ad2665d1a0e 100644 --- a/packages/devtools_app/lib/src/screens/debugger/breakpoints.dart +++ b/packages/devtools_app/lib/src/screens/debugger/breakpoints.dart @@ -46,10 +46,7 @@ class _BreakpointsState extends State itemCount: breakpoints.length, itemExtent: defaultListItemHeight, itemBuilder: (_, index) { - return buildBreakpoint( - breakpoints[index], - selectedBreakpoint, - ); + return buildBreakpoint(breakpoints[index], selectedBreakpoint); }, ); }, @@ -91,9 +88,10 @@ class _BreakpointsState extends State children: [ TextSpan( text: ' (${bp.scriptUri})', - style: isSelected - ? theme.selectedSubtleTextStyle - : theme.subtleTextStyle, + style: + isSelected + ? theme.selectedSubtleTextStyle + : theme.subtleTextStyle, ), ], ), diff --git a/packages/devtools_app/lib/src/screens/debugger/call_stack.dart b/packages/devtools_app/lib/src/screens/debugger/call_stack.dart index 58a471a2f29..ee9576e4bb3 100644 --- a/packages/devtools_app/lib/src/screens/debugger/call_stack.dart +++ b/packages/devtools_app/lib/src/screens/debugger/call_stack.dart @@ -59,10 +59,7 @@ class _CallStackState extends State ); } - Widget _buildStackFrame( - StackFrameAndSourcePosition frame, - bool selected, - ) { + Widget _buildStackFrame(StackFrameAndSourcePosition frame, bool selected) { final theme = Theme.of(context); Widget child; @@ -79,10 +76,7 @@ class _CallStackState extends State const SizedBox(width: defaultSpacing, child: Divider()), Padding( padding: const EdgeInsets.symmetric(horizontal: densePadding), - child: Text( - frameDescription, - style: theme.regularTextStyle, - ), + child: Text(frameDescription, style: theme.regularTextStyle), ), const Expanded(child: Divider()), ], @@ -98,9 +92,10 @@ class _CallStackState extends State if (locationDescription != null) TextSpan( text: ' $locationDescription', - style: selected - ? theme.selectedSubtleTextStyle - : theme.subtleTextStyle, + style: + selected + ? theme.selectedSubtleTextStyle + : theme.subtleTextStyle, ), ], ), @@ -124,12 +119,13 @@ class _CallStackState extends State return isAsyncBreak ? result : DevToolsTooltip( - message: locationDescription == null - ? frameDescription - : '$frameDescription $locationDescription', - waitDuration: tooltipWaitLong, - child: result, - ); + message: + locationDescription == null + ? frameDescription + : '$frameDescription $locationDescription', + waitDuration: tooltipWaitLong, + child: result, + ); } Future _onStackFrameSelected(StackFrameAndSourcePosition frame) async { diff --git a/packages/devtools_app/lib/src/screens/debugger/codeview.dart b/packages/devtools_app/lib/src/screens/debugger/codeview.dart index cfa38e012ad..bf7c78f2aa4 100644 --- a/packages/devtools_app/lib/src/screens/debugger/codeview.dart +++ b/packages/devtools_app/lib/src/screens/debugger/codeview.dart @@ -39,8 +39,9 @@ import 'key_sets.dart'; final _log = Logger('codeview'); -final debuggerCodeViewFileOpenerKey = - GlobalKey(debugLabel: 'DebuggerCodeViewFileOpenerKey'); +final debuggerCodeViewFileOpenerKey = GlobalKey( + debugLabel: 'DebuggerCodeViewFileOpenerKey', +); // TODO(kenz): consider moving lines / pausedPositions calculations to the // controller. @@ -57,11 +58,13 @@ class CodeView extends StatefulWidget { this.enableHistory = true, }); - static const debuggerCodeViewHorizontalScrollbarKey = - Key('debuggerCodeViewHorizontalScrollbarKey'); + static const debuggerCodeViewHorizontalScrollbarKey = Key( + 'debuggerCodeViewHorizontalScrollbarKey', + ); - static const debuggerCodeViewVerticalScrollbarKey = - Key('debuggerCodeViewVerticalScrollbarKey'); + static const debuggerCodeViewVerticalScrollbarKey = Key( + 'debuggerCodeViewVerticalScrollbarKey', + ); static double get rowHeight => scaleByFontFactor(16.0); @@ -171,8 +174,9 @@ class _CodeViewState extends State with AutoDisposeMixin { profileController?.dispose(); textController.dispose(); horizontalController.dispose(); - widget.codeViewController.scriptLocation - .removeListener(_handleScriptLocationChanged); + widget.codeViewController.scriptLocation.removeListener( + _handleScriptLocationChanged, + ); super.dispose(); } @@ -225,7 +229,8 @@ class _CodeViewState extends State with AutoDisposeMixin { final lineCount = parsedScript?.lineCount; if (lineCount != null && lineCount * CodeView.rowHeight > extent) { final lineIndex = line - 1; - var scrollPosition = lineIndex * CodeView.rowHeight - + var scrollPosition = + lineIndex * CodeView.rowHeight - ((extent - CodeView.rowHeight) / 2); scrollPosition = scrollPosition.clamp(0.0, position.extentTotal); if (animate) { @@ -246,8 +251,8 @@ class _CodeViewState extends State with AutoDisposeMixin { verticalController.hasAttachedControllers ? updateScrollPositionImpl() : WidgetsBinding.instance.addPostFrameCallback( - (_) => updateScrollPositionImpl(), - ); + (_) => updateScrollPositionImpl(), + ); } @override @@ -303,31 +308,18 @@ class _CodeViewState extends State with AutoDisposeMixin { currentLine.add(span); if (span.toPlainText() == '\n') { lines.add( - TextSpan( - style: theme.fixedFontStyle, - children: currentLine, - ), + TextSpan(style: theme.fixedFontStyle, children: currentLine), ); currentLine = []; } return true; }); - lines.add( - TextSpan( - style: theme.fixedFontStyle, - children: currentLine, - ), - ); + lines.add(TextSpan(style: theme.fixedFontStyle, children: currentLine)); } else { - lines.addAll( - [ - for (final line in scriptSource.split('\n')) - TextSpan( - style: theme.fixedFontStyle, - text: line, - ), - ], - ); + lines.addAll([ + for (final line in scriptSource.split('\n')) + TextSpan(style: theme.fixedFontStyle, text: line), + ]); } } @@ -341,10 +333,11 @@ class _CodeViewState extends State with AutoDisposeMixin { thumbVisibility: true, // Only listen for vertical scroll notifications (ignore those // from the nested horizontal SingleChildScrollView): - notificationPredicate: (ScrollNotification notification) => - notification.depth == 1, + notificationPredicate: + (ScrollNotification notification) => notification.depth == 1, child: ValueListenableBuilder( - valueListenable: widget.debuggerController?.selectedStackFrame ?? + valueListenable: + widget.debuggerController?.selectedStackFrame ?? const FixedValueListenable( null, ), @@ -379,8 +372,9 @@ class _CodeViewState extends State with AutoDisposeMixin { ); return Scrollbar( - key: CodeView - .debuggerCodeViewHorizontalScrollbarKey, + key: + CodeView + .debuggerCodeViewHorizontalScrollbarKey, thumbVisibility: true, controller: horizontalController, child: SingleChildScrollView( @@ -398,13 +392,18 @@ class _CodeViewState extends State with AutoDisposeMixin { widget.codeViewController, scrollController: textController, lines: lines, - selectedFrameNotifier: widget - .debuggerController - ?.selectedStackFrame, - searchMatchesNotifier: widget - .codeViewController.searchMatches, - activeSearchMatchNotifier: widget - .codeViewController.activeSearchMatch, + selectedFrameNotifier: + widget + .debuggerController + ?.selectedStackFrame, + searchMatchesNotifier: + widget + .codeViewController + .searchMatches, + activeSearchMatchNotifier: + widget + .codeViewController + .activeSearchMatch, showProfileInformation: showProfileInformation, ), @@ -441,24 +440,25 @@ class _CodeViewState extends State with AutoDisposeMixin { return scriptUri; }, titleIcon: Icons.search, - onTitleTap: () => widget.codeViewController - ..toggleFileOpenerVisibility(true) - ..toggleSearchInFileVisibility(false), + onTitleTap: + () => + widget.codeViewController + ..toggleFileOpenerVisibility(true) + ..toggleSearchInFileVisibility(false), controls: [ ScriptPopupMenu(widget.codeViewController), ScriptHistoryPopupMenu( itemBuilder: _buildScriptMenuFromHistory, onSelected: (scriptRef) async { - await widget.codeViewController - .showScriptLocation(ScriptLocation(scriptRef)); + await widget.codeViewController.showScriptLocation( + ScriptLocation(scriptRef), + ); }, enabled: widget.codeViewController.scriptsHistory.hasScripts, ), ], contentBuilder: (context, ScriptRef? scriptRef) { - return Expanded( - child: contentBuilder(context, scriptRef), - ); + return Expanded(child: contentBuilder(context, scriptRef)); }, ); } @@ -471,9 +471,7 @@ class _CodeViewState extends State with AutoDisposeMixin { width: extraWideSearchFieldWidth, height: defaultTextFieldHeight, padding: EdgeInsets.zero, - child: FileSearchField( - codeViewController: widget.codeViewController, - ), + child: FileSearchField(codeViewController: widget.codeViewController), ); } @@ -486,8 +484,8 @@ class _CodeViewState extends State with AutoDisposeMixin { searchFieldEnabled: parsedScript != null, shouldRequestFocus: true, searchFieldWidth: wideSearchFieldWidth, - onClose: () => - widget.codeViewController.toggleSearchInFileVisibility(false), + onClose: + () => widget.codeViewController.toggleSearchInFileVisibility(false), ), ); } @@ -500,35 +498,33 @@ class _CodeViewState extends State with AutoDisposeMixin { return widget.codeViewController.scriptsHistory.openedScripts .take(scriptHistorySize) .map((scriptRef) { - return PopupMenuItem( - value: scriptRef, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - ScriptRefUtils.fileName(scriptRef), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - Text( - scriptRef.uri ?? '', - overflow: TextOverflow.ellipsis, - maxLines: 1, - style: Theme.of(context).subtleTextStyle, + return PopupMenuItem( + value: scriptRef, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + ScriptRefUtils.fileName(scriptRef), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + Text( + scriptRef.uri ?? '', + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: Theme.of(context).subtleTextStyle, + ), + ], ), - ], - ), - ); - }).toList(); + ); + }) + .toList(); } } class CodeViewEmptyState extends StatelessWidget { - const CodeViewEmptyState({ - super.key, - required this.widget, - }); + const CodeViewEmptyState({super.key, required this.widget}); final CodeView widget; @@ -539,8 +535,8 @@ class CodeViewEmptyState extends StatelessWidget { return Center( child: ElevatedButton( autofocus: true, - onPressed: () => - widget.codeViewController.toggleFileOpenerVisibility(true), + onPressed: + () => widget.codeViewController.toggleFileOpenerVisibility(true), child: Text( 'Open a file ($openFileKeySetDescription)', style: theme.textTheme.titleMedium, @@ -605,9 +601,7 @@ class ProfileInformationGutter extends StatelessWidget { ), ], ), - const Center( - child: VerticalDivider(), - ), + const Center(child: VerticalDivider()), ], ), ), @@ -638,28 +632,20 @@ class _ProfileInformationGutterHeader extends StatelessWidget { Expanded( child: DevToolsTooltip( message: totalTimeTooltip, - child: const Text( - 'Total %', - textAlign: TextAlign.center, - ), + child: const Text('Total %', textAlign: TextAlign.center), ), ), const SizedBox(width: denseSpacing), Expanded( child: DevToolsTooltip( message: selfTimeTooltip, - child: const Text( - 'Self %', - textAlign: TextAlign.center, - ), + child: const Text('Self %', textAlign: TextAlign.center), ), ), ], ), ), - const Divider( - height: 0, - ), + const Divider(height: 0), ], ), ); @@ -667,10 +653,7 @@ class _ProfileInformationGutterHeader extends StatelessWidget { } class ProfileInformationGutterItem extends StatelessWidget { - const ProfileInformationGutterItem({ - super.key, - required this.profilerData, - }); + const ProfileInformationGutterItem({super.key, required this.profilerData}); final ProfileReportEntry profilerData; @@ -728,9 +711,7 @@ class ProfilePercentageItem extends StatelessWidget { message: hoverText, child: Container( color: color, - padding: const EdgeInsets.symmetric( - horizontal: densePadding, - ), + padding: const EdgeInsets.symmetric(horizontal: densePadding), child: Text( '${percentage.toStringAsFixed(2)} %', textAlign: TextAlign.end, @@ -783,7 +764,8 @@ class Gutters extends StatelessWidget { // - each character in the longest line number // - one for the breakpoint dot // - two for the paused arrow - final gutterWidth = assumedMonospaceCharacterWidth * 4 + + final gutterWidth = + assumedMonospaceCharacterWidth * 4 + assumedMonospaceCharacterWidth * (defaultEpsilon + math.log(math.max(lines.length, 100)) / math.ln10) .truncateToDouble(); @@ -820,14 +802,14 @@ class Gutters extends StatelessWidget { !showProfileInformation ? const SizedBox(width: denseSpacing) : Padding( - padding: const EdgeInsets.only(right: denseSpacing), - child: ProfileInformationGutter( - scrollController: profileController!, - lineCount: lineCount, - lineOffset: lineOffset, - sourceReport: sourceReport, - ), + padding: const EdgeInsets.only(right: denseSpacing), + child: ProfileInformationGutter( + scrollController: profileController!, + lineCount: lineCount, + lineOffset: lineOffset, + sourceReport: sourceReport, ), + ), ], ); } @@ -875,8 +857,9 @@ class Gutter extends StatelessWidget { Widget build(BuildContext context) { final bpLineSet = Set.of(breakpoints.map((bp) => bp.line)); final theme = Theme.of(context); - final coverageLines = - sourceReport.coverageHitLines.union(sourceReport.coverageMissedLines); + final coverageLines = sourceReport.coverageHitLines.union( + sourceReport.coverageMissedLines, + ); // Used to account for the presence of `_ProfileInformationGutterHeader` at // the top of the profiler gutter columns. Everything needs to be shifted // down a single line so profiling information for line 1 isn't hidden by @@ -958,9 +941,10 @@ class GutterItem extends StatelessWidget { TextStyle? coverageTextStyleOverride; final hasCoverage = coverageHit; if (hasCoverage != null) { - color = hasCoverage - ? theme.colorScheme.coverageHitColor - : theme.colorScheme.coverageMissColor; + color = + hasCoverage + ? theme.colorScheme.coverageHitColor + : theme.colorScheme.coverageMissColor; coverageTextStyleOverride = theme.regularTextStyleWithColor( theme.colorScheme.coverageAndPerformanceTextColor, ); @@ -1110,12 +1094,11 @@ class _LinesState extends State with AutoDisposeMixin { lineContents: widget.lines[dataIndex], pausedFrame: isPausedLine ? pausedFrame : null, focused: isPausedLine || isFocusedLine, - searchMatches: _searchMatchesForLine( - dataIndex, - ), - activeSearchMatch: activeSearch?.position.line == dataIndex - ? activeSearch - : null, + searchMatches: _searchMatchesForLine(dataIndex), + activeSearchMatch: + activeSearch?.position.line == dataIndex + ? activeSearch + : null, ); }, ); @@ -1133,9 +1116,11 @@ class _LinesState extends State with AutoDisposeMixin { void _maybeScrollToLine(int? lineNumber) { if (lineNumber == null) return; - final isOutOfViewTop = lineNumber * CodeView.rowHeight < + final isOutOfViewTop = + lineNumber * CodeView.rowHeight < widget.scrollController.offset + CodeView.rowHeight; - final isOutOfViewBottom = lineNumber * CodeView.rowHeight > + final isOutOfViewBottom = + lineNumber * CodeView.rowHeight > widget.scrollController.offset + widget.height - CodeView.rowHeight; if (isOutOfViewTop || isOutOfViewBottom) { @@ -1185,16 +1170,17 @@ class _LineItemState extends State }) async { if (!serviceConnection.serviceManager.isMainIsolatePaused) return null; - final word = wordForHover( - event.localPosition.dx, - widget.lineContents, - ); + final word = wordForHover(event.localPosition.dx, widget.lineContents); if (word != '') { try { final response = await evalService.evalAtCurrentFrame(word); - final isolateRef = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value; + final isolateRef = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value; if (response is! InstanceRef) return null; final variable = DartObjectNode.fromValue( value: response, @@ -1203,11 +1189,7 @@ class _LineItemState extends State await buildVariablesTree(variable); return HoverCardData( title: word, - contents: Material( - child: ExpandableVariable( - variable: variable, - ), - ), + contents: Material(child: ExpandableVariable(variable: variable)), width: LineItem._hoverWidth, ); } catch (_) { @@ -1285,23 +1267,22 @@ class _LineItemState extends State } Widget _hoverableLine() => HoverCardTooltip.async( - enabled: () => true, - asyncTimeout: 100, - asyncGenerateHoverCardData: _generateHoverCardData, - child: Text.rich( - searchAwareLineContents(), - maxLines: 1, - ), - ); + enabled: () => true, + asyncTimeout: 100, + asyncGenerateHoverCardData: _generateHoverCardData, + child: Text.rich(searchAwareLineContents(), maxLines: 1), + ); TextSpan searchAwareLineContents() { // If syntax highlighting is disabled for the script, then // `widget.lineContents` is simply a `TextSpan` with no children. final lineContents = widget.lineContents.children ?? [widget.lineContents]; - final activeSearchAwareContents = - _activeSearchAwareLineContents(lineContents); - final allSearchAwareContents = - _searchMatchAwareLineContents(activeSearchAwareContents!); + final activeSearchAwareContents = _activeSearchAwareLineContents( + lineContents, + ); + final allSearchAwareContents = _searchMatchAwareLineContents( + activeSearchAwareContents!, + ); return TextSpan( children: allSearchAwareContents, style: widget.lineContents.style, @@ -1332,23 +1313,19 @@ class _LineItemState extends State ), ); - final matchStyle = - (span.style ?? DefaultTextStyle.of(context).style).copyWith( - color: Colors.black, - backgroundColor: matchColor, - ); + final matchStyle = (span.style ?? DefaultTextStyle.of(context).style) + .copyWith(color: Colors.black, backgroundColor: matchColor); if (matchEndInSpan <= spanText.length) { - final matchText = - spanText.substring(matchStartInSpan, matchEndInSpan); + final matchText = spanText.substring( + matchStartInSpan, + matchEndInSpan, + ); final trailingText = spanText.substring(matchEndInSpan); // Add the match and any part of [span] that occurs after the search // match. contentsWithMatch.addAll([ - TextSpan( - text: matchText, - style: matchStyle, - ), + TextSpan(text: matchText, style: matchStyle), if (trailingText.isNotEmpty) TextSpan( text: spanText.substring(matchEndInSpan), @@ -1425,17 +1402,16 @@ class ScriptPopupMenu extends StatelessWidget { Widget build(BuildContext context) { return PopupMenuButton( onSelected: (option) => option.onSelected(context, _controller), - itemBuilder: (_) => [ - for (final menuOption in defaultScriptPopupMenuOptions) - menuOption.build(), - for (final extensionMenuOption in devToolsEnvironmentParameters - .buildExtraDebuggerScriptPopupMenuOptions()) - extensionMenuOption.build(), - ], - child: Icon( - Icons.more_vert, - size: actionsIconSize, - ), + itemBuilder: + (_) => [ + for (final menuOption in defaultScriptPopupMenuOptions) + menuOption.build(), + for (final extensionMenuOption + in devToolsEnvironmentParameters + .buildExtraDebuggerScriptPopupMenuOptions()) + extensionMenuOption.build(), + ], + child: Icon(Icons.more_vert, size: actionsIconSize), ); } } @@ -1465,10 +1441,7 @@ class ScriptHistoryPopupMenu extends StatelessWidget { actionsIconSize + denseSpacing, buttonMinWidth + denseSpacing, ), - child: Icon( - Icons.history, - size: actionsIconSize, - ), + child: Icon(Icons.history, size: actionsIconSize), ); } } @@ -1493,11 +1466,7 @@ class ScriptPopupMenuOption { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label), - if (icon != null) - Icon( - icon, - size: actionsIconSize, - ), + if (icon != null) Icon(icon, size: actionsIconSize), ], ), ); @@ -1514,9 +1483,12 @@ final defaultScriptPopupMenuOptions = [ final copyPackagePathOption = ScriptPopupMenuOption( label: 'Copy package path', icon: Icons.content_copy, - onSelected: (_, controller) => Clipboard.setData( - ClipboardData(text: controller.scriptLocation.value?.scriptRef.uri ?? ''), - ), + onSelected: + (_, controller) => Clipboard.setData( + ClipboardData( + text: controller.scriptLocation.value?.scriptRef.uri ?? '', + ), + ), ); final copyFilePathOption = ScriptPopupMenuOption( @@ -1525,9 +1497,7 @@ final copyFilePathOption = ScriptPopupMenuOption( onSelected: (_, controller) { unawaited(() async { final filePath = await fetchScriptLocationFullFilePath(controller); - await Clipboard.setData( - ClipboardData(text: filePath ?? ''), - ); + await Clipboard.setData(ClipboardData(text: filePath ?? '')); }()); }, ); @@ -1539,23 +1509,22 @@ Future fetchScriptLocationFullFilePath( String? filePath; final packagePath = controller.scriptLocation.value!.scriptRef.uri; if (packagePath != null) { - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!; - filePath = - serviceConnection.serviceManager.resolvedUriManager.lookupFileUri( - isolateId, - packagePath, - ); + final isolateId = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!; + filePath = serviceConnection.serviceManager.resolvedUriManager + .lookupFileUri(isolateId, packagePath); if (filePath == null) { await serviceConnection.serviceManager.resolvedUriManager.fetchFileUris( isolateId, [packagePath], ); - filePath = - serviceConnection.serviceManager.resolvedUriManager.lookupFileUri( - isolateId, - packagePath, - ); + filePath = serviceConnection.serviceManager.resolvedUriManager + .lookupFileUri(isolateId, packagePath); } } return filePath; @@ -1626,9 +1595,7 @@ class GoToLineDialog extends StatelessWidget { ), ], ), - actions: const [ - DialogCancelButton(), - ], + actions: const [DialogCancelButton()], ); } } @@ -1655,12 +1622,7 @@ class PositionedPopup extends StatelessWidget { valueListenable: isVisibleListenable, builder: (context, isVisible, _) { return isVisible - ? Positioned( - top: top, - left: left, - right: right, - child: child, - ) + ? Positioned(top: top, left: left, right: right, child: child) : const SizedBox.shrink(); }, ); 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 a314a74657b..4cf572cbc67 100644 --- a/packages/devtools_app/lib/src/screens/debugger/codeview_controller.dart +++ b/packages/devtools_app/lib/src/screens/debugger/codeview_controller.dart @@ -60,8 +60,9 @@ class CodeViewController extends DisposableController } Future _handleNavigationEvent(DevToolsNavigationState state) async { - final processedState = - CodeViewSourceLocationNavigationState._fromState(state); + final processedState = CodeViewSourceLocationNavigationState._fromState( + state, + ); final object = processedState.object; _navigationInProgress = true; await showScriptLocation(processedState.location, focusLine: true); @@ -156,9 +157,7 @@ class CodeViewController extends DisposableController await _maybeSetUpProgramExplorer(); addAutoDisposeListener( currentScriptRef, - () => unawaited( - _maybeSetUpProgramExplorer(), - ), + () => unawaited(_maybeSetUpProgramExplorer()), ); } @@ -192,8 +191,10 @@ class CodeViewController extends DisposableController // opener will close automatically when its focus is lost. toggleFileOpenerVisibility(false); - final succeeded = - await _showScriptLocation(scriptLocation, focusLine: focusLine); + final succeeded = await _showScriptLocation( + scriptLocation, + focusLine: focusLine, + ); if (succeeded) { // Update the scripts history (and make sure we don't react to the @@ -211,10 +212,7 @@ class CodeViewController extends DisposableController } final isolateRef = serviceConnection.serviceManager.isolateManager.selectedIsolate.value!; - final processedReport = await _getSourceReport( - isolateRef, - current.script, - ); + final processedReport = await _getSourceReport(isolateRef, current.script); parsedScript.value = ParsedScript( script: current.script, @@ -275,18 +273,15 @@ class CodeViewController extends DisposableController final hitLines = {}; final missedLines = {}; try { - final report = - await serviceConnection.serviceManager.service!.getSourceReport( - isolateRef.id!, - // TODO(bkonyi): make _Profile a public report type. - // See https://github.com/dart-lang/sdk/issues/50641 - const [ - SourceReportKind.kCoverage, - '_Profile', - ], - scriptId: script.id!, - reportLines: true, - ); + final report = await serviceConnection.serviceManager.service! + .getSourceReport( + isolateRef.id!, + // TODO(bkonyi): make _Profile a public report type. + // See https://github.com/dart-lang/sdk/issues/50641 + const [SourceReportKind.kCoverage, '_Profile'], + scriptId: script.id!, + reportLines: true, + ); for (final range in report.ranges!) { final coverage = range.coverage!; @@ -298,11 +293,11 @@ class CodeViewController extends DisposableController return ProcessedSourceReport( coverageHitLines: hitLines, coverageMissedLines: missedLines, - profilerEntries: - profileReport.profileRanges.fold>( - {}, - (last, e) => last..addAll(e.entries), - ), + profilerEntries: profileReport.profileRanges + .fold>( + {}, + (last, e) => last..addAll(e.entries), + ), ); } catch (e, st) { // Ignore - not supported for all vm service implementations. @@ -344,10 +339,7 @@ class CodeViewController extends DisposableController _log.warning(e, e, st); } - final processedReport = await _getSourceReport( - isolateRef, - script, - ); + final processedReport = await _getSourceReport(isolateRef, script); return ParsedScript( script: script, @@ -384,8 +376,9 @@ class CodeViewController extends DisposableController if (isWebApp && enableSourceMapsLink != null) { final enableSourceMapsAction = NotificationAction( label: 'Enable sourcemaps', - onPressed: () => - unawaited(launchUrlWithErrorHandling(enableSourceMapsLink.url)), + onPressed: + () => + unawaited(launchUrlWithErrorHandling(enableSourceMapsLink.url)), ); notificationService.pushNotification( NotificationMessage( @@ -437,9 +430,9 @@ class ProcessedSourceReport { }); const ProcessedSourceReport.empty() - : coverageHitLines = const {}, - coverageMissedLines = const {}, - profilerEntries = const {}; + : coverageHitLines = const {}, + coverageMissedLines = const {}, + profilerEntries = const {}; final Set coverageHitLines; final Set coverageMissedLines; @@ -502,21 +495,18 @@ class CodeViewSourceLocationNavigationState extends DevToolsNavigationState { required int line, ObjRef? object, }) : super( - kind: type, - state: { - _kScriptId: script.id, - _kUri: script.uri, - _kLine: line.toString(), - if (object != null) _kObject: json.encode(object.json), - }, - ); + kind: type, + state: { + _kScriptId: script.id, + _kUri: script.uri, + _kLine: line.toString(), + if (object != null) _kObject: json.encode(object.json), + }, + ); CodeViewSourceLocationNavigationState._fromState( DevToolsNavigationState state, - ) : super( - kind: type, - state: state.state, - ); + ) : super(kind: type, state: state.state); static CodeViewSourceLocationNavigationState? fromState( DevToolsNavigationState? state, @@ -531,10 +521,7 @@ class CodeViewSourceLocationNavigationState extends DevToolsNavigationState { static const _kObject = 'object'; static const type = 'codeViewSourceLocation'; - ScriptRef get script => ScriptRef( - id: state[_kScriptId]!, - uri: state[_kUri], - ); + ScriptRef get script => ScriptRef(id: state[_kScriptId]!, uri: state[_kUri]); int get line => int.parse(state[_kLine]!); @@ -546,10 +533,8 @@ class CodeViewSourceLocationNavigationState extends DevToolsNavigationState { return createServiceObject(json.decode(obj), const []) as ObjRef?; } - ScriptLocation get location => ScriptLocation( - script, - location: SourcePosition(line: line, column: 1), - ); + ScriptLocation get location => + ScriptLocation(script, location: SourcePosition(line: line, column: 1)); @override String toString() { diff --git a/packages/devtools_app/lib/src/screens/debugger/controls.dart b/packages/devtools_app/lib/src/screens/debugger/controls.dart index a00141342dd..70b0b279c73 100644 --- a/packages/devtools_app/lib/src/screens/debugger/controls.dart +++ b/packages/devtools_app/lib/src/screens/debugger/controls.dart @@ -36,7 +36,10 @@ class _DebuggingControlsState extends State if (!initController()) return; addAutoDisposeListener( serviceConnection - .serviceManager.isolateManager.mainIsolateState?.isPaused, + .serviceManager + .isolateManager + .mainIsolateState + ?.isPaused, ); addAutoDisposeListener(controller.resuming); addAutoDisposeListener(controller.stackFramesWithLocation); @@ -47,13 +50,14 @@ class _DebuggingControlsState extends State final resuming = controller.resuming.value; final hasStackFrames = controller.stackFramesWithLocation.value.isNotEmpty; final isSystemIsolate = controller.isSystemIsolate; - final canStep = serviceConnection.serviceManager.isMainIsolatePaused && + final canStep = + serviceConnection.serviceManager.isMainIsolatePaused && !resuming && hasStackFrames && !isSystemIsolate; final isVmApp = serviceConnection.serviceManager.connectedApp?.isRunningOnDartVM ?? - false; + false; return SizedBox( height: defaultButtonHeight, child: Row( @@ -89,18 +93,20 @@ class _DebuggingControlsState extends State icon: Codicons.debugPause, autofocus: true, // Disable when paused or selected isolate is a system isolate. - onPressed: (isPaused || isSystemIsolate) - ? null - : () => unawaited(controller.pause()), + onPressed: + (isPaused || isSystemIsolate) + ? null + : () => unawaited(controller.pause()), ), ButtonGroupItemData( tooltip: 'Resume', icon: Codicons.debugContinue, // Enable while paused + not resuming and selected isolate is not // a system isolate. - onPressed: ((isPaused && !resuming) && !isSystemIsolate) - ? () => unawaited(controller.resume()) - : null, + onPressed: + ((isPaused && !resuming) && !isSystemIsolate) + ? () => unawaited(controller.resume()) + : null, ), ], ); @@ -139,9 +145,10 @@ class _DebuggingControlsState extends State label: 'File Explorer', onPressed: controller.codeViewController.toggleLibrariesVisible, gaScreen: gac.debugger, - gaSelection: visible - ? gac.DebuggerEvents.hideFileExplorer.name - : gac.DebuggerEvents.showFileExplorer.name, + gaSelection: + visible + ? gac.DebuggerEvents.hideFileExplorer.name + : gac.DebuggerEvents.showFileExplorer.name, minScreenWidthForTextBeforeScaling: DebuggingControls.minWidthBeforeScaling, ); @@ -151,10 +158,7 @@ class _DebuggingControlsState extends State } class CodeStatisticsControls extends StatelessWidget { - const CodeStatisticsControls({ - super.key, - required this.controller, - }); + const CodeStatisticsControls({super.key, required this.controller}); final DebuggerController controller; @@ -198,11 +202,12 @@ class CodeStatisticsControls extends StatelessWidget { tooltip: 'Refresh statistics', gaScreen: gac.debugger, gaSelection: gac.DebuggerEvents.refreshStatistics.name, - onPressed: showCodeCoverage || showProfileInformation - ? () => unawaited( + onPressed: + showCodeCoverage || showProfileInformation + ? () => unawaited( controller.codeViewController.refreshCodeStatistics(), ) - : null, + : null, ), ], ); @@ -212,10 +217,7 @@ class CodeStatisticsControls extends StatelessWidget { } class _CodeStatsControl extends StatelessWidget { - const _CodeStatsControl({ - required this.icon, - required this.tooltip, - }); + const _CodeStatsControl({required this.icon, required this.tooltip}); final IconData icon; final String tooltip; @@ -226,26 +228,21 @@ class _CodeStatsControl extends StatelessWidget { message: tooltip, child: Container( padding: const EdgeInsets.symmetric(horizontal: defaultSpacing), - child: Icon( - icon, - size: defaultIconSize, - ), + child: Icon(icon, size: defaultIconSize), ), ); } } class BreakOnExceptionsControl extends StatelessWidget { - const BreakOnExceptionsControl({ - super.key, - required this.controller, - }); + const BreakOnExceptionsControl({super.key, required this.controller}); final DebuggerController controller; @override Widget build(BuildContext context) { - final isInSmallMode = MediaQuery.of(context).size.width < + final isInSmallMode = + MediaQuery.of(context).size.width < DebuggingControls.minWidthBeforeScaling; return ValueListenableBuilder( valueListenable: controller.exceptionPauseMode, @@ -253,19 +250,18 @@ class BreakOnExceptionsControl extends StatelessWidget { return RoundedDropDownButton( value: ExceptionMode.from(modeId), // Cannot set exception pause mode for system isolates. - onChanged: controller.isSystemIsolate - ? null - : (ExceptionMode? mode) { - unawaited(controller.setIsolatePauseMode(mode!.id)); - }, + onChanged: + controller.isSystemIsolate + ? null + : (ExceptionMode? mode) { + unawaited(controller.setIsolatePauseMode(mode!.id)); + }, isDense: true, items: [ for (final mode in ExceptionMode.modes) DropdownMenuItem( value: mode, - child: Text( - isInSmallMode ? mode.name : mode.description, - ), + child: Text(isInSmallMode ? mode.name : mode.description), ), ], ); diff --git a/packages/devtools_app/lib/src/screens/debugger/debugger_controller.dart b/packages/devtools_app/lib/src/screens/debugger/debugger_controller.dart index ddbb47c4e7f..53962626605 100644 --- a/packages/devtools_app/lib/src/screens/debugger/debugger_controller.dart +++ b/packages/devtools_app/lib/src/screens/debugger/debugger_controller.dart @@ -148,7 +148,7 @@ class DebuggerController extends DisposableController ValueNotifier>([]); ValueListenable> - get stackFramesWithLocation => _stackFramesWithLocation; + get stackFramesWithLocation => _stackFramesWithLocation; final _selectedStackFrame = ValueNotifier(null); @@ -160,8 +160,9 @@ class DebuggerController extends DisposableController ValueListenable get selectedBreakpoint => _selectedBreakpoint; - final _exceptionPauseMode = - ValueNotifier(ExceptionPauseMode.kUnhandled); + final _exceptionPauseMode = ValueNotifier( + ExceptionPauseMode.kUnhandled, + ); ValueListenable get exceptionPauseMode => _exceptionPauseMode; @@ -235,9 +236,10 @@ class DebuggerController extends DisposableController return _service .resume( _isolateRefId, - step: useAsyncStepping - ? StepOption.kOverAsyncSuspension - : StepOption.kOver, + step: + useAsyncStepping + ? StepOption.kOverAsyncSuspension + : StepOption.kOver, ) .whenComplete(() => _debugTimingLog.log('stepOver() completed')); } @@ -255,10 +257,7 @@ class DebuggerController extends DisposableController } Future setIsolatePauseMode(String mode) async { - await _service.setIsolatePauseMode( - _isolateRefId, - exceptionPauseMode: mode, - ); + await _service.setIsolatePauseMode(_isolateRefId, exceptionPauseMode: mode); _exceptionPauseMode.value = mode; } @@ -326,12 +325,15 @@ class DebuggerController extends DisposableController if (theIsolateRef == null) return; // Refresh the list of scripts. final previousScriptRefs = scriptManager.sortedScripts.value; - final currentScriptRefs = - await scriptManager.retrieveAndSortScripts(theIsolateRef); - final removedScripts = - Set.of(previousScriptRefs).difference(Set.of(currentScriptRefs)); - final addedScripts = - Set.of(currentScriptRefs).difference(Set.of(previousScriptRefs)); + final currentScriptRefs = await scriptManager.retrieveAndSortScripts( + theIsolateRef, + ); + final removedScripts = Set.of( + previousScriptRefs, + ).difference(Set.of(currentScriptRefs)); + final addedScripts = Set.of( + currentScriptRefs, + ).difference(Set.of(previousScriptRefs)); // TODO(devoncarew): Show a message in the logging view. @@ -347,8 +349,9 @@ class DebuggerController extends DisposableController // Redirect the current editor screen if necessary. if (removedScripts.contains(codeViewController.currentScriptRef.value)) { final uri = codeViewController.currentScriptRef.value!.uri; - final newScriptRef = - addedScripts.firstWhereOrNull((script) => script.uri == uri); + final newScriptRef = addedScripts.firstWhereOrNull( + (script) => script.uri == uri, + ); if (newScriptRef != null) { // Display the script location. @@ -399,29 +402,23 @@ class DebuggerController extends DisposableController _log.warning( 'Pause event has no frame. This likely indicates a DWDS bug.', ); - await _populateFrameInfo( - [ - await _createStackFrameWithLocation( - Frame( - code: CodeRef( - name: 'No Dart frames found, likely paused in JS.', - kind: CodeKind.kTag, - id: DateTime.now().microsecondsSinceEpoch.toString(), - ), + await _populateFrameInfo([ + await _createStackFrameWithLocation( + Frame( + code: CodeRef( + name: 'No Dart frames found, likely paused in JS.', + kind: CodeKind.kTag, + id: DateTime.now().microsecondsSinceEpoch.toString(), ), ), - ], - truncated: true, - ); + ), + ], truncated: true); ga.select(gac.debugger, gac.DebuggerEvents.pausedWithNoFrames.name); return; } - await _populateFrameInfo( - [ - await _createStackFrameWithLocation(topFrame), - ], - truncated: true, - ); + await _populateFrameInfo([ + await _createStackFrameWithLocation(topFrame), + ], truncated: true); unawaited(_getFullStack()); return; } @@ -431,15 +428,10 @@ class DebuggerController extends DisposableController const initialFrameRequestCount = 12; _getStackOperation = CancelableOperation.fromFuture( - _getStackInfo( - limit: initialFrameRequestCount, - ), + _getStackInfo(limit: initialFrameRequestCount), ); final stackInfo = await _getStackOperation!.value; - await _populateFrameInfo( - stackInfo.frames, - truncated: stackInfo.truncated, - ); + await _populateFrameInfo(stackInfo.frames, truncated: stackInfo.truncated); // In the background, populate the rest of the frames. if (stackInfo.truncated) { @@ -450,8 +442,9 @@ class DebuggerController extends DisposableController Future<_StackInfo> _getStackInfo({int? limit}) async { _debugTimingLog.log('getStack() with limit: $limit'); final stack = await _service.getStack(_isolateRefId, limit: limit); - _debugTimingLog - .log('getStack() completed (frames: ${stack.frames!.length})'); + _debugTimingLog.log( + 'getStack() completed (frames: ${stack.frames!.length})', + ); final frames = _framesForCallStack( stack.frames ?? [], @@ -494,8 +487,9 @@ class DebuggerController extends DisposableController Future _populateScripts(Isolate isolate) async { final theIsolateRef = _isolate.value; if (theIsolateRef == null) return; - final scriptRefs = - await scriptManager.retrieveAndSortScripts(theIsolateRef); + final scriptRefs = await scriptManager.retrieveAndSortScripts( + theIsolateRef, + ); // Update the selected script. final mainScriptRef = scriptRefs.firstWhereOrNull((ref) { @@ -566,14 +560,10 @@ class DebuggerController extends DisposableController return []; } - final variables = frame.vars! - .map( - (v) => DartObjectNode.create( - v, - _isolate.value, - ), - ) - .toList(); + final variables = + frame.vars! + .map((v) => DartObjectNode.create(v, _isolate.value)) + .toList(); // TODO(jacobr): would be nice to be able to remove this call to unawaited // but it would require a significant refactor. variables @@ -606,8 +596,13 @@ class DebuggerController extends DisposableController } Future _fetchDapFrame(Frame vmFrame) async { - final isolateNumber = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value?.number; + final isolateNumber = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value + ?.number; final frameIndex = vmFrame.index; if (isolateNumber == null || frameIndex == null) return null; @@ -625,18 +620,14 @@ class DebuggerController extends DisposableController Future> _fetchDapScopes(int frameId) async { final scopesResponse = await _service.dapScopesRequest( - dap.ScopesArguments( - frameId: frameId, - ), + dap.ScopesArguments(frameId: frameId), ); return scopesResponse?.scopes ?? []; } Future> _fetchDapVariables(int variablesReference) async { final variablesResponse = await _service.dapVariablesRequest( - dap.VariablesArguments( - variablesReference: variablesReference, - ), + dap.VariablesArguments(variablesReference: variablesReference), ); return variablesResponse?.variables ?? []; } @@ -665,10 +656,7 @@ class DebuggerController extends DisposableController ); newFrame.vars = [ - BoundVariable( - name: '', - value: reportedException, - ), + BoundVariable(name: '', value: reportedException), ...frame.vars ?? [], ]; diff --git a/packages/devtools_app/lib/src/screens/debugger/debugger_model.dart b/packages/devtools_app/lib/src/screens/debugger/debugger_model.dart index e7c4994a6cb..5509726a75a 100644 --- a/packages/devtools_app/lib/src/screens/debugger/debugger_model.dart +++ b/packages/devtools_app/lib/src/screens/debugger/debugger_model.dart @@ -24,10 +24,7 @@ bool includeDiagnosticChildren = false; /// A tuple of a script and an optional location. class ScriptLocation { - ScriptLocation( - this.scriptRef, { - this.location, - }); + ScriptLocation(this.scriptRef, {this.location}); final ScriptRef scriptRef; @@ -186,10 +183,7 @@ class _BreakpointAndSourcePositionUnresolved /// A tuple of a stack frame and a source position. class StackFrameAndSourcePosition { - StackFrameAndSourcePosition( - this.frame, { - this.position, - }); + StackFrameAndSourcePosition(this.frame, {this.position}); final Frame frame; diff --git a/packages/devtools_app/lib/src/screens/debugger/debugger_screen.dart b/packages/devtools_app/lib/src/screens/debugger/debugger_screen.dart index 75b6e8585d3..1f281f50d82 100644 --- a/packages/devtools_app/lib/src/screens/debugger/debugger_screen.dart +++ b/packages/devtools_app/lib/src/screens/debugger/debugger_screen.dart @@ -39,10 +39,10 @@ import 'variables.dart'; class DebuggerScreen extends Screen { DebuggerScreen() - : super.fromMetaData( - ScreenMetaData.debugger, - showFloatingDebuggerControls: false, - ); + : super.fromMetaData( + ScreenMetaData.debugger, + showFloatingDebuggerControls: false, + ); static final id = ScreenMetaData.debugger.id; @@ -98,8 +98,10 @@ class _DebuggerScreenBodyWrapper extends StatefulWidget { class _DebuggerScreenBodyWrapperState extends State<_DebuggerScreenBodyWrapper> with AutoDisposeMixin, - ProvidedControllerMixin { + ProvidedControllerMixin< + DebuggerController, + _DebuggerScreenBodyWrapper + > { late bool _shownFirstScript; @override @@ -158,10 +160,7 @@ class DebuggerScreenBody extends StatelessWidget { axis: Axis.horizontal, initialFractions: const [0.25, 0.75], children: [ - const RoundedOutlinedBorder( - clip: true, - child: DebuggerWindows(), - ), + const RoundedOutlinedBorder(clip: true, child: DebuggerWindows()), DebuggerSourceAndControls( shownFirstScript: shownFirstScript, setShownFirstScript: setShownFirstScript, @@ -195,10 +194,10 @@ class DebuggerWindows extends StatelessWidget { actions: [ CopyToClipboardControl( dataProvider: () { - final callStackList = controller - .stackFramesWithLocation.value - .map((frame) => frame.callStackDisplay) - .toList(); + final callStackList = + controller.stackFramesWithLocation.value + .map((frame) => frame.callStackDisplay) + .toList(); for (var i = 0; i < callStackList.length; i++) { callStackList[i] = '#$i ${callStackList[i]}'; } @@ -218,11 +217,7 @@ class DebuggerWindows extends StatelessWidget { roundedTopBorder: false, ), ], - children: const [ - CallStack(), - Variables(), - Breakpoints(), - ], + children: const [CallStack(), Variables(), Breakpoints()], ); }, ); @@ -245,9 +240,10 @@ class _BreakpointsWindowActions extends StatelessWidget { child: ToolbarAction( icon: Icons.delete, size: defaultIconSize, - onPressed: breakpoints.isNotEmpty - ? () => unawaited(breakpointManager.clearBreakpoints()) - : null, + onPressed: + breakpoints.isNotEmpty + ? () => unawaited(breakpointManager.clearBreakpoints()) + : null, ), ), ], @@ -294,8 +290,8 @@ class DebuggerSourceAndControls extends StatelessWidget { child: ProgramExplorer( controller: codeViewController.programExplorerController, - onNodeSelected: (node) => - _onNodeSelected(context, node), + onNodeSelected: + (node) => _onNodeSelected(context, node), ), ), ], @@ -315,10 +311,7 @@ class DebuggerSourceAndControls extends StatelessWidget { if (scriptRef != null && parsedScript != null && !shownFirstScript()) { - ga.timeEnd( - DebuggerScreen.id, - gac.pageReady, - ); + ga.timeEnd(DebuggerScreen.id, gac.pageReady); unawaited( serviceConnection.sendDwdsEvent( screen: DebuggerScreen.id, @@ -333,9 +326,10 @@ class DebuggerSourceAndControls extends StatelessWidget { debuggerController: controller, scriptRef: scriptRef, parsedScript: parsedScript, - onSelected: (script, line) => unawaited( - breakpointManager.toggleBreakpoint(script, line), - ), + onSelected: + (script, line) => unawaited( + breakpointManager.toggleBreakpoint(script, line), + ), ); }, ), @@ -372,10 +366,7 @@ class GoToLineNumberIntent extends Intent { class GoToLineNumberAction extends Action { @override void invoke(GoToLineNumberIntent intent) { - showGoToLineDialog( - intent._context, - intent._controller.codeViewController, - ); + showGoToLineDialog(intent._context, intent._controller.codeViewController); intent._controller.codeViewController ..toggleFileOpenerVisibility(false) ..toggleSearchInFileVisibility(false); @@ -428,10 +419,7 @@ class OpenFileAction extends Action { } class DebuggerStatus extends StatefulWidget { - const DebuggerStatus({ - super.key, - required this.controller, - }); + const DebuggerStatus({super.key, required this.controller}); final DebuggerController controller; @@ -465,20 +453,17 @@ class _DebuggerStatusState extends State with AutoDisposeMixin { void _updateStatusOnPause() { addAutoDisposeListener( serviceConnection - .serviceManager.isolateManager.mainIsolateState?.isPaused, - () => unawaited( - _updateStatus(), - ), + .serviceManager + .isolateManager + .mainIsolateState + ?.isPaused, + () => unawaited(_updateStatus()), ); } @override Widget build(BuildContext context) { - return Text( - _status, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ); + return Text(_status, maxLines: 1, overflow: TextOverflow.ellipsis); } Future _updateStatus() async { @@ -554,7 +539,10 @@ class _FloatingDebuggerControlsState extends State controlHeight = _isPaused ? defaultButtonHeight : 0.0; addAutoDisposeListener( serviceConnection - .serviceManager.isolateManager.mainIsolateState?.isPaused, + .serviceManager + .isolateManager + .mainIsolateState + ?.isPaused, () { setState(() { if (_isPaused) { @@ -588,9 +576,7 @@ class _FloatingDebuggerControlsState extends State Container( height: defaultButtonHeight, alignment: Alignment.centerLeft, - padding: const EdgeInsets.symmetric( - horizontal: defaultSpacing, - ), + padding: const EdgeInsets.symmetric(horizontal: defaultSpacing), child: Text( 'Main isolate is paused in the debugger', style: TextStyle(color: colorScheme.onWarningContainer), diff --git a/packages/devtools_app/lib/src/screens/debugger/file_search.dart b/packages/devtools_app/lib/src/screens/debugger/file_search.dart index efb1ac73b89..9d8b81d4658 100644 --- a/packages/devtools_app/lib/src/screens/debugger/file_search.dart +++ b/packages/devtools_app/lib/src/screens/debugger/file_search.dart @@ -21,10 +21,7 @@ const noResultsMsg = 'No files found.'; final _fileNamesCache = {}; class FileSearchField extends StatefulWidget { - const FileSearchField({ - super.key, - required this.codeViewController, - }); + const FileSearchField({super.key, required this.codeViewController}); final CodeViewController codeViewController; @@ -98,9 +95,10 @@ class FileSearchFieldState extends State // If the current query is a continuation of the previous query, then // filter down the previous matches. Otherwise search through all scripts: - final scripts = currentQuery.startsWith(previousQuery) - ? _searchResults.scriptRefs - : scriptManager.sortedScripts.value; + final scripts = + currentQuery.startsWith(previousQuery) + ? _searchResults.scriptRefs + : scriptManager.sortedScripts.value; final searchResults = _createSearchResults(currentQuery, scripts); if (searchResults.scriptRefs.isEmpty) { @@ -137,8 +135,9 @@ class FileSearchFieldState extends State return; } final scriptRef = _scriptsCache[scriptUri]!; - await widget.codeViewController - .showScriptLocation(ScriptLocation(scriptRef)); + await widget.codeViewController.showScriptLocation( + ScriptLocation(scriptRef), + ); _onClose(); } @@ -196,12 +195,13 @@ class FileQuery { final fileName = _fileName(scriptUri); final fileNameIndex = scriptUri.lastIndexOf(fileName); - final matchedSegments = _findExactSegments(fileName) - .map( - (range) => - Range(range.begin + fileNameIndex, range.end + fileNameIndex), - ) - .toList(); + final matchedSegments = + _findExactSegments(fileName) + .map( + (range) => + Range(range.begin + fileNameIndex, range.end + fileNameIndex), + ) + .toList(); return AutoCompleteMatch(scriptUri, matchedSegments: matchedSegments); } @@ -241,17 +241,22 @@ class FileQuery { List matchedSegments; if (isMultiToken) { - matchedSegments = - _findFuzzySegments(scriptUri, query.replaceAll(' ', '')); + matchedSegments = _findFuzzySegments( + scriptUri, + query.replaceAll(' ', ''), + ); } else { final fileName = _fileName(scriptUri); final fileNameIndex = scriptUri.lastIndexOf(fileName); - matchedSegments = _findFuzzySegments(fileName, query) - .map( - (range) => - Range(range.begin + fileNameIndex, range.end + fileNameIndex), - ) - .toList(); + matchedSegments = + _findFuzzySegments(fileName, query) + .map( + (range) => Range( + range.begin + fileNameIndex, + range.end + fileNameIndex, + ), + ) + .toList(); } return AutoCompleteMatch(scriptUri, matchedSegments: matchedSegments); @@ -264,8 +269,9 @@ class FileQuery { final end = start + token.length; matchedSegments.add(Range(start, end)); } - matchedSegments - .sort((rangeA, rangeB) => rangeA.begin.compareTo(rangeB.begin)); + matchedSegments.sort( + (rangeA, rangeB) => rangeA.begin.compareTo(rangeB.begin), + ); return matchedSegments; } @@ -335,9 +341,9 @@ class FileSearchResults { required List exactFileNameMatches, required List exactFullPathMatches, required List fuzzyMatches, - }) : _exactFileNameMatches = exactFileNameMatches, - _exactFullPathMatches = exactFullPathMatches, - _fuzzyMatches = fuzzyMatches; + }) : _exactFileNameMatches = exactFileNameMatches, + _exactFullPathMatches = exactFullPathMatches, + _fuzzyMatches = fuzzyMatches; final List allScripts; final FileQuery query; @@ -347,23 +353,27 @@ class FileSearchResults { FileSearchResults get topMatches => _buildTopMatches(); - List get scriptRefs => query.isEmpty - ? allScripts - : [ - ..._exactFileNameMatches, - ..._exactFullPathMatches, - ..._fuzzyMatches, - ]; - - List get autoCompleteMatches => query.isEmpty - ? allScripts.map((script) => AutoCompleteMatch(script.uri!)).toList() - : [ - ..._exactFileNameMatches - .map(query.createExactFileNameAutoCompleteMatch), - ..._exactFullPathMatches - .map(query.createExactFullPathAutoCompleteMatch), - ..._fuzzyMatches.map(query.createFuzzyMatchAutoCompleteMatch), - ]; + List get scriptRefs => + query.isEmpty + ? allScripts + : [ + ..._exactFileNameMatches, + ..._exactFullPathMatches, + ..._fuzzyMatches, + ]; + + List get autoCompleteMatches => + query.isEmpty + ? allScripts.map((script) => AutoCompleteMatch(script.uri!)).toList() + : [ + ..._exactFileNameMatches.map( + query.createExactFileNameAutoCompleteMatch, + ), + ..._exactFullPathMatches.map( + query.createExactFullPathAutoCompleteMatch, + ), + ..._fuzzyMatches.map(query.createFuzzyMatchAutoCompleteMatch), + ]; FileSearchResults copyWith({ List? allScripts, @@ -383,9 +393,7 @@ class FileSearchResults { FileSearchResults _buildTopMatches() { if (query.isEmpty) { - return copyWith( - allScripts: allScripts.sublist(0, numOfMatchesToShow), - ); + return copyWith(allScripts: allScripts.sublist(0, numOfMatchesToShow)); } if (scriptRefs.length <= numOfMatchesToShow) { diff --git a/packages/devtools_app/lib/src/screens/debugger/key_sets.dart b/packages/devtools_app/lib/src/screens/debugger/key_sets.dart index fa11d8fc345..59e9db1ecb8 100644 --- a/packages/devtools_app/lib/src/screens/debugger/key_sets.dart +++ b/packages/devtools_app/lib/src/screens/debugger/key_sets.dart @@ -15,8 +15,9 @@ final goToLineNumberKeySet = LogicalKeySet( LogicalKeyboardKey.keyG, ); -final goToLineNumberKeySetDescription = - goToLineNumberKeySet.describeKeys(isMacOS: HostPlatform.instance.isMacOS); +final goToLineNumberKeySetDescription = goToLineNumberKeySet.describeKeys( + isMacOS: HostPlatform.instance.isMacOS, +); final searchInFileKeySet = LogicalKeySet( HostPlatform.instance.isMacOS @@ -25,9 +26,7 @@ final searchInFileKeySet = LogicalKeySet( LogicalKeyboardKey.keyF, ); -final escapeKeySet = LogicalKeySet( - LogicalKeyboardKey.escape, -); +final escapeKeySet = LogicalKeySet(LogicalKeyboardKey.escape); final openFileKeySet = LogicalKeySet( HostPlatform.instance.isMacOS @@ -36,5 +35,6 @@ final openFileKeySet = LogicalKeySet( LogicalKeyboardKey.keyP, ); -final openFileKeySetDescription = - openFileKeySet.describeKeys(isMacOS: HostPlatform.instance.isMacOS); +final openFileKeySetDescription = openFileKeySet.describeKeys( + isMacOS: HostPlatform.instance.isMacOS, +); diff --git a/packages/devtools_app/lib/src/screens/debugger/program_explorer.dart b/packages/devtools_app/lib/src/screens/debugger/program_explorer.dart index 9c5bc77a7d4..9032c63a127 100644 --- a/packages/devtools_app/lib/src/screens/debugger/program_explorer.dart +++ b/packages/devtools_app/lib/src/screens/debugger/program_explorer.dart @@ -24,10 +24,7 @@ const libraryIcon = Icons.insert_drive_file; double get _selectedNodeTopSpacing => defaultTreeViewRowHeight * 3; class _ProgramExplorerRow extends StatelessWidget { - const _ProgramExplorerRow({ - required this.node, - this.onTap, - }); + const _ProgramExplorerRow({required this.node, this.onTap}); final VMServiceObjectNode node; final VoidCallback? onTap; @@ -52,9 +49,7 @@ class _ProgramExplorerRow extends StatelessWidget { onTap: onTap, child: Row( children: [ - ProgramStructureIcon( - object: node.object, - ), + ProgramStructureIcon(object: node.object), const SizedBox(width: densePadding), Flexible( child: Text( @@ -202,10 +197,7 @@ class _ProgramExplorerRow extends StatelessWidget { } class ProgramStructureIcon extends StatelessWidget { - const ProgramStructureIcon({ - super.key, - required this.object, - }); + const ProgramStructureIcon({super.key, required this.object}); final ObjRef? object; @@ -251,40 +243,35 @@ class ProgramStructureIcon extends StatelessWidget { height: defaultIconSize, width: defaultIconSize, child: Container( - decoration: icon == null - ? BoxDecoration( - color: color, - shape: BoxShape.circle, - ) - : null, - child: icon == null - ? Center( - child: Text( - character!, - style: TextStyle( - height: 1, - fontFamily: theme.fixedFontStyle.fontFamily, - color: theme.colorScheme.defaultBackgroundColor, - fontSize: smallFontSize, + decoration: + icon == null + ? BoxDecoration(color: color, shape: BoxShape.circle) + : null, + child: + icon == null + ? Center( + child: Text( + character!, + style: TextStyle( + height: 1, + fontFamily: theme.fixedFontStyle.fontFamily, + color: theme.colorScheme.defaultBackgroundColor, + fontSize: smallFontSize, + ), + // Required to center the individual character within the + // shape. Since letters like 'm' are shorter than letters + // like 'f', there's padding applied to the top of shorter + // characters in order for everything to align properly. + // Since we're only dealing with individual characters, we + // want to disable this behavior so shorter characters don't + // appear to be slightly below center. + textHeightBehavior: TextHeightBehavior( + applyHeightToFirstAscent: isShortCharacter!, + applyHeightToLastDescent: false, + ), ), - // Required to center the individual character within the - // shape. Since letters like 'm' are shorter than letters - // like 'f', there's padding applied to the top of shorter - // characters in order for everything to align properly. - // Since we're only dealing with individual characters, we - // want to disable this behavior so shorter characters don't - // appear to be slightly below center. - textHeightBehavior: TextHeightBehavior( - applyHeightToFirstAscent: isShortCharacter!, - applyHeightToLastDescent: false, - ), - ), - ) - : Icon( - icon, - size: defaultIconSize, - color: color, - ), + ) + : Icon(icon, size: defaultIconSize, color: color), ), ); } @@ -308,10 +295,11 @@ class _FileExplorer extends StatefulWidget { class _FileExplorerState extends State<_FileExplorer> with AutoDisposeMixin { late final ScrollController _scrollController; - double get selectedNodeOffset => widget.controller.selectedNodeIndex.value == - -1 - ? -1 - : widget.controller.selectedNodeIndex.value * defaultTreeViewRowHeight; + double get selectedNodeOffset => + widget.controller.selectedNodeIndex.value == -1 + ? -1 + : widget.controller.selectedNodeIndex.value * + defaultTreeViewRowHeight; @override void initState() { @@ -402,9 +390,8 @@ class _ProgramOutlineView extends StatelessWidget { }, ); }, - emptyTreeViewBuilder: () => const Center( - child: Text('Nothing to inspect'), - ), + emptyTreeViewBuilder: + () => const Center(child: Text('Nothing to inspect')), ); }, ); @@ -436,13 +423,14 @@ class ProgramExplorer extends StatelessWidget { if (!initialized) { body = const CenteredCircularProgressIndicator(); } else { - final fileExplorerHeader = displayHeader - ? AreaPaneHeader( - title: Text(title), - includeTopBorder: false, - roundedTopBorder: false, - ) - : const BlankHeader(); + final fileExplorerHeader = + displayHeader + ? AreaPaneHeader( + title: Text(title), + includeTopBorder: false, + roundedTopBorder: false, + ) + : const BlankHeader(); final fileExplorer = _FileExplorer( controller: controller, onItemExpanded: onItemExpanded, @@ -460,33 +448,35 @@ class ProgramExplorer extends StatelessWidget { // // See https://github.com/flutter/devtools/issues/3447. return serviceConnection - .serviceManager.connectedApp!.isDartWebAppNow! + .serviceManager + .connectedApp! + .isDartWebAppNow! ? Column( - children: [ - fileExplorerHeader, - Expanded(child: fileExplorer), - ], - ) + children: [ + fileExplorerHeader, + Expanded(child: fileExplorer), + ], + ) : FlexSplitColumn( - totalHeight: constraints.maxHeight, - initialFractions: const [0.7, 0.3], - minSizes: const [0.0, 0.0], - headers: [ - fileExplorerHeader as PreferredSizeWidget, - const AreaPaneHeader( - title: Text('Outline'), - roundedTopBorder: false, - ), - ], - children: [ - fileExplorer, - _ProgramOutlineView( - controller: controller, - onItemExpanded: onItemExpanded, - onItemSelected: onItemSelected, - ), - ], - ); + totalHeight: constraints.maxHeight, + initialFractions: const [0.7, 0.3], + minSizes: const [0.0, 0.0], + headers: [ + fileExplorerHeader as PreferredSizeWidget, + const AreaPaneHeader( + title: Text('Outline'), + roundedTopBorder: false, + ), + ], + children: [ + fileExplorer, + _ProgramOutlineView( + controller: controller, + onItemExpanded: onItemExpanded, + onItemSelected: onItemSelected, + ), + ], + ); }, ); } diff --git a/packages/devtools_app/lib/src/screens/debugger/program_explorer_controller.dart b/packages/devtools_app/lib/src/screens/debugger/program_explorer_controller.dart index b70f789b199..99f0ab25d64 100644 --- a/packages/devtools_app/lib/src/screens/debugger/program_explorer_controller.dart +++ b/packages/devtools_app/lib/src/screens/debugger/program_explorer_controller.dart @@ -17,9 +17,7 @@ class ProgramExplorerController extends DisposableController with AutoDisposeControllerMixin { /// [showCodeNodes] controls whether or not [Code] nodes are displayed in the /// outline view. - ProgramExplorerController({ - this.showCodeNodes = false, - }); + ProgramExplorerController({this.showCodeNodes = false}); /// The outline view nodes for the currently selected library. ValueListenable> get outlineNodes => _outlineNodes; @@ -73,22 +71,20 @@ class ProgramExplorerController extends DisposableController final isolate = serviceConnection.serviceManager.isolateManager.selectedIsolate.value; - final libraries = isolate != null - ? serviceConnection.serviceManager.isolateManager - .isolateState(isolate) - .isolateNow! - .libraries! - : []; + final libraries = + isolate != null + ? serviceConnection.serviceManager.isolateManager + .isolateState(isolate) + .isolateNow! + .libraries! + : []; if (scriptManager.sortedScripts.value.isEmpty && isolate != null) { await scriptManager.retrieveAndSortScripts(isolate); } // Build the initial tree. - final nodes = VMServiceObjectNode.createRootsFrom( - this, - libraries, - ); + final nodes = VMServiceObjectNode.createRootsFrom(this, libraries); rootObjectNodesInternal.replaceAll(nodes); _initialized.value = true; } @@ -97,10 +93,7 @@ class ProgramExplorerController extends DisposableController // Re-initialize after reload. // TODO(elliette): If file was opened from before the reload, we should try // to open that one instead of the entrypoint file. - addAutoDisposeListener( - scriptManager.sortedScripts, - refresh, - ); + addAutoDisposeListener(scriptManager.sortedScripts, refresh); } Future selectScriptNode(ScriptRef? script) async { @@ -150,9 +143,10 @@ class ProgramExplorerController extends DisposableController final matchingNode = depthFirstTraversal( node, returnCondition: matchingNodeCondition, - exploreChildrenCondition: includeCollapsedNodes - ? null - : (VMServiceObjectNode node) => node.isExpanded, + exploreChildrenCondition: + includeCollapsedNodes + ? null + : (VMServiceObjectNode node) => node.isExpanded, action: (VMServiceObjectNode _) => index++, ); if (matchingNode != null) return index; @@ -251,14 +245,17 @@ class ProgramExplorerController extends DisposableController Future populateNode(VMServiceObjectNode node) async { final object = node.object; final service = serviceConnection.serviceManager.service; - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id; + final isolateId = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id; Future> getObjects(Iterable objs) { return Future.wait( - objs.map( - (o) => service!.getObject(isolateId!, o.id!), - ), + objs.map((o) => service!.getObject(isolateId!, o.id!)), ); } @@ -285,10 +282,12 @@ class ProgramExplorerController extends DisposableController // fetching it again. if (func.unoptimizedCode != null && func.unoptimizedCode?.id! != code.id!) { - unoptimizedCode = await service.getObject( - isolateId, - func.unoptimizedCode!.id!, - ) as Code; + unoptimizedCode = + await service.getObject( + isolateId, + func.unoptimizedCode!.id!, + ) + as Code; } func.unoptimizedCode = unoptimizedCode; } @@ -332,8 +331,13 @@ class ProgramExplorerController extends DisposableController /// which is the source location of the target [object]. Future searchFileExplorer(ObjRef object) async { final service = serviceConnection.serviceManager.service!; - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!; + final isolateId = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!; // If `object` is a library, it will always be a root node and is simple to // find. @@ -370,10 +374,7 @@ class ProgramExplorerController extends DisposableController // If we couldn't find the target library as a root node, it's possible we // have a library defined using the `library` keyword by the user, which // will likely be under a directory node. - libNode ??= breadthFirstSearchObject( - scriptObj, - rootObjectNodes.value, - ); + libNode ??= breadthFirstSearchObject(scriptObj, rootObjectNodes.value); // If the object's owning script URI is the same as the target library URI, // return the library node as the match. diff --git a/packages/devtools_app/lib/src/screens/debugger/program_explorer_model.dart b/packages/devtools_app/lib/src/screens/debugger/program_explorer_model.dart index 21453143e97..282ddad5751 100644 --- a/packages/devtools_app/lib/src/screens/debugger/program_explorer_model.dart +++ b/packages/devtools_app/lib/src/screens/debugger/program_explorer_model.dart @@ -60,11 +60,7 @@ class VMServiceObjectNode extends TreeNode { return _outline; } - final root = VMServiceObjectNode( - controller, - '', - ObjRef(id: '0'), - ); + final root = VMServiceObjectNode(controller, '', ObjRef(id: '0')); String uri; Library lib; @@ -84,15 +80,17 @@ class VMServiceObjectNode extends TreeNode { // script's URI. if (libNode == null) { final service = serviceConnection.serviceManager.service!; - final isolate = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!; + final isolate = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value!; final libRef = serviceConnection.serviceManager.isolateManager .isolateState(isolate) .isolateNow! .libraries! - .firstWhere( - (lib) => script!.uri!.startsWith(lib.uri!), - ); + .firstWhere((lib) => script!.uri!.startsWith(lib.uri!)); lib = await service.getObject(isolate.id!, libRef.id!) as Library; } else { lib = libNode.object as Library; @@ -118,11 +116,7 @@ class VMServiceObjectNode extends TreeNode { } for (final function in lib.functions!) { if (function.location?.script?.uri == uri) { - final node = VMServiceObjectNode( - controller, - function.name, - function, - ); + final node = VMServiceObjectNode(controller, function.name, function); await controller.populateNode(node); _buildCodeNodes(node.object as Func, node); root.addChild(node); @@ -131,11 +125,7 @@ class VMServiceObjectNode extends TreeNode { for (final field in lib.variables!) { if (field.location?.script?.uri == uri) { - final node = VMServiceObjectNode( - controller, - field.name, - field, - ); + final node = VMServiceObjectNode(controller, field.name, field); await controller.populateNode(node); root.addChild(node); } @@ -178,9 +168,10 @@ class VMServiceObjectNode extends TreeNode { // Clear out the _childrenAsMap map. root._trimChildrenAsMapEntries(); - final processed = root.children - .map((e) => e._collapseSingleChildDirectoryNodes()) - .toList(); + final processed = + root.children + .map((e) => e._collapseSingleChildDirectoryNodes()) + .toList(); root.children.clear(); root.addAllChildren(processed); @@ -194,8 +185,14 @@ class VMServiceObjectNode extends TreeNode { // Place the root library's parent node at the top of the explorer if it's // part of a package. Otherwise, it's a file path and its directory should // appear near the top of the list anyway. - final rootLibUri = serviceConnection.serviceManager.isolateManager - .mainIsolateState?.isolateNow?.rootLib?.uri; + final rootLibUri = + serviceConnection + .serviceManager + .isolateManager + .mainIsolateState + ?.isolateNow + ?.rootLib + ?.uri; if (rootLibUri != null) { if (rootLibUri.startsWith('package:') || rootLibUri.startsWith('google3:')) { @@ -224,11 +221,7 @@ class VMServiceObjectNode extends TreeNode { for (final part in parts) { // Directory nodes shouldn't be selectable unless they're a library node. - node = node._lookupOrCreateChild( - part, - null, - isSelectable: false, - ); + node = node._lookupOrCreateChild(part, null, isSelectable: false); } node = node._lookupOrCreateChild(name, script); @@ -251,13 +244,7 @@ class VMServiceObjectNode extends TreeNode { } final code = function.code; if (code != null) { - node.addChild( - VMServiceObjectNode( - controller, - code.name, - code, - ), - ); + node.addChild(VMServiceObjectNode(controller, code.name, code)); final unoptimizedCode = function.unoptimizedCode; // It's possible for `function.code` to be unoptimized code, so don't // create a duplicate node in that situation. @@ -314,11 +301,8 @@ class VMServiceObjectNode extends TreeNode { } return this; } - final updated = children - .map( - (e) => e._collapseSingleChildDirectoryNodes(), - ) - .toList(); + final updated = + children.map((e) => e._collapseSingleChildDirectoryNodes()).toList(); children.clear(); addAllChildren(updated); return this; @@ -361,14 +345,12 @@ class VMServiceObjectNode extends TreeNode { if (scriptRef != null) { final fetchedScript = await scriptManager.getScript(scriptRef); - final position = tokenPos == 0 - ? null - : SourcePosition.calculatePosition(fetchedScript!, tokenPos!); - - location = ScriptLocation( - scriptRef, - location: position, - ); + final position = + tokenPos == 0 + ? null + : SourcePosition.calculatePosition(fetchedScript!, tokenPos!); + + location = ScriptLocation(scriptRef, location: position); } } 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 0dd8fc591ad..4355d71bde9 100644 --- a/packages/devtools_app/lib/src/screens/debugger/span_parser.dart +++ b/packages/devtools_app/lib/src/screens/debugger/span_parser.dart @@ -17,8 +17,11 @@ abstract class SpanParser { final scopeStack = ScopeStack(); final scanner = LineScanner(src); while (!scanner.isDone) { - final foundMatch = - grammar.topLevelMatcher.scan(grammar, scanner, scopeStack); + final foundMatch = grammar.topLevelMatcher.scan( + grammar, + scanner, + scopeStack, + ); if (!foundMatch && !scanner.isDone) { // Found no match, move forward by a character and try again. scanner.readChar(); @@ -80,8 +83,8 @@ class ScopeSpan { required this.scopes, required ScopeStackLocation startLocation, required ScopeStackLocation endLocation, - }) : _startLocation = startLocation, - _endLocation = endLocation; + }) : _startLocation = startLocation, + _endLocation = endLocation; ScopeStackLocation get startLocation => _startLocation; ScopeStackLocation get endLocation => _endLocation; @@ -162,8 +165,9 @@ class ScopeSpan { /// using the 'includes' keyword. class Repository { Repository.build(Map grammarJson) { - final repositoryJson = (grammarJson['repository'] as Map?) - ?.cast>(); + final repositoryJson = + (grammarJson['repository'] as Map?) + ?.cast>(); if (repositoryJson == null) { return; } @@ -225,8 +229,9 @@ abstract class GrammarMatcher { final startOffset = match.indexOf(captureText); final capture = captures[i.toString()] as Map; final captureStartLocation = matchStartLocation.offset(startOffset); - final captureEndLocation = - captureStartLocation.offset(captureText.length); + final captureEndLocation = captureStartLocation.offset( + captureText.length, + ); final captureName = capture['name'] as String?; scopeStack.push(captureName, captureStartLocation); @@ -237,8 +242,9 @@ abstract class GrammarMatcher { scanner.substring(0, captureEndLocation.position), position: captureStartLocation.position, ); - GrammarMatcher.fromJson(capture) - .scan(grammar, captureScanner, scopeStack); + GrammarMatcher.fromJson( + capture, + ).scan(grammar, captureScanner, scopeStack); } scopeStack.pop(captureName, captureEndLocation); @@ -252,10 +258,11 @@ abstract class GrammarMatcher { /// A simple matcher which matches a single line. class _SimpleMatcher extends GrammarMatcher { _SimpleMatcher(super.json) - : match = RegExp(json['match'] as String, multiLine: true), - captures = (json['captures'] as Map?) - ?.cast>(), - super._(); + : match = RegExp(json['match'] as String, multiLine: true), + captures = + (json['captures'] as Map?) + ?.cast>(), + super._(); static bool isType(Map json) { return json.containsKey('match'); @@ -289,22 +296,25 @@ class _SimpleMatcher extends GrammarMatcher { class _MultilineMatcher extends GrammarMatcher { _MultilineMatcher(super.json) - : begin = RegExp(json['begin'] as String, multiLine: true), - beginCaptures = json['beginCaptures'] as Map?, - contentName = json['contentName'] as String?, - end = json['end'] == null - ? null - : RegExp(json['end'] as String, multiLine: true), - endCaptures = json['endCaptures'] as Map?, - captures = json['captures'] as Map?, - whileCond = json['while'] == null - ? null - : RegExp(json['while'] as String, multiLine: true), - patterns = (json['patterns'] as List?) - ?.cast>() - .map((e) => GrammarMatcher.fromJson(e)) - .toList(), - super._(); + : begin = RegExp(json['begin'] as String, multiLine: true), + beginCaptures = json['beginCaptures'] as Map?, + contentName = json['contentName'] as String?, + end = + json['end'] == null + ? null + : RegExp(json['end'] as String, multiLine: true), + endCaptures = json['endCaptures'] as Map?, + captures = json['captures'] as Map?, + whileCond = + json['while'] == null + ? null + : RegExp(json['while'] as String, multiLine: true), + patterns = + (json['patterns'] as List?) + ?.cast>() + .map((e) => GrammarMatcher.fromJson(e)) + .toList(), + super._(); static bool isType(Map json) { return json.containsKey('begin') && @@ -482,11 +492,7 @@ class _MultilineMatcher extends GrammarMatcher { } // Now, split any spans produced whileContentBeginMarker by `whileCond`. - scopeStack.splitFromMarker( - scanner, - whileContentBeginMarker, - whileCond!, - ); + scopeStack.splitFromMarker(scanner, whileContentBeginMarker, whileCond!); } else { throw StateError( "One of 'end' or 'while' must be provided for rule: $name", @@ -517,11 +523,12 @@ class _MultilineMatcher extends GrammarMatcher { class _PatternMatcher extends GrammarMatcher { _PatternMatcher(super.json) - : patterns = (json['patterns'] as List?) - ?.cast>() - .map((e) => GrammarMatcher.fromJson(e)) - .toList(), - super._(); + : patterns = + (json['patterns'] as List?) + ?.cast>() + .map((e) => GrammarMatcher.fromJson(e)) + .toList(), + super._(); static bool isType(Map json) { return json.containsKey('patterns'); @@ -554,9 +561,7 @@ class _PatternMatcher extends GrammarMatcher { /// `patterns` array. Allows for executing rules defined within a /// [Repository]. class _IncludeMatcher extends GrammarMatcher { - _IncludeMatcher(String include) - : include = include.substring(1), - super._({}); + _IncludeMatcher(String include) : include = include.substring(1), super._({}); final String include; @@ -575,9 +580,7 @@ class _IncludeMatcher extends GrammarMatcher { @override Map toJson() { - return { - 'include': include, - }; + return {'include': include}; } } @@ -673,8 +676,9 @@ class ScopeStack { _nextLocation = begin.location; // Add the split spans individually. - for (final span in spansToSplit - .expand((spanToSplit) => spanToSplit.split(scanner, condition))) { + for (final span in spansToSplit.expand( + (spanToSplit) => spanToSplit.split(scanner, condition), + )) { // To handler spans with multiple scopes, we need to push each scope, and // then pop each scope. We cannot use `add`. for (final scope in span.scopes) { @@ -686,10 +690,7 @@ class ScopeStack { } } - void _produceSpan( - Set scopes, { - required ScopeStackLocation end, - }) { + void _produceSpan(Set scopes, {required ScopeStackLocation end}) { // Don't produce zero-width spans. if (end.position == _nextLocation.position) return; @@ -733,10 +734,7 @@ class ScopeStackItem { /// /// Used for back-tracking when handling nested multiline tokens. class ScopeStackMarker { - ScopeStackMarker({ - required this.spanIndex, - required this.location, - }); + ScopeStackMarker({required this.spanIndex, required this.location}); final int spanIndex; 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 b1f92e8d418..db1fc64f488 100644 --- a/packages/devtools_app/lib/src/screens/debugger/syntax_highlighter.dart +++ b/packages/devtools_app/lib/src/screens/debugger/syntax_highlighter.dart @@ -18,10 +18,8 @@ final _log = Logger('syntax_highlighter'); class SyntaxHighlighter { SyntaxHighlighter({String? source}) : source = source ?? ''; - SyntaxHighlighter.withGrammar({ - Grammar? grammar, - String? source, - }) : source = source ?? '' { + SyntaxHighlighter.withGrammar({Grammar? grammar, String? source}) + : source = source ?? '' { _grammar = grammar; } @@ -113,10 +111,7 @@ class SyntaxHighlighter { /// Enters a new scope for a span of text. Returns a [List] /// containing the stylized text from within the scope. - List _scope( - ScopeSpan currentScope, - List scopes, - ) { + List _scope(ScopeSpan currentScope, List scopes) { return _highlightLoopHelper( currentScope: currentScope, loopCondition: () => currentScope.contains(_currentPosition), @@ -143,27 +138,14 @@ class SyntaxHighlighter { _currentPosition, ); if (text.isNotEmpty) { - sourceSpans.add( - TextSpan( - style: _getStyleForSpan(), - text: text, - ), - ); + sourceSpans.add(TextSpan(style: _getStyleForSpan(), text: text)); } - sourceSpans.addAll( - _scope( - scopes.removeAt(0), - scopes, - ), - ); + sourceSpans.addAll(_scope(scopes.removeAt(0), scopes)); // Reset the beginning of the current span to the first position after // the close of the span that was just processed. currentScopeBegin = _currentPosition; } else if (_atNewline()) { - currentScopeBegin = _processNewlines( - sourceSpans, - currentScopeBegin!, - ); + currentScopeBegin = _processNewlines(sourceSpans, currentScopeBegin!); } else { ++_currentPosition; } @@ -175,12 +157,7 @@ class SyntaxHighlighter { _currentPosition, ); if (text.isNotEmpty) { - sourceSpans.add( - TextSpan( - style: _getStyleForSpan(), - text: text, - ), - ); + sourceSpans.add(TextSpan(style: _getStyleForSpan(), text: text)); } if (currentScope != null) { _spanStack.removeLast(); @@ -201,10 +178,7 @@ class SyntaxHighlighter { sourceSpans.add( TextSpan( style: _getStyleForSpan(), - text: _processedSource.substring( - currentScopeBegin, - _currentPosition, - ), + text: _processedSource.substring(currentScopeBegin, _currentPosition), ), ); } @@ -220,9 +194,7 @@ class SyntaxHighlighter { } Map _buildSyntaxColorTable(ThemeData theme) { - final commentStyle = TextStyle( - color: theme.colorScheme.commentSyntaxColor, - ); + final commentStyle = TextStyle(color: theme.colorScheme.commentSyntaxColor); final functionStyle = TextStyle( color: theme.colorScheme.functionSyntaxColor, ); @@ -238,9 +210,7 @@ class SyntaxHighlighter { final variableStyle = TextStyle( color: theme.colorScheme.variableSyntaxColor, ); - final stringStyle = TextStyle( - color: theme.colorScheme.stringSyntaxColor, - ); + final stringStyle = TextStyle(color: theme.colorScheme.stringSyntaxColor); final numericConstantStyle = TextStyle( color: theme.colorScheme.numericConstantSyntaxColor, ); @@ -268,13 +238,9 @@ class SyntaxHighlighter { 'variable.language.dart', ]; - const numericConstantScopes = [ - 'constant.numeric.dart', - ]; + const numericConstantScopes = ['constant.numeric.dart']; - const functionScopes = [ - 'entity.name.function.dart', - ]; + const functionScopes = ['entity.name.function.dart']; const controlFlowScopes = [ 'keyword.control.catch-exception.dart', @@ -308,9 +274,7 @@ class SyntaxHighlighter { List scopes, TextStyle style, ) { - return { - for (final scope in scopes) scope: style, - }; + return {for (final scope in scopes) scope: style}; } return { diff --git a/packages/devtools_app/lib/src/screens/debugger/variables.dart b/packages/devtools_app/lib/src/screens/debugger/variables.dart index 1347fde4631..0a090a57d38 100644 --- a/packages/devtools_app/lib/src/screens/debugger/variables.dart +++ b/packages/devtools_app/lib/src/screens/debugger/variables.dart @@ -36,18 +36,15 @@ class Variables extends StatelessWidget { } else { return TreeView( dataRootsListenable: serviceConnection.appState.variables, - dataDisplayProvider: (variable, onPressed) => DisplayProvider( - variable: variable, - onTap: onPressed, - ), + dataDisplayProvider: + (variable, onPressed) => + DisplayProvider(variable: variable, onTap: onPressed), onItemSelected: onItemPressed, ); } } - Future onDapItemExpanded( - DapObjectNode node, - ) async { + Future onDapItemExpanded(DapObjectNode node) async { if (node.isExpanded) { for (final child in node.children) { await child.fetchChildren(); @@ -55,9 +52,7 @@ class Variables extends StatelessWidget { } } - Future onItemPressed( - DartObjectNode v, - ) async { + Future onItemPressed(DartObjectNode v) async { // On expansion, lazily build the variables tree for performance reasons. if (v.isExpanded) { await Future.wait(v.children.map(buildVariablesTree)); 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 0664dbd399a..c0c53b8d925 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 @@ -23,11 +23,7 @@ const _kNotificationCardSize = Size(475, 132); const _kSearchFieldFullWidth = 314.0; const _kSearchFieldSplitScreenWidth = 280.0; -enum TableViewType { - domainView, - pathView, - singleUrlView, -} +enum TableViewType { domainView, pathView, singleUrlView } /// A view that display all deep links for the app. class DeepLinkListView extends StatefulWidget { @@ -144,32 +140,28 @@ class _ValidatedDeepLinksView extends StatelessWidget { if (displayOptions.showSplitScreen) { return Row( children: [ - Expanded( - child: _AllDeepLinkDataTable(controller: controller), - ), - VerticalDivider( - width: 1.0, - color: Theme.of(context).focusColor, - ), + Expanded(child: _AllDeepLinkDataTable(controller: controller)), + VerticalDivider(width: 1.0, color: Theme.of(context).focusColor), Expanded( child: ValueListenableBuilder( valueListenable: controller.selectedLink, - builder: (context, _, _) => TabBarView( - children: [ - ValidationDetailView( - controller: controller, - viewType: TableViewType.domainView, + builder: + (context, _, _) => TabBarView( + children: [ + ValidationDetailView( + controller: controller, + viewType: TableViewType.domainView, + ), + ValidationDetailView( + controller: controller, + viewType: TableViewType.pathView, + ), + ValidationDetailView( + controller: controller, + viewType: TableViewType.singleUrlView, + ), + ], ), - ValidationDetailView( - controller: controller, - viewType: TableViewType.pathView, - ), - ValidationDetailView( - controller: controller, - viewType: TableViewType.singleUrlView, - ), - ], - ), ), ), ], @@ -183,9 +175,7 @@ class _ValidatedDeepLinksView extends StatelessWidget { pathErrorCount: displayOptions.pathErrorCount, controller: controller, ), - Expanded( - child: _AllDeepLinkDataTable(controller: controller), - ), + Expanded(child: _AllDeepLinkDataTable(controller: controller)), ], ); }, @@ -236,8 +226,9 @@ class _DataTable extends StatelessWidget { ], ], selectionNotifier: controller.selectedLink, - defaultSortColumn: (viewType == TableViewType.pathView ? path : domain) - as ColumnData, + defaultSortColumn: + (viewType == TableViewType.pathView ? path : domain) + as ColumnData, defaultSortDirection: SortDirection.ascending, sortOriginalData: true, onItemSelected: (linkdata) { @@ -279,8 +270,12 @@ class _DeepLinkListViewTopPanel extends StatelessWidget { _ConfigurationDropdown( title: 'iOS Configuration:', valueListenable: controller.selectedIosConfigurationIndex, - configurations: controller - .selectedProject.value!.iosBuildOptions.configurations, + configurations: + controller + .selectedProject + .value! + .iosBuildOptions + .configurations, onChanged: controller.updateSelectedIosConfigurationIndex, ), const SizedBox(width: denseSpacing), @@ -337,9 +332,7 @@ class _ConfigurationDropdown extends StatelessWidget { } class _AllDeepLinkDataTable extends StatelessWidget { - const _AllDeepLinkDataTable({ - required this.controller, - }); + const _AllDeepLinkDataTable({required this.controller}); final DeepLinksController controller; @@ -359,19 +352,18 @@ class _AllDeepLinkDataTable extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( - padding: - const EdgeInsets.symmetric(horizontal: defaultSpacing), - child: Text( - 'All deep links', - style: textTheme.titleMedium, + padding: const EdgeInsets.symmetric( + horizontal: defaultSpacing, ), + child: Text('All deep links', style: textTheme.titleMedium), ), Padding( padding: const EdgeInsets.symmetric(horizontal: denseSpacing), child: SizedBox( - width: controller.displayOptions.showSplitScreen - ? _kSearchFieldSplitScreenWidth - : _kSearchFieldFullWidth, + width: + controller.displayOptions.showSplitScreen + ? _kSearchFieldSplitScreenWidth + : _kSearchFieldFullWidth, child: DevToolsClearableTextField( labelText: '', hintText: 'Search a URL, domain or path', @@ -391,14 +383,8 @@ class _AllDeepLinkDataTable extends StatelessWidget { height: defaultHeaderHeight, child: TabBar( tabs: [ - DevToolsTab.create( - tabName: 'Domain view', - gaPrefix: gaPrefix, - ), - DevToolsTab.create( - tabName: 'Path view', - gaPrefix: gaPrefix, - ), + DevToolsTab.create(tabName: 'Domain view', gaPrefix: gaPrefix), + DevToolsTab.create(tabName: 'Path view', gaPrefix: gaPrefix), DevToolsTab.create( tabName: 'Single URL view', gaPrefix: gaPrefix, @@ -411,25 +397,26 @@ class _AllDeepLinkDataTable extends StatelessWidget { Expanded( child: ValueListenableBuilder( valueListenable: controller.displayLinkDatasNotifier, - builder: (context, linkDatas, _) => TabBarView( - children: [ - _DataTable( - viewType: TableViewType.domainView, - linkDatas: linkDatas.byDomain, - controller: controller, - ), - _DataTable( - viewType: TableViewType.pathView, - linkDatas: linkDatas.byPath, - controller: controller, - ), - _DataTable( - viewType: TableViewType.singleUrlView, - linkDatas: linkDatas.all, - controller: controller, + builder: + (context, linkDatas, _) => TabBarView( + children: [ + _DataTable( + viewType: TableViewType.domainView, + linkDatas: linkDatas.byDomain, + controller: controller, + ), + _DataTable( + viewType: TableViewType.pathView, + linkDatas: linkDatas.byPath, + controller: controller, + ), + _DataTable( + viewType: TableViewType.singleUrlView, + linkDatas: linkDatas.all, + controller: controller, + ), + ], ), - ], - ), ), ), ], @@ -471,8 +458,9 @@ class _NotificationCardSection extends StatelessWidget { controller.updateDisplayOptions(showSplitScreen: true); }, child: const Padding( - padding: - EdgeInsets.symmetric(horizontal: intermediateSpacing), + padding: EdgeInsets.symmetric( + horizontal: intermediateSpacing, + ), child: Text('Fix domain'), ), ), @@ -492,8 +480,9 @@ class _NotificationCardSection extends StatelessWidget { controller.updateDisplayOptions(showSplitScreen: true); }, child: const Padding( - padding: - EdgeInsets.symmetric(horizontal: intermediateSpacing), + padding: EdgeInsets.symmetric( + horizontal: intermediateSpacing, + ), child: Text('Fix path'), ), ), @@ -543,10 +532,7 @@ class NotificationCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title), - Text( - description, - style: theme.subtleTextStyle, - ), + Text(description, style: theme.subtleTextStyle), Expanded( child: Align( alignment: Alignment.bottomRight, diff --git a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_controller.dart b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_controller.dart index 828348cf672..a2b5629d6c7 100644 --- a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_controller.dart +++ b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_controller.dart @@ -175,10 +175,7 @@ class DeepLinksController extends DisposableController domain: linkData.domain, path: linkData.path, scheme: linkData.scheme.union(previousRecord?.scheme ?? {}), - os: { - if (previousRecord != null) ...previousRecord.os, - ...linkData.os, - }, + os: {if (previousRecord != null) ...previousRecord.os, ...linkData.os}, associatedDomains: [ ...previousRecord?.associatedDomains ?? [], if (linkData.domain != null) linkData.domain!, @@ -202,10 +199,7 @@ class DeepLinksController extends DisposableController domain: linkData.domain, path: linkData.path, scheme: linkData.scheme.union(previousRecord?.scheme ?? {}), - os: { - if (previousRecord != null) ...previousRecord.os, - ...linkData.os, - }, + os: {if (previousRecord != null) ...previousRecord.os, ...linkData.os}, associatedPath: [ ...previousRecord?.associatedPath ?? [], if (linkData.path != null && !linkData.path!.isExcluded) @@ -306,8 +300,9 @@ class DeepLinksController extends DisposableController if (selectedProject.value!.androidVariants.isEmpty) { return; } - final variant = selectedProject - .value!.androidVariants[selectedAndroidVariantIndex.value]; + final variant = + selectedProject.value!.androidVariants[selectedAndroidVariantIndex + .value]; await ga.timeAsync( gac.deeplink, gac.AnalyzeFlutterProject.loadAppLinks.name, @@ -322,9 +317,8 @@ class DeepLinksController extends DisposableController ga.impression( gac.deeplink, gac.AnalyzeFlutterProject.androidAppLinksSettingsLoaded.name, - screenMetricsProvider: () => DeepLinkScreenMetrics( - androidAppId: result.applicationId, - ), + screenMetricsProvider: + () => DeepLinkScreenMetrics(androidAppId: result.applicationId), ); } catch (_) { ga.select( @@ -360,9 +354,9 @@ class DeepLinksController extends DisposableController ga.impression( gac.deeplink, gac.AnalyzeFlutterProject.iosUniversalLinkSettingsLoaded.name, - screenMetricsProvider: () => DeepLinkScreenMetrics( - iosBundleId: result.bundleIdentifier, - ), + screenMetricsProvider: + () => + DeepLinkScreenMetrics(iosBundleId: result.bundleIdentifier), ); } catch (_) { pagePhase.value = PagePhase.validationErrorPage; @@ -425,8 +419,9 @@ class DeepLinksController extends DisposableController domainPathToLinkData[domainAndPath] = LinkData( domain: appLink.host, path: Path(path: appLink.path), - pathErrors: - _getPathErrorsFromIntentFilterChecks(appLink.intentFilterChecks), + pathErrors: _getPathErrorsFromIntentFilterChecks( + appLink.intentFilterChecks, + ), os: {PlatformOS.android}, scheme: {if (scheme != null) scheme}, ); @@ -481,8 +476,9 @@ class DeepLinksController extends DisposableController final generatedAssetLinksForSelectedLink = ValueNotifier(null); - final displayOptionsNotifier = - ValueNotifier(DisplayOptions()); + final displayOptionsNotifier = ValueNotifier( + DisplayOptions(), + ); /// The [TextEditingController] for the search text field. final textEditingController = TextEditingController(); @@ -491,8 +487,10 @@ class DeepLinksController extends DisposableController bool addLocalFingerprint(String fingerprint) { // A valid fingerprint consists of 32 pairs of hexadecimal digits separated by colons. bool isValidFingerprint(String input) { - final pattern = - RegExp(r'^([0-9a-f]{2}:){31}[0-9a-f]{2}$', caseSensitive: false); + final pattern = RegExp( + r'^([0-9a-f]{2}:){31}[0-9a-f]{2}$', + caseSensitive: false, + ); return pattern.hasMatch(input); } @@ -511,23 +509,22 @@ class DeepLinksController extends DisposableController generatedAssetLinksForSelectedLink.value = null; final domain = selectedLink.value!.domain; if (domain != null) { - generatedAssetLinksForSelectedLink.value = - await deepLinksService.generateAssetLinks( - domain: domain, - applicationId: applicationId, - localFingerprint: localFingerprint.value, - ); + generatedAssetLinksForSelectedLink.value = await deepLinksService + .generateAssetLinks( + domain: domain, + applicationId: applicationId, + localFingerprint: localFingerprint.value, + ); } } Future> _validateDomain(List rawLinkdatas) async { - final domains = rawLinkdatas - .where( - (linkdata) => linkdata.domain != null, - ) - .map((linkdata) => linkdata.domain!) - .toSet() - .toList(); + final domains = + rawLinkdatas + .where((linkdata) => linkdata.domain != null) + .map((linkdata) => linkdata.domain!) + .toSet() + .toList(); Map> androidDomainErrors = {}; Map> iosDomainErrors = {}; @@ -568,12 +565,16 @@ class DeepLinksController extends DisposableController if (linkdata.os.contains(PlatformOS.ios)) ...(iosDomainErrors[linkdata.domain] ?? []), ]; - final hasAndroidAssetLinksFile = !(androidDomainErrors[linkdata.domain] - ?.contains(AndroidDomainError.existence) ?? - false); - final hasIosAasaFile = !(iosDomainErrors[linkdata.domain] - ?.contains(IosDomainError.existence) ?? - false); + final hasAndroidAssetLinksFile = + !(androidDomainErrors[linkdata.domain]?.contains( + AndroidDomainError.existence, + ) ?? + false); + final hasIosAasaFile = + !(iosDomainErrors[linkdata.domain]?.contains( + IosDomainError.existence, + ) ?? + false); if (linkdata.os.contains(PlatformOS.ios)) { final iosPaths = iosDomainPaths[linkdata.domain] ?? []; @@ -644,19 +645,13 @@ class DeepLinksController extends DisposableController if (FeatureFlags.deepLinkIosCheck) ..._rawIosLinkDatas, ]; if (linkdata.isEmpty) { - ga.select( - gac.deeplink, - gac.AnalyzeFlutterProject.flutterNoAppLink.name, - ); + ga.select(gac.deeplink, gac.AnalyzeFlutterProject.flutterNoAppLink.name); pagePhase.value = PagePhase.noLinks; return; } // There are deep links to validate. - ga.select( - gac.deeplink, - gac.AnalyzeFlutterProject.flutterHasAppLinks.name, - ); + ga.select(gac.deeplink, gac.AnalyzeFlutterProject.flutterHasAppLinks.name); linkdata = await _validateDomain(linkdata); if (pagePhase.value == PagePhase.validationErrorPage) { return; @@ -673,12 +668,14 @@ class DeepLinksController extends DisposableController byPath: linkDatasByPath(linkdata), ); displayOptionsNotifier.value = displayOptionsNotifier.value.copyWith( - domainErrorCount: validatedLinkDatas.byDomain - .where((element) => element.domainErrors.isNotEmpty) - .length, - pathErrorCount: validatedLinkDatas.byPath - .where((element) => element.pathErrors.isNotEmpty) - .length, + domainErrorCount: + validatedLinkDatas.byDomain + .where((element) => element.domainErrors.isNotEmpty) + .length, + pathErrorCount: + validatedLinkDatas.byPath + .where((element) => element.pathErrors.isNotEmpty) + .length, ); applyFilters(); @@ -697,17 +694,20 @@ class DeepLinksController extends DisposableController late final LinkData linkdata; switch (viewType) { case TableViewType.domainView: - linkdata = linkDatas.byDomain + linkdata = + linkDatas.byDomain .where((e) => e.domainErrors.isNotEmpty) .firstOrNull ?? linkDatas.byDomain.first; case TableViewType.pathView: - linkdata = linkDatas.byPath + linkdata = + linkDatas.byPath .where((e) => e.pathErrors.isNotEmpty) .firstOrNull ?? linkDatas.byPath.first; case TableViewType.singleUrlView: - linkdata = linkDatas.all + linkdata = + linkDatas.all .where( (e) => e.domainErrors.isNotEmpty || e.pathErrors.isNotEmpty, ) @@ -718,8 +718,9 @@ class DeepLinksController extends DisposableController } set searchContent(String content) { - displayOptionsNotifier.value = - displayOptionsNotifier.value.copyWith(searchContent: content); + displayOptionsNotifier.value = displayOptionsNotifier.value.copyWith( + searchContent: content, + ); applyFilters(); } @@ -740,12 +741,16 @@ class DeepLinksController extends DisposableController pathSortingOption: pathSortingOption, ); if (addedFilter != null) { - displayOptionsNotifier.value = - displayOptionsNotifier.value.updateFilter(addedFilter, true); + displayOptionsNotifier.value = displayOptionsNotifier.value.updateFilter( + addedFilter, + true, + ); } if (removedFilter != null) { - displayOptionsNotifier.value = - displayOptionsNotifier.value.updateFilter(removedFilter, false); + displayOptionsNotifier.value = displayOptionsNotifier.value.updateFilter( + removedFilter, + false, + ); } if (addedFilter != null || removedFilter != null) { @@ -764,34 +769,38 @@ class DeepLinksController extends DisposableController @visibleForTesting List getFilterredLinks(List linkDatas) { final searchContent = displayOptions.searchContent; - linkDatas = linkDatas.where((linkData) { - if (searchContent.isNotEmpty && - !linkData.matchesSearchToken( - RegExp(searchContent, caseSensitive: false), - )) { - return false; - } + linkDatas = + linkDatas.where((linkData) { + if (searchContent.isNotEmpty && + !linkData.matchesSearchToken( + RegExp(searchContent, caseSensitive: false), + )) { + return false; + } - if (!((linkData.os.contains(PlatformOS.android) && - displayOptions.filters.contains(FilterOption.android)) || - (linkData.os.contains(PlatformOS.ios) && - displayOptions.filters.contains(FilterOption.ios)))) { - return false; - } + if (!((linkData.os.contains(PlatformOS.android) && + displayOptions.filters.contains(FilterOption.android)) || + (linkData.os.contains(PlatformOS.ios) && + displayOptions.filters.contains(FilterOption.ios)))) { + return false; + } - if (!((linkData.domainErrors.isNotEmpty && - displayOptions.filters - .contains(FilterOption.failedDomainCheck)) || - (linkData.pathErrors.isNotEmpty && - displayOptions.filters.contains(FilterOption.failedPathCheck)) || - (linkData.domainErrors.isEmpty && - linkData.pathErrors.isEmpty && - displayOptions.filters.contains(FilterOption.noIssue)))) { - return false; - } + if (!((linkData.domainErrors.isNotEmpty && + displayOptions.filters.contains( + FilterOption.failedDomainCheck, + )) || + (linkData.pathErrors.isNotEmpty && + displayOptions.filters.contains( + FilterOption.failedPathCheck, + )) || + (linkData.domainErrors.isEmpty && + linkData.pathErrors.isEmpty && + displayOptions.filters.contains(FilterOption.noIssue)))) { + return false; + } - return true; - }).toList(); + return true; + }).toList(); return linkDatas; } 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 3edd79be588..1b8f0b8f581 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 @@ -170,14 +170,13 @@ class IosDomainError extends DomainError { static IosDomainError iosFileFormatDomainError({ required List subcheckErrors, - }) => - IosDomainError( - 'Apple-App-Site-Association file format is incorrect', - 'This test checks that your Apple-App-Site-Association file ' - 'follows the correct format guidelines.', - 'Ensure your Apple-App-Site-Association file follows the correct format guidelines.', - subcheckErrors: subcheckErrors, - ); + }) => IosDomainError( + 'Apple-App-Site-Association file format is incorrect', + 'This test checks that your Apple-App-Site-Association file ' + 'follows the correct format guidelines.', + 'Ensure your Apple-App-Site-Association file follows the correct format guidelines.', + subcheckErrors: subcheckErrors, + ); final List subcheckErrors; } @@ -191,7 +190,7 @@ String propertyTypeMessage({ class AASAfileFormatSubCheck extends CommonError { const AASAfileFormatSubCheck(String title, String explanation) - : super(title, explanation, ''); + : super(title, explanation, ''); static final appLinksFormat = AASAfileFormatSubCheck( 'Applinks format', @@ -386,10 +385,7 @@ class ValidatedLinkDatas { required this.byDomain, required this.byPath, }); - ValidatedLinkDatas.empty() - : all = [], - byDomain = [], - byPath = []; + ValidatedLinkDatas.empty() : all = [], byDomain = [], byPath = []; final List all; final List byDomain; final List byPath; @@ -542,12 +538,7 @@ class _ErrorAwareText extends StatelessWidget { ), ), const SizedBox(width: denseSpacing), - Flexible( - child: Text( - text, - overflow: TextOverflow.ellipsis, - ), - ), + Flexible(child: Text(text, overflow: TextOverflow.ellipsis)), ], ); } @@ -556,8 +547,8 @@ class _ErrorAwareText extends StatelessWidget { class DomainColumn extends ColumnData implements ColumnRenderer, ColumnHeaderRenderer { DomainColumn(this.controller) - : sortingOption = controller.displayOptions.domainSortingOption, - super.wide('Domain'); + : sortingOption = controller.displayOptions.domainSortingOption, + super.wide('Domain'); DeepLinksController controller; SortingOption? sortingOption; @@ -578,12 +569,10 @@ class DomainColumn extends ColumnData children: [ const Text('Domain'), PopupMenuButton( - itemBuilder: (BuildContext context) => - _buildPopupMenuSortingEntries(controller, isPath: false), - child: Icon( - Icons.arrow_drop_down, - size: actionsIconSize, - ), + itemBuilder: + (BuildContext context) => + _buildPopupMenuSortingEntries(controller, isPath: false), + child: Icon(Icons.arrow_drop_down, size: actionsIconSize), ), ], ); @@ -603,20 +592,16 @@ class DomainColumn extends ColumnData return dataObject.domain == null ? Text('missing domain', style: Theme.of(context).errorTextStyle) : _ErrorAwareText( - isError: dataObject.domainErrors.isNotEmpty, - controller: controller, - text: dataObject.domain!, - link: dataObject, - ); + isError: dataObject.domainErrors.isNotEmpty, + controller: controller, + text: dataObject.domain!, + link: dataObject, + ); } @override - int compare(LinkData a, LinkData b) => _compareLinkData( - a, - b, - sortingOption: sortingOption, - compareDomain: true, - ); + int compare(LinkData a, LinkData b) => + _compareLinkData(a, b, sortingOption: sortingOption, compareDomain: true); @override String get config => '$title $sortingOption'; @@ -625,8 +610,8 @@ class DomainColumn extends ColumnData class PathColumn extends ColumnData implements ColumnRenderer, ColumnHeaderRenderer { PathColumn(this.controller) - : sortingOption = controller.displayOptions.pathSortingOption, - super.wide('Path'); + : sortingOption = controller.displayOptions.pathSortingOption, + super.wide('Path'); DeepLinksController controller; SortingOption? sortingOption; @@ -647,12 +632,10 @@ class PathColumn extends ColumnData children: [ const Text('Path'), PopupMenuButton( - itemBuilder: (BuildContext context) => - _buildPopupMenuSortingEntries(controller, isPath: true), - child: Icon( - Icons.arrow_drop_down, - size: actionsIconSize, - ), + itemBuilder: + (BuildContext context) => + _buildPopupMenuSortingEntries(controller, isPath: true), + child: Icon(Icons.arrow_drop_down, size: actionsIconSize), ), ], ); @@ -680,11 +663,11 @@ class PathColumn extends ColumnData @override int compare(LinkData a, LinkData b) => _compareLinkData( - a, - b, - sortingOption: sortingOption, - compareDomain: false, - ); + a, + b, + sortingOption: sortingOption, + compareDomain: false, + ); @override String get config => '$title $sortingOption'; @@ -735,10 +718,7 @@ class SchemeColumn extends ColumnData _buildPopupMenuFilterEntry(controller, FilterOption.custom), ]; }, - child: Icon( - Icons.arrow_drop_down, - size: actionsIconSize, - ), + child: Icon(Icons.arrow_drop_down, size: actionsIconSize), ), ], ); @@ -790,10 +770,7 @@ class OSColumn extends ColumnData _buildPopupMenuFilterEntry(controller, FilterOption.ios), ]; }, - child: Icon( - Icons.arrow_drop_down, - size: actionsIconSize, - ), + child: Icon(Icons.arrow_drop_down, size: actionsIconSize), ), ], ); @@ -866,10 +843,7 @@ class StatusColumn extends ColumnData _buildPopupMenuFilterEntry(controller, FilterOption.noIssue), ]; }, - child: Icon( - Icons.arrow_drop_down, - size: actionsIconSize, - ), + child: Icon(Icons.arrow_drop_down, size: actionsIconSize), ), ], ); @@ -902,11 +876,7 @@ class StatusColumn extends ColumnData class NavigationColumn extends ColumnData implements ColumnRenderer { - NavigationColumn() - : super( - '', - fixedWidthPx: scaleByFontFactor(40), - ); + NavigationColumn() : super('', fixedWidthPx: scaleByFontFactor(40)); @override bool get supportsSorting => false; @@ -938,13 +908,15 @@ PopupMenuEntry _buildPopupMenuFilterEntry( children: [ ValueListenableBuilder( valueListenable: controller.displayOptionsNotifier, - builder: (context, option, _) => Checkbox( - value: option.filters.contains(filterOption), - onChanged: (bool? checked) => controller.updateDisplayOptions( - removedFilter: checked! ? null : filterOption, - addedFilter: checked ? filterOption : null, - ), - ), + builder: + (context, option, _) => Checkbox( + value: option.filters.contains(filterOption), + onChanged: + (bool? checked) => controller.updateDisplayOptions( + removedFilter: checked! ? null : filterOption, + addedFilter: checked ? filterOption : null, + ), + ), ), Text(filterOption.description), ], @@ -962,16 +934,8 @@ List> _buildPopupMenuSortingEntries( SortingOption.errorOnTop, isPath: isPath, ), - _buildPopupMenuSortingEntry( - controller, - SortingOption.aToZ, - isPath: isPath, - ), - _buildPopupMenuSortingEntry( - controller, - SortingOption.zToA, - isPath: isPath, - ), + _buildPopupMenuSortingEntry(controller, SortingOption.aToZ, isPath: isPath), + _buildPopupMenuSortingEntry(controller, SortingOption.zToA, isPath: isPath), ]; } 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 868a6fcbdd6..0f07bca4a3b 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 @@ -161,15 +161,17 @@ class DeepLinksService { final result = json.decode(response.body) as Map; - final validationResult = (result[_androidValidationResultKey] as List) - .cast>(); + final validationResult = + (result[_androidValidationResultKey] as List) + .cast>(); googlePlayFingerprintsAvailable = result[_googlePlayFingerprintsAvailabilityKey] == - _googlePlayFingerprintsAvailableValue; + _googlePlayFingerprintsAvailableValue; for (final domainResult in validationResult) { final domainName = domainResult[_domainNameKey] as String; - final failedChecks = (domainResult[_failedChecksKey] as List?) - ?.cast>(); + final failedChecks = + (domainResult[_failedChecksKey] as List?) + ?.cast>(); if (failedChecks != null) { for (final failedCheck in failedChecks) { final checkName = failedCheck[_checkNameKey] as String; @@ -205,23 +207,22 @@ class DeepLinksService { Uri.parse(iosDomainValidationURL), headers: postHeader, body: jsonEncode({ - _appIdKey: { - _bundleIdKey: bundleId, - _teamIdKey: teamId, - }, + _appIdKey: {_bundleIdKey: bundleId, _teamIdKey: teamId}, _universalLinkDomainsKey: [ for (final domain in domainList) {_iosDomainNameKey: domain}, ], }), ); final result = json.decode(response.body) as Map; - final validationResult = (result[_iosValidationResultsKey] as List) - .cast>(); + final validationResult = + (result[_iosValidationResultsKey] as List) + .cast>(); for (final domainResult in validationResult) { if (domainResult[_domainNameKey] case final String domainName) { - final failedChecks = (domainResult[_failedChecksKey] as List?) - ?.cast>(); + final failedChecks = + (domainResult[_failedChecksKey] as List?) + ?.cast>(); if (failedChecks != null) { for (final failedCheck in failedChecks) { final checkName = failedCheck[_checkNameKey] as String; @@ -233,15 +234,17 @@ class DeepLinksService { []; // Adds sub checks for file format error. - final subChecks = (failedCheck[_subCheckResultsKey] as List?) - ?.cast>(); + final subChecks = + (failedCheck[_subCheckResultsKey] as List?) + ?.cast>(); for (final subCheck in (subChecks ?? [])) { final subCheckName = subCheck[_checkNameKey] as String; final subCheckResultType = subCheck[_resultTypeKey] as String; if (subCheckResultType != _passedKey) { - failedAasaFileFormatSubCheck - .add(aasaFileFormatSubCheck[subCheckName]!); + failedAasaFileFormatSubCheck.add( + aasaFileFormatSubCheck[subCheckName]!, + ); } } @@ -261,25 +264,30 @@ class DeepLinksService { } } - final aasaAppPaths = (domainResult[_aasaAppPathsKey] as List?) - ?.cast>(); + final aasaAppPaths = + (domainResult[_aasaAppPathsKey] as List?) + ?.cast>(); if (aasaAppPaths != null) { for (final aasaAppPath in aasaAppPaths) { - final aasaPaths = (aasaAppPath[_aasaPathsKey] as List?) - ?.cast>(); + final aasaPaths = + (aasaAppPath[_aasaPathsKey] as List?) + ?.cast>(); if (aasaPaths != null) { for (final aasaPath in aasaPaths) { final path = aasaPath[_pathKey] as String?; if (path.isNullOrEmpty) { continue; } - final rawQueryParams = (aasaPath[_queryParamsKey] as List?) - ?.cast>(); + final rawQueryParams = + (aasaPath[_queryParamsKey] as List?) + ?.cast>(); final queryParams = { for (final item in rawQueryParams ?? []) item[_keyKey] as String: item[_valueKey] as String, }; - paths.putIfAbsent(domainName, () => []).add( + paths + .putIfAbsent(domainName, () => []) + .add( Path( path: path!, queryParams: queryParams, @@ -295,11 +303,7 @@ class DeepLinksService { } } } - return ValidateIosDomainResult( - errorCode, - domainErrors, - paths, - ); + return ValidateIosDomainResult(errorCode, domainErrors, paths); } // The request can take 1000 domains at most, split domains to make a few calls in serial with a batch of _domainBatchSize. @@ -323,13 +327,11 @@ class DeepLinksService { final response = await client.post( Uri.parse(assetLinksGenerationURL), headers: postHeader, - body: jsonEncode( - { - _packageNameKey: applicationId, - _domainsKey: [domain], - if (localFingerprint != null) _fingerprintsKey: [localFingerprint], - }, - ), + body: jsonEncode({ + _packageNameKey: applicationId, + _domainsKey: [domain], + if (localFingerprint != null) _fingerprintsKey: [localFingerprint], + }), ); final result = json.decode(response.body) as Map; final errorCode = (result[_errorCodeKey] as String?) ?? ''; diff --git a/packages/devtools_app/lib/src/screens/deep_link_validation/project_root_selection/root_selector.dart b/packages/devtools_app/lib/src/screens/deep_link_validation/project_root_selection/root_selector.dart index 510c966eea3..6bba82ee772 100644 --- a/packages/devtools_app/lib/src/screens/deep_link_validation/project_root_selection/root_selector.dart +++ b/packages/devtools_app/lib/src/screens/deep_link_validation/project_root_selection/root_selector.dart @@ -102,12 +102,11 @@ class _ProjectRootsDropdownState extends State { isDense: true, isExpanded: true, value: selectedUri, - items: [ - for (final uri in widget.projectRoots) _buildMenuItem(uri), - ], - onChanged: (uri) => setState(() { - selectedUri = uri; - }), + items: [for (final uri in widget.projectRoots) _buildMenuItem(uri)], + onChanged: + (uri) => setState(() { + selectedUri = uri; + }), ), ); } @@ -118,10 +117,7 @@ class _ProjectRootsDropdownState extends State { child: DevToolsTooltip( message: uri.path, waitDuration: tooltipWaitExtraLong, - child: Text( - uri.path, - overflow: TextOverflow.ellipsis, - ), + child: Text(uri.path, overflow: TextOverflow.ellipsis), ), ); } @@ -152,15 +148,8 @@ class _FlexibleProjectSelectionView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ const Spacer(), - Flexible( - flex: 8, - fit: FlexFit.tight, - child: child, - ), - if (showButtonInRow) ...[ - const SizedBox(width: defaultSpacing), - button, - ], + Flexible(flex: 8, fit: FlexFit.tight, child: child), + if (showButtonInRow) ...[const SizedBox(width: defaultSpacing), button], const Spacer(), ], ); @@ -170,11 +159,7 @@ class _FlexibleProjectSelectionView extends StatelessWidget { if (!showButtonInRow) { content = Column( mainAxisSize: MainAxisSize.min, - children: [ - content, - const SizedBox(height: defaultSpacing), - button, - ], + children: [content, const SizedBox(height: defaultSpacing), button], ); } diff --git a/packages/devtools_app/lib/src/screens/deep_link_validation/project_root_selection/select_project_view.dart b/packages/devtools_app/lib/src/screens/deep_link_validation/project_root_selection/select_project_view.dart index 9755a3ba6bb..3f2022350ce 100644 --- a/packages/devtools_app/lib/src/screens/deep_link_validation/project_root_selection/select_project_view.dart +++ b/packages/devtools_app/lib/src/screens/deep_link_validation/project_root_selection/select_project_view.dart @@ -99,9 +99,7 @@ class _SelectProjectViewState extends State content: Text( 'It looks like you have selected a non-Flutter project. Please select a Flutter project instead.', ), - actions: [ - DialogCloseButton(), - ], + actions: [DialogCloseButton()], ); }, ); @@ -202,10 +200,7 @@ class _LoadingProjectView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - 'Project loading...', - style: theme.regularTextStyle, - ), + Text('Project loading...', style: theme.regularTextStyle), Container( width: _kLinearProgressIndicatorWidth, padding: const EdgeInsets.symmetric(vertical: densePadding), diff --git a/packages/devtools_app/lib/src/screens/deep_link_validation/validation_details_view.dart b/packages/devtools_app/lib/src/screens/deep_link_validation/validation_details_view.dart index a26ab6dfc8a..b14de16fbea 100644 --- a/packages/devtools_app/lib/src/screens/deep_link_validation/validation_details_view.dart +++ b/packages/devtools_app/lib/src/screens/deep_link_validation/validation_details_view.dart @@ -115,8 +115,8 @@ class ValidationDetailHeader extends StatelessWidget { style: Theme.of(context).textTheme.titleMedium, ), IconButton( - onPressed: () => - controller.updateDisplayOptions(showSplitScreen: false), + onPressed: + () => controller.updateDisplayOptions(showSplitScreen: false), icon: const Icon(Icons.close), ), ], @@ -127,9 +127,7 @@ class ValidationDetailHeader extends StatelessWidget { } class _DomainCheckTable extends StatelessWidget { - const _DomainCheckTable({ - required this.controller, - }); + const _DomainCheckTable({required this.controller}); final DeepLinksController controller; @@ -142,7 +140,7 @@ class _DomainCheckTable extends StatelessWidget { builder: (context, localFingerprint, _) { final fingerprintExists = controller.googlePlayFingerprintsAvailability.value || - localFingerprint != null; + localFingerprint != null; return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ @@ -156,7 +154,8 @@ class _DomainCheckTable extends StatelessWidget { initiallyExpanded: !fingerprintExists, checkName: 'Digital assets link file', status: _CheckStatusText( - hasError: !fingerprintExists || + hasError: + !fingerprintExists || linkData.domainErrors.any((e) => e is AndroidDomainError), ), children: [ @@ -174,24 +173,26 @@ class _DomainCheckTable extends StatelessWidget { os: PlatformOS.ios, checkName: 'Apple-App-Site-Association file', status: _CheckStatusText( - hasError: - linkData.domainErrors.any((e) => e is IosDomainError), + hasError: linkData.domainErrors.any( + (e) => e is IosDomainError, + ), ), children: [ for (final error in linkData.domainErrors.whereType()) _IssuesBorderWrap( - children: error == IosDomainError.existence - ? [ - _FailureDetails( - errors: [error], - oneFixGuideForAll: - 'To fix this issue, add an Apple-App-Site-Association file at the following location: ' - 'https://${controller.selectedLink.value!.domain}/.well-known/apple-app-site-association', - ), - const SizedBox(height: denseSpacing), - _CodeCard( - content: '''{ + children: + error == IosDomainError.existence + ? [ + _FailureDetails( + errors: [error], + oneFixGuideForAll: + 'To fix this issue, add an Apple-App-Site-Association file at the following location: ' + 'https://${controller.selectedLink.value!.domain}/.well-known/apple-app-site-association', + ), + const SizedBox(height: denseSpacing), + _CodeCard( + content: '''{ "applinks": { "details": [ { @@ -207,13 +208,13 @@ class _DomainCheckTable extends StatelessWidget { ] } }''', - ), - ] - : [ - _FailureDetails( - errors: [error, ...error.subcheckErrors], - ), - ], + ), + ] + : [ + _FailureDetails( + errors: [error, ...error.subcheckErrors], + ), + ], ), ], ), @@ -228,19 +229,16 @@ class _DomainCheckTable extends StatelessWidget { /// There is a general fix for the asset links json file issues: /// Update it with the generated asset link file. class _AssetLinksJsonFileIssues extends StatelessWidget { - const _AssetLinksJsonFileIssues({ - required this.controller, - }); + const _AssetLinksJsonFileIssues({required this.controller}); final DeepLinksController controller; @override Widget build(BuildContext context) { - final errors = controller.selectedLink.value!.domainErrors - .where( - (error) => domainAssetLinksJsonFileErrors.contains(error), - ) - .toList(); + final errors = + controller.selectedLink.value!.domainErrors + .where((error) => domainAssetLinksJsonFileErrors.contains(error)) + .toList(); return ExpansionTile( controlAffinity: ListTileControlAffinity.leading, title: _VerifiedOrErrorText( @@ -276,9 +274,10 @@ class _HostingIssues extends StatelessWidget { @override Widget build(BuildContext context) { - final errors = controller.selectedLink.value!.domainErrors - .where((error) => domainAndroidHostingErrors.contains(error)) - .toList(); + final errors = + controller.selectedLink.value!.domainErrors + .where((error) => domainAndroidHostingErrors.contains(error)) + .toList(); return ExpansionTile( controlAffinity: ListTileControlAffinity.leading, title: _VerifiedOrErrorText( @@ -298,9 +297,7 @@ class _HostingIssues extends StatelessWidget { } class _Fingerprint extends StatelessWidget { - const _Fingerprint({ - required this.controller, - }); + const _Fingerprint({required this.controller}); final DeepLinksController controller; @@ -328,10 +325,7 @@ class _Fingerprint extends StatelessWidget { return ExpansionTile( controlAffinity: ListTileControlAffinity.leading, initiallyExpanded: isError, - title: _VerifiedOrErrorText( - title, - isError: isError, - ), + title: _VerifiedOrErrorText(title, isError: isError), children: [ _IssuesBorderWrap( children: [ @@ -343,9 +337,7 @@ class _Fingerprint extends StatelessWidget { const SizedBox(height: denseSpacing), ], if (isError) ...[ - const Text( - 'Issue: no fingerprint detected locally or on PDC', - ), + const Text('Issue: no fingerprint detected locally or on PDC'), const SizedBox(height: denseSpacing), const Text('Fix guide:'), const SizedBox(height: denseSpacing), @@ -367,9 +359,7 @@ class _Fingerprint extends StatelessWidget { } class _LocalFingerprint extends StatelessWidget { - const _LocalFingerprint({ - required this.controller, - }); + const _LocalFingerprint({required this.controller}); final DeepLinksController controller; @@ -382,39 +372,38 @@ class _LocalFingerprint extends StatelessWidget { const SizedBox(height: intermediateSpacing), controller.localFingerprint.value == null ? TextField( - decoration: const InputDecoration( - labelText: 'Enter your local fingerprint', - hintText: - 'eg: A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4', - filled: true, - ), - onSubmitted: (fingerprint) async { - final validFingerprintAdded = - controller.addLocalFingerprint(fingerprint); - - if (!validFingerprintAdded) { - await showDialog( - context: context, - builder: (_) { - return const DevToolsDialog( - title: Text('This is not a valid fingerprint'), - content: Text( - 'A valid fingerprint consists of 32 pairs of hexadecimal digits separated by colons.' - 'It should be the same encoding and format as in the assetlinks.json', - ), - actions: [ - DialogCloseButton(), - ], - ); - }, - ); - } - }, - ) - : _CodeCard( - content: controller.localFingerprint.value, - hasCopyAction: false, + decoration: const InputDecoration( + labelText: 'Enter your local fingerprint', + hintText: + 'eg: A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4', + filled: true, ), + onSubmitted: (fingerprint) async { + final validFingerprintAdded = controller.addLocalFingerprint( + fingerprint, + ); + + if (!validFingerprintAdded) { + await showDialog( + context: context, + builder: (_) { + return const DevToolsDialog( + title: Text('This is not a valid fingerprint'), + content: Text( + 'A valid fingerprint consists of 32 pairs of hexadecimal digits separated by colons.' + 'It should be the same encoding and format as in the assetlinks.json', + ), + actions: [DialogCloseButton()], + ); + }, + ); + } + }, + ) + : _CodeCard( + content: controller.localFingerprint.value, + hasCopyAction: false, + ), ], ); } @@ -442,10 +431,7 @@ class _ViewDeveloperGuide extends StatelessWidget { } class _CodeCard extends StatelessWidget { - const _CodeCard({ - this.content, - this.hasCopyAction = true, - }); + const _CodeCard({this.content, this.hasCopyAction = true}); final String? content; final bool hasCopyAction; @@ -457,26 +443,25 @@ class _CodeCard extends StatelessWidget { elevation: 0.0, child: Padding( padding: const EdgeInsets.all(denseSpacing), - child: content != null - ? Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Flexible(child: SelectionArea(child: Text(content!))), - if (hasCopyAction) - CopyToClipboardControl(dataProvider: () => content), - ], - ) - : const CenteredCircularProgressIndicator(), + child: + content != null + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible(child: SelectionArea(child: Text(content!))), + if (hasCopyAction) + CopyToClipboardControl(dataProvider: () => content), + ], + ) + : const CenteredCircularProgressIndicator(), ), ); } } class _GenerateAssetLinksPanel extends StatelessWidget { - const _GenerateAssetLinksPanel({ - required this.controller, - }); + const _GenerateAssetLinksPanel({required this.controller}); final DeepLinksController controller; @@ -485,17 +470,13 @@ class _GenerateAssetLinksPanel extends StatelessWidget { final theme = Theme.of(context); return ValueListenableBuilder( valueListenable: controller.generatedAssetLinksForSelectedLink, - builder: ( - _, - GenerateAssetLinksResult? generatedAssetLinks, - _, - ) { + builder: (_, GenerateAssetLinksResult? generatedAssetLinks, _) { return (generatedAssetLinks != null && generatedAssetLinks.errorCode.isNotEmpty) ? Text( - 'Not able to generate assetlinks.json, because the app ${controller.applicationId} is not uploaded to Google Play.', - style: theme.subtleTextStyle, - ) + 'Not able to generate assetlinks.json, because the app ${controller.applicationId} is not uploaded to Google Play.', + style: theme.subtleTextStyle, + ) : _CodeCard(content: generatedAssetLinks?.generatedString); }, ); @@ -503,10 +484,7 @@ class _GenerateAssetLinksPanel extends StatelessWidget { } class _FailureDetails extends StatelessWidget { - const _FailureDetails({ - required this.errors, - this.oneFixGuideForAll, - }); + const _FailureDetails({required this.errors, this.oneFixGuideForAll}); final List errors; final String? oneFixGuideForAll; @@ -520,28 +498,19 @@ class _FailureDetails extends StatelessWidget { const SizedBox(height: densePadding), Text('Issue: ${error.title}'), const SizedBox(height: densePadding), - Text( - error.explanation, - style: Theme.of(context).subtleTextStyle, - ), + Text(error.explanation, style: Theme.of(context).subtleTextStyle), if (oneFixGuideForAll == null) ...[ const SizedBox(height: defaultSpacing), const Text('Fix guide:'), const SizedBox(height: densePadding), - Text( - error.fixDetails, - style: Theme.of(context).subtleTextStyle, - ), + Text(error.fixDetails, style: Theme.of(context).subtleTextStyle), ], ], if (oneFixGuideForAll != null) ...[ const SizedBox(height: defaultSpacing), const Text('Fix guide:'), const SizedBox(height: densePadding), - Text( - oneFixGuideForAll!, - style: Theme.of(context).subtleTextStyle, - ), + Text(oneFixGuideForAll!, style: Theme.of(context).subtleTextStyle), ], ], ); @@ -549,9 +518,7 @@ class _FailureDetails extends StatelessWidget { } class _DomainAssociatedLinksPanel extends StatelessWidget { - const _DomainAssociatedLinksPanel({ - required this.controller, - }); + const _DomainAssociatedLinksPanel({required this.controller}); final DeepLinksController controller; @@ -562,10 +529,7 @@ class _DomainAssociatedLinksPanel extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - 'Associated deep link URL', - style: theme.textTheme.titleMedium, - ), + Text('Associated deep link URL', style: theme.textTheme.titleMedium), Card( color: theme.colorScheme.surface, shape: const RoundedRectangleBorder(), @@ -573,27 +537,28 @@ class _DomainAssociatedLinksPanel extends StatelessWidget { padding: const EdgeInsets.all(denseSpacing), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: linkData.associatedPath - .map( - (path) => Padding( - padding: const EdgeInsets.symmetric( - vertical: denseRowSpacing, - ), - child: Row( - children: [ - if (linkData.domainErrors.isNotEmpty) - Icon( - Icons.error, - color: theme.colorScheme.error, - size: defaultIconSize, - ), - const SizedBox(width: denseSpacing), - Text('${linkData.domain}$path'), - ], - ), - ), - ) - .toList(), + children: + linkData.associatedPath + .map( + (path) => Padding( + padding: const EdgeInsets.symmetric( + vertical: denseRowSpacing, + ), + child: Row( + children: [ + if (linkData.domainErrors.isNotEmpty) + Icon( + Icons.error, + color: theme.colorScheme.error, + size: defaultIconSize, + ), + const SizedBox(width: denseSpacing), + Text('${linkData.domain}$path'), + ], + ), + ), + ) + .toList(), ), ), ), @@ -630,10 +595,7 @@ class _CrossCheckTable extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: intermediateSpacing), - Text( - 'App check', - style: theme.textTheme.titleMedium, - ), + Text('App check', style: theme.textTheme.titleMedium), const SizedBox(height: intermediateSpacing), const _CheckTableHeader(), const Divider(height: 1.0), @@ -691,10 +653,7 @@ class _PathCheckTable extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: intermediateSpacing), - Text( - 'App check', - style: theme.textTheme.titleMedium, - ), + Text('App check', style: theme.textTheme.titleMedium), const SizedBox(height: intermediateSpacing), const _CheckTableHeader(), const Divider(height: 1.0), @@ -714,9 +673,10 @@ class _ManifestFileCheck extends StatelessWidget { @override Widget build(BuildContext context) { final linkData = controller.selectedLink.value!; - final errors = manifestFileErrors - .where((error) => linkData.pathErrors.contains(error)) - .toList(); + final errors = + manifestFileErrors + .where((error) => linkData.pathErrors.contains(error)) + .toList(); return _CheckExpansionTile( os: PlatformOS.android, @@ -877,14 +837,11 @@ class _CheckStatusText extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); return hasError - ? Text( - 'Check failed', - style: theme.errorTextStyle, - ) + ? Text('Check failed', style: theme.errorTextStyle) : Text( - 'No issues found', - style: TextStyle(color: theme.colorScheme.green), - ); + 'No issues found', + style: TextStyle(color: theme.colorScheme.green), + ); } } @@ -899,15 +856,15 @@ class _VerifiedOrErrorText extends StatelessWidget { children: [ isError ? Icon( - Icons.error, - color: Theme.of(context).colorScheme.error, - size: defaultIconSize, - ) + Icons.error, + color: Theme.of(context).colorScheme.error, + size: defaultIconSize, + ) : Icon( - Icons.verified, - color: Theme.of(context).colorScheme.green, - size: defaultIconSize, - ), + Icons.verified, + color: Theme.of(context).colorScheme.green, + size: defaultIconSize, + ), const SizedBox(width: denseSpacing), Text(text), ], diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_breadcrumbs.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_breadcrumbs.dart index ff5b907f93c..f1c27844ec6 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_breadcrumbs.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_breadcrumbs.dart @@ -37,21 +37,19 @@ class InspectorBreadcrumbNavigator extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 6), child: Row( - children: breadcrumbs.map((item) { - if (item.isChevron) { - return Icon( - Icons.chevron_right, - size: defaultIconSize, - ); - } - - return Flexible( - child: _InspectorBreadcrumb( - data: item, - onTap: () => onTap(item.node), - ), - ); - }).toList(), + children: + breadcrumbs.map((item) { + if (item.isChevron) { + return Icon(Icons.chevron_right, size: defaultIconSize); + } + + return Flexible( + child: _InspectorBreadcrumb( + data: item, + onTap: () => onTap(item.node), + ), + ); + }).toList(), ), ), ); @@ -61,33 +59,32 @@ class InspectorBreadcrumbNavigator extends StatelessWidget { List nodes, ) { final lastNode = nodes.safeLast; - final items = nodes.map((node) { - return _InspectorBreadcrumbData.wrap( - node: node, - isSelected: node == lastNode, - ); - }).toList(); + final items = + nodes.map((node) { + return _InspectorBreadcrumbData.wrap( + node: node, + isSelected: node == lastNode, + ); + }).toList(); List<_InspectorBreadcrumbData> breadcrumbs; - breadcrumbs = items.length > _maxNumberOfBreadcrumbs - ? [ - items[0], - _InspectorBreadcrumbData.more(), - ...items.sublist( - items.length - _maxNumberOfBreadcrumbs + 1, - items.length, - ), - ] - : items; + breadcrumbs = + items.length > _maxNumberOfBreadcrumbs + ? [ + items[0], + _InspectorBreadcrumbData.more(), + ...items.sublist( + items.length - _maxNumberOfBreadcrumbs + 1, + items.length, + ), + ] + : items; return breadcrumbs.joinWith(_InspectorBreadcrumbData.chevron()); } } class _InspectorBreadcrumb extends StatelessWidget { - const _InspectorBreadcrumb({ - required this.data, - required this.onTap, - }); + const _InspectorBreadcrumb({required this.data, required this.onTap}); static const _iconScale = 0.75; @@ -100,19 +97,21 @@ class _InspectorBreadcrumb extends StatelessWidget { data.text, maxLines: 1, overflow: TextOverflow.ellipsis, - style: DiagnosticsTextStyles.regular(Theme.of(context).colorScheme) - .copyWith(fontSize: scaleByFontFactor(11)), + style: DiagnosticsTextStyles.regular( + Theme.of(context).colorScheme, + ).copyWith(fontSize: scaleByFontFactor(11)), ); - final icon = data.icon == null - ? null - : Transform.scale( - scale: _iconScale, - child: Padding( - padding: const EdgeInsets.only(right: iconPadding), - child: data.icon, - ), - ); + final icon = + data.icon == null + ? null + : Transform.scale( + scale: _iconScale, + child: Padding( + padding: const EdgeInsets.only(right: iconPadding), + child: data.icon, + ), + ); return InkWell( onTap: data.isClickable ? onTap : null, @@ -124,16 +123,14 @@ class _InspectorBreadcrumb extends StatelessWidget { ), decoration: BoxDecoration( borderRadius: defaultBorderRadius, - color: data.isSelected - ? Theme.of(context).colorScheme.selectedRowBackgroundColor - : Colors.transparent, + color: + data.isSelected + ? Theme.of(context).colorScheme.selectedRowBackgroundColor + : Colors.transparent, ), child: Row( mainAxisSize: MainAxisSize.min, - children: [ - if (icon != null) icon, - Flexible(child: text), - ], + children: [if (icon != null) icon, Flexible(child: text)], ), ), ); @@ -191,10 +188,7 @@ class _InspectorBreadcrumbData { Widget? get icon { if (alternativeIcon != null) { - return Icon( - _breadcrumbSeparatorIcon, - size: defaultIconSize, - ); + return Icon(_breadcrumbSeparatorIcon, size: defaultIconSize); } return node?.diagnostic?.icon; diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart index 33d7161be83..3c224f8a351 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart @@ -51,9 +51,7 @@ class InspectorController extends DisposableController unawaited(_init(detailsTree: detailsTree)); } - Future _init({ - InspectorTreeController? detailsTree, - }) async { + Future _init({InspectorTreeController? detailsTree}) async { _refreshRateLimiter = RateLimiter(refreshFramesPerSecond, refresh); inspectorTree.config = InspectorTreeConfig( @@ -62,14 +60,15 @@ class InspectorController extends DisposableController onExpand: _onExpand, onClientActiveChange: _onClientChange, ); - details = isSummaryTree - ? InspectorController( - inspectorTree: detailsTree!, - treeType: treeType, - parent: this, - isSummaryTree: false, - ) - : null; + details = + isSummaryTree + ? InspectorController( + inspectorTree: detailsTree!, + treeType: treeType, + parent: this, + isSummaryTree: false, + ) + : null; await serviceConnection.serviceManager.onServiceAvailable; @@ -105,10 +104,10 @@ class InspectorController extends DisposableController if (_supportsToggleSelectWidgetMode.value) { serviceConnection.serviceManager.serviceExtensionManager .setServiceExtensionState( - extensions.enableOnDeviceInspector.extension, - enabled: true, - value: true, - ); + extensions.enableOnDeviceInspector.extension, + enabled: true, + value: true, + ); } }); } @@ -150,9 +149,10 @@ class InspectorController extends DisposableController IsolateRef? _mainIsolate; - ValueListenable get _supportsToggleSelectWidgetMode => - serviceConnection.serviceManager.serviceExtensionManager - .hasServiceExtension(extensions.toggleSelectWidgetMode.extension); + ValueListenable get _supportsToggleSelectWidgetMode => serviceConnection + .serviceManager + .serviceExtensionManager + .hasServiceExtension(extensions.toggleSelectWidgetMode.extension); void _onClientChange(bool added) { if (!added && _clientCount == 0) { @@ -447,9 +447,10 @@ class InspectorController extends DisposableController treeGroups.cancelNext(); try { final group = treeGroups.next; - final node = await (detailsSubtree - ? group.getDetailsSubtree(subtreeRoot, subtreeDepth: subtreeDepth) - : group.getRoot(treeType, isSummaryTree: true)); + final node = + await (detailsSubtree + ? group.getDetailsSubtree(subtreeRoot, subtreeDepth: subtreeDepth) + : group.getRoot(treeType, isSummaryTree: true)); if (node == null || group.disposed || _disposed) { return; } @@ -725,15 +726,17 @@ class InspectorController extends DisposableController void _updateSelectedErrorFromNode(InspectorTreeNode? node) { final inspectorRef = node?.diagnostic?.valueRef.id; - final errors = serviceConnection.errorBadgeManager - .erroredItemsForPage(InspectorScreen.id) - .value; + final errors = + serviceConnection.errorBadgeManager + .erroredItemsForPage(InspectorScreen.id) + .value; // Check whether the node that was just selected has any errors associated // with it. - var errorIndex = inspectorRef != null - ? errors.keys.toList().indexOf(inspectorRef) - : null; + var errorIndex = + inspectorRef != null + ? errors.keys.toList().indexOf(inspectorRef) + : null; if (errorIndex == -1) { errorIndex = null; } @@ -743,8 +746,10 @@ class InspectorController extends DisposableController if (errorIndex != null) { // Mark the error as "seen" as this will render slightly differently // so the user can track which errored nodes they've viewed. - serviceConnection.errorBadgeManager - .markErrorAsRead(InspectorScreen.id, errors[inspectorRef!]!); + serviceConnection.errorBadgeManager.markErrorAsRead( + InspectorScreen.id, + errors[inspectorRef!]!, + ); // Also clear the error badge since new errors may have arrived while // the inspector was visible (normally they're cleared when visiting // the screen) and visiting an errored node seems an appropriate @@ -757,9 +762,10 @@ class InspectorController extends DisposableController void selectErrorByIndex(int index) { _selectedErrorIndex.value = index; - final errors = serviceConnection.errorBadgeManager - .erroredItemsForPage(InspectorScreen.id) - .value; + final errors = + serviceConnection.errorBadgeManager + .erroredItemsForPage(InspectorScreen.id) + .value; unawaited( updateSelectionFromService( @@ -807,7 +813,8 @@ class InspectorController extends DisposableController unawaited(_addNodeToConsole(node)); // Don't reroot if the selected value is already visible in the details tree. - final maybeReroot = isSummaryTree && + final maybeReroot = + isSummaryTree && details != null && selectedDiagnostic != null && !details!.hasDiagnosticsValue(selectedDiagnostic!.valueRef); @@ -824,8 +831,9 @@ class InspectorController extends DisposableController if (isSummaryTree && detailsLocal != null) { detailsLocal.selectAndShowNode(selectedDiagnostic); } else if (parantLocal != null) { - parantLocal - .selectAndShowNode(firstAncestorInParentTree(selectedNode.value)); + parantLocal.selectAndShowNode( + firstAncestorInParentTree(selectedNode.value), + ); } } } diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_data_models.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_data_models.dart index 9cc4d96c856..e7310fc55fe 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_data_models.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_data_models.dart @@ -72,17 +72,18 @@ List computeRenderSizes({ } List transformToRenderSize(double largestRenderSize) => [ - for (final s in sizes) - (s - smallestSize) * - (largestRenderSize - smallestRenderSize) / - (largestSize - smallestSize) + - smallestRenderSize, - ]; + for (final s in sizes) + (s - smallestSize) * + (largestRenderSize - smallestRenderSize) / + (largestSize - smallestSize) + + smallestRenderSize, + ]; var renderSizes = transformToRenderSize(largestRenderSize); if (useMaxSizeAvailable && sum(renderSizes) < maxSizeAvailable) { - largestRenderSize = (maxSizeAvailable - n * smallestRenderSize) * + largestRenderSize = + (maxSizeAvailable - n * smallestRenderSize) * (largestSize - smallestSize) / sum([for (final s in sizes) s - smallestSize]) + smallestRenderSize; @@ -95,19 +96,21 @@ List computeRenderSizes({ /// Represents parsed layout information for a specific [RemoteDiagnosticsNode]. class LayoutProperties { LayoutProperties(this.node, {int copyLevel = 1}) - : description = node.description, - size = node.size!, - constraints = node.constraints, - isFlex = node.isFlex, - flexFactor = node.flexFactor, - flexFit = node.flexFit, - children = copyLevel == 0 - ? [] - : node.childrenNow - .map( - (child) => LayoutProperties(child, copyLevel: copyLevel - 1), - ) - .toList(growable: false) { + : description = node.description, + size = node.size!, + constraints = node.constraints, + isFlex = node.isFlex, + flexFactor = node.flexFactor, + flexFit = node.flexFit, + children = + copyLevel == 0 + ? [] + : node.childrenNow + .map( + (child) => + LayoutProperties(child, copyLevel: copyLevel - 1), + ) + .toList(growable: false) { for (final child in children) { child.parent = this; } @@ -170,10 +173,10 @@ class LayoutProperties { if (constraintsLocal == null) return ''; return constraintsLocal.hasBoundedWidth ? describeAxis( - constraintsLocal.minWidth, - constraintsLocal.maxWidth, - 'w', - ) + constraintsLocal.minWidth, + constraintsLocal.maxWidth, + 'w', + ) : 'width is unconstrained'; } @@ -182,10 +185,10 @@ class LayoutProperties { if (constraintsLocal == null) return ''; return constraintsLocal.hasBoundedHeight ? describeAxis( - constraintsLocal.minHeight, - constraintsLocal.maxHeight, - 'h', - ) + constraintsLocal.minHeight, + constraintsLocal.maxHeight, + 'h', + ) : 'height is unconstrained'; } @@ -248,10 +251,7 @@ class LayoutProperties { /// /// See also: /// * [OverflowIndicatorPainter] -enum OverflowSide { - right, - bottom, -} +enum OverflowSide { right, bottom } // TODO(jacobr): is it possible to overflow on multiple sides? // TODO(jacobr): do we need to worry about overflowing on the left side in RTL @@ -356,8 +356,9 @@ class FlexLayoutProperties extends LayoutProperties { static FlexLayoutProperties _buildNode(RemoteDiagnosticsNode node) { final renderObjectJson = node.renderObject!.json; - final properties = (renderObjectJson['properties'] as List) - .cast>(); + final properties = + (renderObjectJson['properties'] as List) + .cast>(); final data = { for (final property in properties) @@ -367,16 +368,19 @@ class FlexLayoutProperties extends LayoutProperties { return FlexLayoutProperties._fromNode( node, direction: _directionUtils.enumEntry(data['direction']) ?? Axis.vertical, - mainAxisAlignment: - _mainAxisAlignmentUtils.enumEntry(data['mainAxisAlignment']), + mainAxisAlignment: _mainAxisAlignmentUtils.enumEntry( + data['mainAxisAlignment'], + ), mainAxisSize: _mainAxisSizeUtils.enumEntry(data['mainAxisSize']), - crossAxisAlignment: - _crossAxisAlignmentUtils.enumEntry(data['crossAxisAlignment']), - textDirection: _textDirectionUtils.enumEntry(data['textDirection']) ?? + crossAxisAlignment: _crossAxisAlignmentUtils.enumEntry( + data['crossAxisAlignment'], + ), + textDirection: + _textDirectionUtils.enumEntry(data['textDirection']) ?? TextDirection.ltr, verticalDirection: _verticalDirectionUtils.enumEntry(data['verticalDirection']) ?? - VerticalDirection.down, + VerticalDirection.down, textBaseline: _textBaselineUtils.enumEntry(data['textBaseline']), ); } @@ -417,10 +421,11 @@ class FlexLayoutProperties extends LayoutProperties { num get totalFlex { if (children.isEmpty) return 0; - _totalFlex ??= children - .map((child) => child.flexFactor ?? 0) - .reduce((value, element) => value + element) - .toInt(); + _totalFlex ??= + children + .map((child) => child.flexFactor ?? 0) + .reduce((value, element) => value + element) + .toInt(); return _totalFlex!; } @@ -554,11 +559,12 @@ class FlexLayoutProperties extends LayoutProperties { ); } else { // uniform cross axis sizes. - double size = crossAxisAlignment == CrossAxisAlignment.stretch - ? maxSizeAvailable(axis) - : largestSize / - math.max(dimension(axis), 1.0) * - maxSizeAvailable(axis); + double size = + crossAxisAlignment == CrossAxisAlignment.stretch + ? maxSizeAvailable(axis) + : largestSize / + math.max(dimension(axis), 1.0) * + maxSizeAvailable(axis); size = math.max(size, smallestRenderSize(axis)); return sizes.map((_) => size).toList(); } @@ -567,9 +573,10 @@ class FlexLayoutProperties extends LayoutProperties { final widths = renderSizes(Axis.horizontal); final heights = renderSizes(Axis.vertical); - final renderFreeSpace = freeSpace > 0.0 - ? (isMainAxisHorizontal ? widths.last : heights.last) - : 0.0; + final renderFreeSpace = + freeSpace > 0.0 + ? (isMainAxisHorizontal ? widths.last : heights.last) + : 0.0; final renderLeadingSpace = leadingSpace(renderFreeSpace); final renderBetweenSpace = betweenSpace(renderFreeSpace); @@ -616,11 +623,11 @@ class FlexLayoutProperties extends LayoutProperties { for (var i = 0; i < children.length; ++i) { childrenRenderProps.add( RenderProperties( - axis: direction, - size: Size(widths[i], heights[i]), - offset: Offset.zero, - realSize: displayChildren[i].size, - ) + axis: direction, + size: Size(widths[i], heights[i]), + offset: Offset.zero, + realSize: displayChildren[i].size, + ) ..mainAxisOffset = calculateMainAxisOffset(i) ..crossAxisOffset = calculateCrossAxisOffset(i) ..layoutProperties = displayChildren[i], @@ -661,7 +668,8 @@ class FlexLayoutProperties extends LayoutProperties { displayMainAxisAlignment != MainAxisAlignment.end) { spaces.add( renderPropsWithFullCrossAxisDimension.clone() - ..mainAxisOffset = childrenRenderProps.last.mainAxisDimension + + ..mainAxisOffset = + childrenRenderProps.last.mainAxisDimension + childrenRenderProps.last.mainAxisOffset ..mainAxisDimension = renderLeadingSpace ..mainAxisRealDimension = actualLeadingSpace, @@ -699,13 +707,15 @@ class FlexLayoutProperties extends LayoutProperties { spaces.add(space.clone()..crossAxisOffset = 0.0); spaces.add( space.clone() - ..crossAxisOffset = renderProperties.crossAxisDimension + + ..crossAxisOffset = + renderProperties.crossAxisDimension + renderProperties.crossAxisOffset, ); } else { - space.crossAxisOffset = crossAxisAlignment == CrossAxisAlignment.end - ? 0 - : renderProperties.crossAxisDimension; + space.crossAxisOffset = + crossAxisAlignment == CrossAxisAlignment.end + ? 0 + : renderProperties.crossAxisDimension; spaces.add(space); } } @@ -713,18 +723,24 @@ class FlexLayoutProperties extends LayoutProperties { } static final _directionUtils = EnumUtils(Axis.values); - static final _mainAxisAlignmentUtils = - EnumUtils(MainAxisAlignment.values); - static final _mainAxisSizeUtils = - EnumUtils(MainAxisSize.values); - static final _crossAxisAlignmentUtils = - EnumUtils(CrossAxisAlignment.values); - static final _textDirectionUtils = - EnumUtils(TextDirection.values); - static final _verticalDirectionUtils = - EnumUtils(VerticalDirection.values); - static final _textBaselineUtils = - EnumUtils(TextBaseline.values); + static final _mainAxisAlignmentUtils = EnumUtils( + MainAxisAlignment.values, + ); + static final _mainAxisSizeUtils = EnumUtils( + MainAxisSize.values, + ); + static final _crossAxisAlignmentUtils = EnumUtils( + CrossAxisAlignment.values, + ); + static final _textDirectionUtils = EnumUtils( + TextDirection.values, + ); + static final _verticalDirectionUtils = EnumUtils( + VerticalDirection.values, + ); + static final _textBaselineUtils = EnumUtils( + TextBaseline.values, + ); } /// RenderProperties contains information for rendering a [LayoutProperties] node @@ -736,12 +752,12 @@ class RenderProperties { Size? realSize, this.layoutProperties, this.isFreeSpace = false, - }) : width = size?.width ?? 0.0, - height = size?.height ?? 0.0, - realWidth = realSize?.width ?? 0.0, - realHeight = realSize?.height ?? 0.0, - dx = offset?.dx ?? 0.0, - dy = offset?.dy ?? 0.0; + }) : width = size?.width ?? 0.0, + height = size?.height ?? 0.0, + realWidth = realSize?.width ?? 0.0, + realHeight = realSize?.height ?? 0.0, + dx = offset?.dx ?? 0.0, + dy = offset?.dy ?? 0.0; final Axis axis; 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 eb5d874b16c..0a969828eb3 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 @@ -143,19 +143,14 @@ class InspectorScreenBodyState extends State initialFractions: const [0.33, 0.67], children: [ summaryTree, - InspectorDetails( - detailsTree: detailsTree, - controller: controller, - ), + InspectorDetails(detailsTree: detailsTree, controller: controller), ], ); return Column( children: [ const InspectorControls(), const SizedBox(height: intermediateSpacing), - Expanded( - child: widgetTrees, - ), + Expanded(child: widgetTrees), ], ); } @@ -171,24 +166,28 @@ class InspectorScreenBodyState extends State constraints: constraints, onRefreshInspectorPressed: _refreshInspector, onSearchVisibleToggle: _onSearchVisibleToggle, - searchFieldBuilder: () => - StatelessSearchField( - controller: _summaryTreeController, - searchFieldEnabled: true, - shouldRequestFocus: searchVisible, - supportsNavigation: true, - onClose: _onSearchVisibleToggle, - ), + searchFieldBuilder: + () => StatelessSearchField( + controller: _summaryTreeController, + searchFieldEnabled: true, + shouldRequestFocus: searchVisible, + supportsNavigation: true, + onClose: _onSearchVisibleToggle, + ), ), Expanded( child: ValueListenableBuilder( valueListenable: serviceConnection.errorBadgeManager .erroredItemsForPage(InspectorScreen.id), builder: (_, LinkedHashMap errors, _) { - final inspectableErrors = errors.map( - (key, value) => - MapEntry(key, value as InspectableWidgetError), - ) as LinkedHashMap; + final inspectableErrors = + errors.map( + (key, value) => MapEntry( + key, + value as InspectableWidgetError, + ), + ) + as LinkedHashMap; return Stack( children: [ InspectorTree( @@ -202,15 +201,17 @@ class InspectorScreenBodyState extends State if (errors.isNotEmpty) ValueListenableBuilder( valueListenable: controller.selectedErrorIndex, - builder: (_, selectedErrorIndex, _) => Positioned( - top: 0, - right: 0, - child: ErrorNavigator( - errors: inspectableErrors, - errorIndex: selectedErrorIndex, - onSelectError: controller.selectErrorByIndex, - ), - ), + builder: + (_, selectedErrorIndex, _) => Positioned( + top: 0, + right: 0, + child: ErrorNavigator( + errors: inspectableErrors, + errorIndex: selectedErrorIndex, + onSelectError: + controller.selectErrorByIndex, + ), + ), ), ], ); @@ -273,14 +274,8 @@ class InspectorScreenBodyState extends State if (!controller.firstInspectorTreeLoadCompleted) { // We do not want to complete this timing operation because the force // refresh will skew the results. - ga.cancelTimingOperation( - InspectorScreen.id, - gac.pageReady, - ); - ga.select( - gac.inspector, - gac.refreshEmptyTree, - ); + ga.cancelTimingOperation(InspectorScreen.id, gac.pageReady); + ga.select(gac.inspector, gac.refreshEmptyTree); controller.firstInspectorTreeLoadCompleted = true; } await controller.onForceRefresh(); @@ -324,18 +319,18 @@ class InspectorSummaryTreeControls extends StatelessWidget { ), ...!isSearchVisible ? [ - const Spacer(), - ToolbarAction( - icon: Icons.search, - onPressed: onSearchVisibleToggle, - tooltip: 'Search Tree', - ), - ] + const Spacer(), + ToolbarAction( + icon: Icons.search, + onPressed: onSearchVisibleToggle, + tooltip: 'Search Tree', + ), + ] : [ - constraints.maxWidth >= _searchBreakpoint - ? _buildSearchControls() - : const Spacer(), - ], + constraints.maxWidth >= _searchBreakpoint + ? _buildSearchControls() + : const Spacer(), + ], ToolbarAction( icon: Icons.refresh, onPressed: onRefreshInspectorPressed, @@ -345,10 +340,7 @@ class InspectorSummaryTreeControls extends StatelessWidget { ), ), if (isSearchVisible && constraints.maxWidth < _searchBreakpoint) - _controlsContainer( - context, - Row(children: [_buildSearchControls()]), - ), + _controlsContainer(context, Row(children: [_buildSearchControls()])), ], ); } @@ -357,9 +349,7 @@ class InspectorSummaryTreeControls extends StatelessWidget { return Container( height: defaultHeaderHeight, decoration: BoxDecoration( - border: Border( - bottom: defaultBorderSide(Theme.of(context)), - ), + border: Border(bottom: defaultBorderSide(Theme.of(context))), ), child: child, ); @@ -392,9 +382,10 @@ class ErrorNavigator extends StatelessWidget { @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; - final label = errorIndex != null - ? 'Error ${errorIndex! + 1}/${errors.length}' - : 'Errors: ${errors.length}'; + final label = + errorIndex != null + ? 'Error ${errorIndex! + 1}/${errors.length}' + : 'Errors: ${errors.length}'; return Container( color: colorScheme.errorContainer, child: Padding( @@ -408,9 +399,7 @@ class ErrorNavigator extends StatelessWidget { padding: const EdgeInsets.only(right: denseSpacing), child: Text( label, - style: TextStyle( - color: colorScheme.onErrorContainer, - ), + style: TextStyle(color: colorScheme.onErrorContainer), ), ), _ErrorNavigatorButton( diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_details_tab.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_screen_details_tab.dart index a73c7b2b7a9..d680b8e41e6 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_details_tab.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_screen_details_tab.dart @@ -72,10 +72,7 @@ class InspectorDetails extends StatelessWidget { } class InspectorExpandCollapseButtons extends StatefulWidget { - const InspectorExpandCollapseButtons({ - super.key, - required this.controller, - }); + const InspectorExpandCollapseButtons({super.key, required this.controller}); final InspectorController controller; @@ -85,7 +82,8 @@ class InspectorExpandCollapseButtons extends StatefulWidget { } class _InspectorExpandCollapseButtonsState - extends State with BlockingActionMixin { + extends State + with BlockingActionMixin { bool get enableButtons => !actionInProgress; @override @@ -93,9 +91,7 @@ class _InspectorExpandCollapseButtonsState return Container( alignment: Alignment.centerRight, decoration: BoxDecoration( - border: Border( - left: defaultBorderSide(Theme.of(context)), - ), + border: Border(left: defaultBorderSide(Theme.of(context))), ), child: Row( mainAxisAlignment: MainAxisAlignment.end, @@ -141,10 +137,7 @@ class _InspectorExpandCollapseButtonsState } void _onCollapseClick() { - ga.select( - gac.inspector, - gac.collapseAll, - ); + ga.select(gac.inspector, gac.collapseAll); widget.controller.collapseDetailsToSelected(); } } 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 3da2d2428d4..dd4d43b0d11 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 @@ -109,11 +109,12 @@ class InspectorTreeController extends DisposableController gac.inspector, gac.inspectorTreeControllerInitialized, nonInteraction: true, - screenMetricsProvider: () => InspectorScreenMetrics.legacy( - inspectorTreeControllerId: gaId, - rootSetCount: _rootSetCount, - rowCount: _root?.subtreeSize, - ), + screenMetricsProvider: + () => InspectorScreenMetrics.legacy( + inspectorTreeControllerId: gaId, + rootSetCount: _rootSetCount, + rowCount: _root?.subtreeSize, + ), ); } @@ -170,11 +171,12 @@ class InspectorTreeController extends DisposableController gac.inspector, gac.inspectorTreeControllerRootChange, nonInteraction: true, - screenMetricsProvider: () => InspectorScreenMetrics.legacy( - inspectorTreeControllerId: gaId, - rootSetCount: ++_rootSetCount, - rowCount: _root?.subtreeSize, - ), + screenMetricsProvider: + () => InspectorScreenMetrics.legacy( + inspectorTreeControllerId: gaId, + rootSetCount: ++_rootSetCount, + rowCount: _root?.subtreeSize, + ), ); }); } @@ -339,12 +341,15 @@ class InspectorTreeController extends DisposableController final rootLocal = root!; - selection = rootLocal - .getRow( - (rootLocal.getRowIndex(selection!) + indexOffset) - .clamp(0, numRows - 1), - ) - ?.node; + selection = + rootLocal + .getRow( + (rootLocal.getRowIndex(selection!) + indexOffset).clamp( + 0, + numRows - 1, + ), + ) + ?.node; } double get horizontalPadding => 10.0; @@ -442,10 +447,7 @@ class InspectorTreeController extends DisposableController void onSelectNode(InspectorTreeNode? node) { selection = node; - ga.select( - gac.inspector, - gac.treeNodeSelection, - ); + ga.select(gac.inspector, gac.treeNodeSelection); expandPath(node); } @@ -550,8 +552,9 @@ class InspectorTreeController extends DisposableController if (diagnosticsNode.hasChildren || diagnosticsNode.inlineProperties.isNotEmpty) { if (diagnosticsNode.childrenReady || !diagnosticsNode.hasChildren) { - final styleIsMultiline = - expandPropertiesByDefault(diagnosticsNode.style); + final styleIsMultiline = expandPropertiesByDefault( + diagnosticsNode.style, + ); setupChildren( diagnosticsNode, node, @@ -655,8 +658,9 @@ class InspectorTreeController extends DisposableController if (searchPreviousMatches) { final previousMatches = searchMatches.value; for (final previousMatch in previousMatches) { - if (previousMatch.node.diagnostic!.searchValue - .caseInsensitiveContains(search)) { + if (previousMatch.node.diagnostic!.searchValue.caseInsensitiveContains( + search, + )) { matches.add(previousMatch); } } @@ -671,21 +675,17 @@ class InspectorTreeController extends DisposableController if (search.isEmpty || inspectorService == null || inspectorService.isDisposed) { - assert( - () { - debugPrint('Search completed, no search'); - return true; - }(), - ); + assert(() { + debugPrint('Search completed, no search'); + return true; + }()); return matches; } - assert( - () { - debugPrint('Search started: $_searchTarget'); - return true; - }(), - ); + assert(() { + debugPrint('Search started: $_searchTarget'); + return true; + }()); for (final row in _searchableCachedRows) { final diagnostic = row!.node.diagnostic; @@ -702,14 +702,12 @@ class InspectorTreeController extends DisposableController // Widget search end } - assert( - () { - debugPrint( - 'Search completed with $debugStatsWidgets widgets, $debugStatsSearchOps ops', - ); - return true; - }(), - ); + assert(() { + debugPrint( + 'Search completed with $debugStatsWidgets widgets, $debugStatsSearchOps ops', + ); + return true; + }()); return matches; } @@ -837,21 +835,21 @@ class _InspectorTreeState extends State } // TODO(devoncarew): Commented out as per flutter/devtools/pull/2001. -// void _onScrollYChange() { -// if (controller == null) return; -// -// // If the vertical position is already being animated we should not trigger -// // a new animation of the horizontal position as a more direct animation of -// // the horizontal position has already been triggered. -// if (currentAnimateY != null) return; -// -// final x = _computeTargetX(_scrollControllerY.offset); -// _scrollControllerX.animateTo( -// x, -// duration: defaultDuration, -// curve: defaultCurve, -// ); -// } + // void _onScrollYChange() { + // if (controller == null) return; + // + // // If the vertical position is already being animated we should not trigger + // // a new animation of the horizontal position as a more direct animation of + // // the horizontal position has already been triggered. + // if (currentAnimateY != null) return; + // + // final x = _computeTargetX(_scrollControllerY.offset); + // _scrollControllerX.animateTo( + // x, + // duration: defaultDuration, + // curve: defaultCurve, + // ); + // } @override Future scrollToRect(Rect rect) async { @@ -862,12 +860,14 @@ class _InspectorTreeState extends State final initialX = rect.left; final initialY = rect.top; - final yOffsetAtViewportTop = _scrollControllerY.hasClients - ? _scrollControllerY.offset - : _scrollControllerY.initialScrollOffset; - final xOffsetAtViewportLeft = _scrollControllerX.hasClients - ? _scrollControllerX.offset - : _scrollControllerX.initialScrollOffset; + final yOffsetAtViewportTop = + _scrollControllerY.hasClients + ? _scrollControllerY.offset + : _scrollControllerY.initialScrollOffset; + final xOffsetAtViewportLeft = + _scrollControllerX.hasClients + ? _scrollControllerX.offset + : _scrollControllerX.initialScrollOffset; final viewPortInScrollControllerSpace = Rect.fromLTWH( xOffsetAtViewportLeft, @@ -878,7 +878,7 @@ class _InspectorTreeState extends State final isRectInViewPort = viewPortInScrollControllerSpace.contains(rect.topLeft) && - viewPortInScrollControllerSpace.contains(rect.bottomRight); + viewPortInScrollControllerSpace.contains(rect.bottomRight); if (isRectInViewPort) { // The rect is already in view, don't scroll return; @@ -948,9 +948,7 @@ class _InspectorTreeState extends State /// Pad [initialY] so that a row would be placed in the vertical center of /// the screen. - double _padTargetY({ - required double initialY, - }) { + double _padTargetY({required double initialY}) { return initialY - (safeViewportHeight / 2) + inspectorRowHeight / 2; } @@ -1025,7 +1023,8 @@ class _InspectorTreeState extends State controller: _scrollControllerX, child: ConstrainedBox( constraints: BoxConstraints( - maxWidth: treeControllerLocal.rowWidth + + maxWidth: + treeControllerLocal.rowWidth + treeControllerLocal.maxRowIndent, ), // TODO(kenz): this scrollbar needs to be sticky to the right side of @@ -1046,27 +1045,28 @@ class _InspectorTreeState extends State offsetControllerViewportDimension: viewportWidth, child: ListView.custom( itemExtent: inspectorRowHeight, - childrenDelegate: SliverChildBuilderDelegate( - (context, index) { - if (index == treeControllerLocal.numRows) { - return SizedBox(height: inspectorRowHeight); - } - final row = treeControllerLocal.getCachedRow(index)!; - final inspectorRef = row.node.diagnostic?.valueRef.id; - return _InspectorTreeRowWidget( - key: PageStorageKey(row.node), - inspectorTreeState: this, - row: row, - scrollControllerX: _scrollControllerX, - viewportWidth: viewportWidth, - error: widget.widgetErrors != null && - inspectorRef != null - ? widget.widgetErrors![inspectorRef] - : null, - ); - }, - childCount: treeControllerLocal.numRows + 1, - ), + childrenDelegate: SliverChildBuilderDelegate(( + context, + index, + ) { + if (index == treeControllerLocal.numRows) { + return SizedBox(height: inspectorRowHeight); + } + final row = treeControllerLocal.getCachedRow(index)!; + final inspectorRef = row.node.diagnostic?.valueRef.id; + return _InspectorTreeRowWidget( + key: PageStorageKey(row.node), + inspectorTreeState: this, + row: row, + scrollControllerX: _scrollControllerX, + viewportWidth: viewportWidth, + error: + widget.widgetErrors != null && + inspectorRef != null + ? widget.widgetErrors![inspectorRef] + : null, + ); + }, childCount: treeControllerLocal.numRows + 1), controller: _scrollControllerY, ), ), @@ -1102,9 +1102,10 @@ class _InspectorTreeState extends State bool get wantKeepAlive => true; } -Paint _defaultPaint(ColorScheme colorScheme) => Paint() - ..color = colorScheme.treeGuidelineColor - ..strokeWidth = chartLineStrokeWidth; +Paint _defaultPaint(ColorScheme colorScheme) => + Paint() + ..color = colorScheme.treeGuidelineColor + ..strokeWidth = chartLineStrokeWidth; /// Custom painter that draws lines indicating how parent and child rows are /// connected to each other. @@ -1142,11 +1143,13 @@ class _RowPainter extends CustomPainter { // If this row is itself connected to a parent then draw the L shaped line // to make that connection. if (row.lineToParent) { - currentX = _controller.getDepthIndent(row.depth - 1) - + currentX = + _controller.getDepthIndent(row.depth - 1) - inspectorColumnWidth * 0.5; - final width = showExpandCollapse - ? inspectorColumnWidth * 0.5 - : inspectorColumnWidth; + final width = + showExpandCollapse + ? inspectorColumnWidth * 0.5 + : inspectorColumnWidth; canvas.drawLine( Offset(currentX, 0.0), Offset(currentX, inspectorRowHeight * 0.5), @@ -1215,9 +1218,10 @@ class InspectorRowContent extends StatelessWidget { Color? backgroundColor; if (row.isSelected) { - backgroundColor = hasError - ? colorScheme.errorContainer - : colorScheme.selectedRowBackgroundColor; + backgroundColor = + hasError + ? colorScheme.errorContainer + : colorScheme.selectedRowBackgroundColor; } final node = row.node; @@ -1234,19 +1238,16 @@ class InspectorRowContent extends StatelessWidget { children: [ node.showExpandCollapse ? InkWell( - onTap: onToggle, - child: RotationTransition( - turns: expandArrowAnimation, - child: Icon( - Icons.expand_more, - size: defaultIconSize, - ), - ), - ) - : const SizedBox( - width: defaultSpacing, - height: defaultSpacing, + onTap: onToggle, + child: RotationTransition( + turns: expandArrowAnimation, + child: Icon(Icons.expand_more, size: defaultIconSize), ), + ) + : const SizedBox( + width: defaultSpacing, + height: defaultSpacing, + ), Expanded( child: Container( color: backgroundColor, @@ -1268,11 +1269,11 @@ class InspectorRowContent extends StatelessWidget { nodeDescriptionHighlightStyle: searchValue.isEmpty || !row.isSearchMatch ? DiagnosticsTextStyles.regular( - Theme.of(context).colorScheme, - ) + Theme.of(context).colorScheme, + ) : row.isSelected - ? theme.searchMatchHighlightStyleFocused - : theme.searchMatchHighlightStyle, + ? theme.searchMatchHighlightStyleFocused + : theme.searchMatchHighlightStyle, ), ), ), @@ -1287,8 +1288,10 @@ class InspectorRowContent extends StatelessWidget { // Wrap with tooltip if there is an error for this node's widget. if (hasError) { - rowWidget = - DevToolsTooltip(message: error!.errorMessage, child: rowWidget); + rowWidget = DevToolsTooltip( + message: error!.errorMessage, + child: rowWidget, + ); } return CustomPaint( 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 2b29b7746e9..567a3c5862a 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 @@ -21,10 +21,7 @@ import '../ui/widgets_theme.dart'; /// Layout visualizer for a widget with a box-layout. class BoxLayoutExplorerWidget extends LayoutExplorerWidget { - const BoxLayoutExplorerWidget( - super.inspectorController, { - super.key, - }); + const BoxLayoutExplorerWidget(super.inspectorController, {super.key}); static bool shouldDisplay(RemoteDiagnosticsNode _) { // Pretend this layout explorer is always available. This layout explorer @@ -41,8 +38,9 @@ class BoxLayoutExplorerWidget extends LayoutExplorerWidget { BoxLayoutExplorerWidgetState(); } -class BoxLayoutExplorerWidgetState extends LayoutExplorerWidgetState< - BoxLayoutExplorerWidget, LayoutProperties> { +class BoxLayoutExplorerWidgetState + extends + LayoutExplorerWidgetState { @override RemoteDiagnosticsNode? getRoot(RemoteDiagnosticsNode? node) { final nodeLocal = node; @@ -79,9 +77,10 @@ class BoxLayoutExplorerWidgetState extends LayoutExplorerWidgetState< setState(() { // This implementation will need to change if we support showing more than // a single widget in the box visualization for the layout explorer. - highlighted = newProperties != null && selectedNode == newProperties.node - ? newProperties - : null; + highlighted = + newProperties != null && selectedNode == newProperties.node + ? newProperties + : null; }); } @@ -169,7 +168,8 @@ class BoxLayoutExplorerWidgetState extends LayoutExplorerWidgetState< final theme = Theme.of(context); final colorScheme = theme.colorScheme; - final parentProperties = this.parentProperties ?? + final parentProperties = + this.parentProperties ?? propertiesLocal; // Fall back to this node's properties if there is no parent. final parentSize = parentProperties.size; diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/flex.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/flex.dart index 42df234e2cc..ad0ac8e1b74 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/flex.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/flex.dart @@ -29,10 +29,7 @@ import 'utils.dart'; double get alignmentDropdownMaxSize => scaleByFontFactor(140.0); class FlexLayoutExplorerWidget extends LayoutExplorerWidget { - const FlexLayoutExplorerWidget( - super.inspectorController, { - super.key, - }); + const FlexLayoutExplorerWidget(super.inspectorController, {super.key}); static bool shouldDisplay(RemoteDiagnosticsNode node) { return (node.isFlex) || (node.parent?.isFlex ?? false); @@ -43,8 +40,12 @@ class FlexLayoutExplorerWidget extends LayoutExplorerWidget { FlexLayoutExplorerWidgetState(); } -class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< - FlexLayoutExplorerWidget, FlexLayoutProperties> { +class FlexLayoutExplorerWidgetState + extends + LayoutExplorerWidgetState< + FlexLayoutExplorerWidget, + FlexLayoutProperties + > { final scrollController = ScrollController(); Axis get direction => properties!.direction; @@ -57,9 +58,10 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< ? colorScheme.mainAxisColor : colorScheme.crossAxisColor; - Color verticalColor(ColorScheme colorScheme) => properties!.isMainAxisVertical - ? colorScheme.mainAxisColor - : colorScheme.crossAxisColor; + Color verticalColor(ColorScheme colorScheme) => + properties!.isMainAxisVertical + ? colorScheme.mainAxisColor + : colorScheme.crossAxisColor; Color horizontalTextColor(ColorScheme colorScheme) => properties!.isMainAxisHorizontal @@ -120,9 +122,10 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< Widget _buildAxisAlignmentDropdown(Axis axis, ThemeData theme) { final colorScheme = theme.colorScheme; - final color = axis == direction - ? colorScheme.mainAxisTextColor - : colorScheme.crossAxisTextColor; + final color = + axis == direction + ? colorScheme.mainAxisTextColor + : colorScheme.crossAxisTextColor; List alignmentEnumEntries; Object? selected; final propertiesLocal = properties!; @@ -150,9 +153,10 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< isExpanded: true, // Avoid showing an underline for the main axis and cross-axis drop downs. underline: const SizedBox(), - iconEnabledColor: axis == propertiesLocal.direction - ? colorScheme.mainAxisColor - : colorScheme.crossAxisColor, + iconEnabledColor: + axis == propertiesLocal.direction + ? colorScheme.mainAxisColor + : colorScheme.crossAxisColor, selectedItemBuilder: (context) { return [ for (final alignment in alignmentEnumEntries) @@ -173,13 +177,13 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< child: Image.asset( (axis == direction) ? mainAxisAssetImageUrl( - direction, - alignment as MainAxisAlignment, - ) + direction, + alignment as MainAxisAlignment, + ) : crossAxisAssetImageUrl( - direction, - alignment as CrossAxisAlignment, - ), + direction, + alignment as CrossAxisAlignment, + ), height: axisAlignmentAssetImageHeight, fit: BoxFit.fitHeight, color: color, @@ -212,13 +216,13 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< child: Image.asset( (axis == direction) ? mainAxisAssetImageUrl( - direction, - alignment as MainAxisAlignment, - ) + direction, + alignment as MainAxisAlignment, + ) : crossAxisAssetImageUrl( - direction, - alignment as CrossAxisAlignment, - ), + direction, + alignment as CrossAxisAlignment, + ), fit: BoxFit.fitHeight, color: color, ), @@ -234,13 +238,14 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< // if the axis is the main axis the type should be [MainAxisAlignment] // if the axis is the cross axis the type should be [CrossAxisAlignment] FlexLayoutProperties changedProperties; - changedProperties = axis == direction - ? propertiesLocal.copyWith( - mainAxisAlignment: newSelection as MainAxisAlignment?, - ) - : propertiesLocal.copyWith( - crossAxisAlignment: newSelection as CrossAxisAlignment?, - ); + changedProperties = + axis == direction + ? propertiesLocal.copyWith( + mainAxisAlignment: newSelection as MainAxisAlignment?, + ) + : propertiesLocal.copyWith( + crossAxisAlignment: newSelection as CrossAxisAlignment?, + ); final valueRef = propertiesLocal.node.valueRef; markAsDirty(); await objectGroup!.invokeSetFlexProperties( @@ -449,9 +454,7 @@ class _VisualizeFlexChildrenState extends State { final contents = Container( decoration: BoxDecoration( - border: Border.all( - color: theme.primaryColorLight, - ), + border: Border.all(color: theme.primaryColorLight), ), margin: const EdgeInsets.only(top: margin, left: margin), child: LayoutBuilder( @@ -463,21 +466,23 @@ class _VisualizeFlexChildrenState extends State { return axis == Axis.horizontal ? maxWidth : maxHeight; } - final childrenAndMainAxisSpacesRenderProps = - widget.properties.childrenRenderProperties( - smallestRenderWidth: minRenderWidth, - largestRenderWidth: defaultMaxRenderWidth, - smallestRenderHeight: minRenderHeight, - largestRenderHeight: defaultMaxRenderHeight, - maxSizeAvailable: maxSizeAvailable, - ); - - final renderProperties = childrenAndMainAxisSpacesRenderProps - .where((renderProps) => !renderProps.isFreeSpace) - .toList(); - final mainAxisSpaces = childrenAndMainAxisSpacesRenderProps - .where((renderProps) => renderProps.isFreeSpace) - .toList(); + final childrenAndMainAxisSpacesRenderProps = widget.properties + .childrenRenderProperties( + smallestRenderWidth: minRenderWidth, + largestRenderWidth: defaultMaxRenderWidth, + smallestRenderHeight: minRenderHeight, + largestRenderHeight: defaultMaxRenderHeight, + maxSizeAvailable: maxSizeAvailable, + ); + + final renderProperties = + childrenAndMainAxisSpacesRenderProps + .where((renderProps) => !renderProps.isFreeSpace) + .toList(); + final mainAxisSpaces = + childrenAndMainAxisSpacesRenderProps + .where((renderProps) => renderProps.isFreeSpace) + .toList(); final crossAxisSpaces = widget.properties.crossAxisSpaces( childrenRenderProperties: renderProperties, maxSizeAvailable: maxSizeAvailable, @@ -523,22 +528,27 @@ class _VisualizeFlexChildrenState extends State { scrollDirection: widget.properties.direction, controller: widget.scrollController, child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: maxWidth, - minHeight: maxHeight, - maxWidth: widget.direction == Axis.horizontal - ? sum( - childrenAndMainAxisSpacesRenderProps - .map((renderSize) => renderSize.width), - ) - : maxWidth, - maxHeight: widget.direction == Axis.vertical - ? sum( - childrenAndMainAxisSpacesRenderProps - .map((renderSize) => renderSize.height), - ) - : maxHeight, - ).normalize(), + constraints: + BoxConstraints( + minWidth: maxWidth, + minHeight: maxHeight, + maxWidth: + widget.direction == Axis.horizontal + ? sum( + childrenAndMainAxisSpacesRenderProps.map( + (renderSize) => renderSize.width, + ), + ) + : maxWidth, + maxHeight: + widget.direction == Axis.vertical + ? sum( + childrenAndMainAxisSpacesRenderProps.map( + (renderSize) => renderSize.height, + ), + ) + : maxHeight, + ).normalize(), child: Stack( children: [ LayoutExplorerBackground(colorScheme: colorScheme), @@ -596,10 +606,7 @@ class FlexChildVisualizer extends StatelessWidget { void onChangeFlexFit(FlexFit? newFlexFit) async { state.markAsDirty(); - await objectGroup!.invokeSetFlexFit( - properties.node.valueRef, - newFlexFit!, - ); + await objectGroup!.invokeSetFlexFit(properties.node.valueRef, newFlexFit!); } Widget _buildFlexFactorChangerDropdown( @@ -611,9 +618,10 @@ class FlexChildVisualizer extends StatelessWidget { Widget buildMenuitemChild(int? flexFactor) { return Text( 'flex: $flexFactor', - style: flexFactor == propertiesLocal.flexFactor - ? theme.boldTextStyle.copyWith(color: emphasizedTextColor) - : theme.regularTextStyleWithColor(emphasizedTextColor), + style: + flexFactor == propertiesLocal.flexFactor + ? theme.boldTextStyle.copyWith(color: emphasizedTextColor) + : theme.regularTextStyleWithColor(emphasizedTextColor), ); } @@ -638,9 +646,9 @@ class FlexChildVisualizer extends StatelessWidget { Widget _buildFlexFitChangerDropdown(ThemeData theme) { Widget flexFitDescription(FlexFit flexFit) => Text( - 'fit: ${flexFit.name}', - style: theme.regularTextStyleWithColor(emphasizedTextColor), - ); + 'fit: ${flexFit.name}', + style: theme.regularTextStyleWithColor(emphasizedTextColor), + ); final propertiesLocal = properties; @@ -673,14 +681,13 @@ class FlexChildVisualizer extends StatelessWidget { // TODO(https://github.com/flutter/devtools/issues/4058) allow more dynamic // flex factor input final currentFlexFactor = properties.flexFactor?.toInt() ?? 0; - final currentMaxFlexFactor = - math.max(currentFlexFactor, maximumFlexFactorOptions); + final currentMaxFlexFactor = math.max( + currentFlexFactor, + maximumFlexFactorOptions, + ); return Container( - margin: const EdgeInsets.only( - top: margin, - left: margin, - ), + margin: const EdgeInsets.only(top: margin, left: margin), child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -718,15 +725,20 @@ class FlexChildVisualizer extends StatelessWidget { final horizontal = rootLocal.isMainAxisHorizontal; late Size size; - size = propertiesLocal.hasFlexFactor - ? SizeTween( - begin: Size( - horizontal ? minRenderWidth - entranceMargin : renderSize.width, - vertical ? minRenderHeight - entranceMargin : renderSize.height, - ), - end: renderSize, - ).evaluate(state.entranceCurve)! - : renderSize; + size = + propertiesLocal.hasFlexFactor + ? SizeTween( + begin: Size( + horizontal + ? minRenderWidth - entranceMargin + : renderSize.width, + vertical + ? minRenderHeight - entranceMargin + : renderSize.height, + ), + end: renderSize, + ).evaluate(state.entranceCurve)! + : renderSize; // Not-expanded widgets enter much faster. return Opacity( opacity: min([state.entranceCurve.value * 5, 1.0]), diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/utils.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/utils.dart index 57868d1c6d1..feb98ee8605 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/utils.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/utils.dart @@ -23,11 +23,7 @@ String mainAxisAssetImageUrl(Axis direction, MainAxisAlignment alignment) { class AnimatedFlexLayoutProperties extends AnimatedLayoutProperties implements FlexLayoutProperties { - AnimatedFlexLayoutProperties( - super.begin, - super.end, - super.animation, - ); + AnimatedFlexLayoutProperties(super.begin, super.end, super.animation); @override CrossAxisAlignment? get crossAxisAlignment => end.crossAxisAlignment; @@ -85,7 +81,8 @@ class AnimatedFlexLayoutProperties } @override - double get crossAxisDimension => lerpDouble( + double get crossAxisDimension => + lerpDouble( begin.crossAxisDimension, end.crossAxisDimension, animation.value, @@ -119,7 +116,8 @@ class AnimatedFlexLayoutProperties bool get isMainAxisVertical => end.isMainAxisVertical; @override - double get mainAxisDimension => lerpDouble( + double get mainAxisDimension => + lerpDouble( begin.mainAxisDimension, end.mainAxisDimension, animation.value, diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/arrow.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/arrow.dart index a90b5e0d501..82ac3bba53f 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/arrow.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/arrow.dart @@ -11,16 +11,12 @@ const defaultArrowColor = Colors.white; const defaultArrowStrokeWidth = 2.0; const defaultDistanceToArrow = 4.0; -enum ArrowType { - up, - left, - right, - down, -} +enum ArrowType { up, left, right, down } -Axis axis(ArrowType type) => (type == ArrowType.up || type == ArrowType.down) - ? Axis.vertical - : Axis.horizontal; +Axis axis(ArrowType type) => + (type == ArrowType.up || type == ArrowType.down) + ? Axis.vertical + : Axis.horizontal; /// Widget that draws a bidirectional arrow around another widget. /// @@ -35,12 +31,12 @@ class ArrowWrapper extends StatelessWidget { double? arrowHeadSize, this.arrowStrokeWidth = defaultArrowStrokeWidth, this.childMarginFromArrow = defaultDistanceToArrow, - }) : assert(childMarginFromArrow > 0.0), - direction = axis(type), - isBidirectional = false, - startArrowType = type, - endArrowType = type, - arrowHeadSize = arrowHeadSize ?? defaultIconSize; + }) : assert(childMarginFromArrow > 0.0), + direction = axis(type), + isBidirectional = false, + startArrowType = type, + endArrowType = type, + arrowHeadSize = arrowHeadSize ?? defaultIconSize; const ArrowWrapper.bidirectional({ super.key, @@ -50,13 +46,13 @@ class ArrowWrapper extends StatelessWidget { required this.arrowHeadSize, this.arrowStrokeWidth = defaultArrowStrokeWidth, this.childMarginFromArrow = defaultDistanceToArrow, - }) : assert(arrowHeadSize >= 0.0), - assert(childMarginFromArrow >= 0.0), - isBidirectional = true, - startArrowType = - direction == Axis.horizontal ? ArrowType.left : ArrowType.up, - endArrowType = - direction == Axis.horizontal ? ArrowType.right : ArrowType.down; + }) : assert(arrowHeadSize >= 0.0), + assert(childMarginFromArrow >= 0.0), + isBidirectional = true, + startArrowType = + direction == Axis.horizontal ? ArrowType.left : ArrowType.up, + endArrowType = + direction == Axis.horizontal ? ArrowType.right : ArrowType.down; final Color arrowColor; final double arrowHeadSize; @@ -96,10 +92,11 @@ class ArrowWrapper extends StatelessWidget { headSize: arrowHeadSize, strokeWidth: arrowStrokeWidth, type: startArrowType, - shouldDrawHead: isBidirectional - ? true - : (startArrowType == ArrowType.left || - startArrowType == ArrowType.up), + shouldDrawHead: + isBidirectional + ? true + : (startArrowType == ArrowType.left || + startArrowType == ArrowType.up), ), ), ), @@ -115,10 +112,11 @@ class ArrowWrapper extends StatelessWidget { headSize: arrowHeadSize, strokeWidth: arrowStrokeWidth, type: endArrowType, - shouldDrawHead: isBidirectional - ? true - : (endArrowType == ArrowType.right || - endArrowType == ArrowType.down), + shouldDrawHead: + isBidirectional + ? true + : (endArrowType == ArrowType.right || + endArrowType == ArrowType.down), ), ), ), @@ -137,15 +135,15 @@ class ArrowWidget extends StatelessWidget { this.shouldDrawHead = true, this.strokeWidth = defaultArrowStrokeWidth, required this.type, - }) : assert(headSize > 0.0), - assert(strokeWidth > 0.0), - _painter = _ArrowPainter( - headSize: headSize, - color: color, - strokeWidth: strokeWidth, - type: type, - shouldDrawHead: shouldDrawHead, - ); + }) : assert(headSize > 0.0), + assert(strokeWidth > 0.0), + _painter = _ArrowPainter( + headSize: headSize, + color: color, + strokeWidth: strokeWidth, + type: type, + shouldDrawHead: shouldDrawHead, + ); final Color color; @@ -162,10 +160,7 @@ class ArrowWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return CustomPaint( - painter: _painter, - child: Container(), - ); + return CustomPaint(painter: _painter, child: Container()); } } @@ -177,7 +172,7 @@ class _ArrowPainter extends CustomPainter { this.shouldDrawHead = true, required this.type, }) : // the height of an equilateral triangle - headHeight = 0.5 * sqrt(3) * headSize; + headHeight = 0.5 * sqrt(3) * headSize; final Color color; final double headSize; @@ -204,9 +199,10 @@ class _ArrowPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - final paint = Paint() - ..color = color - ..strokeWidth = strokeWidth; + final paint = + Paint() + ..color = color + ..strokeWidth = strokeWidth; final originX = size.width / 2, originY = size.height / 2; Offset lineStartingPoint = Offset.zero; @@ -239,11 +235,12 @@ class _ArrowPainter extends CustomPainter { p3 = Offset(originX + headSizeDividedBy2, startingY); break; } - final path = Path() - ..moveTo(p1.dx, p1.dy) - ..lineTo(p2.dx, p2.dy) - ..lineTo(p3.dx, p3.dy) - ..close(); + final path = + Path() + ..moveTo(p1.dx, p1.dy) + ..lineTo(p2.dx, p2.dy) + ..lineTo(p3.dx, p3.dy) + ..close(); canvas.drawPath(path, paint); switch (type) { @@ -281,10 +278,6 @@ class _ArrowPainter extends CustomPainter { break; } } - canvas.drawLine( - lineStartingPoint, - lineEndingPoint, - paint, - ); + canvas.drawLine(lineStartingPoint, lineEndingPoint, paint); } } diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/dimension.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/dimension.dart index 490dc21d639..c7210817f8b 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/dimension.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/dimension.dart @@ -15,9 +15,10 @@ Widget dimensionDescription( final text = Text.rich( description, textAlign: TextAlign.center, - style: overflow - ? overflowingDimensionIndicatorTextStyle(colorScheme) - : dimensionIndicatorTextStyle, + style: + overflow + ? overflowingDimensionIndicatorTextStyle(colorScheme) + : dimensionIndicatorTextStyle, overflow: TextOverflow.ellipsis, ); if (overflow) { diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/free_space.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/free_space.dart index 073d5a00c1f..3480489763b 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/free_space.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/free_space.dart @@ -12,10 +12,7 @@ import 'dimension.dart'; import 'theme.dart'; class FreeSpaceVisualizerWidget extends StatelessWidget { - const FreeSpaceVisualizerWidget( - this.renderProperties, { - super.key, - }); + const FreeSpaceVisualizerWidget(this.renderProperties, {super.key}); final RenderProperties renderProperties; @@ -32,9 +29,7 @@ class FreeSpaceVisualizerWidget extends StatelessWidget { children: [ Flexible( child: dimensionDescription( - TextSpan( - text: widthDescription, - ), + TextSpan(text: widthDescription), false, colorScheme, ), @@ -109,9 +104,7 @@ class PaddingVisualizerWidget extends StatelessWidget { children: [ Flexible( child: dimensionDescription( - TextSpan( - text: widthDescription, - ), + TextSpan(text: widthDescription), false, colorScheme, ), diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/layout_explorer_widget.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/layout_explorer_widget.dart index 743e74a50de..4aedc7536c4 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/layout_explorer_widget.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/layout_explorer_widget.dart @@ -20,17 +20,17 @@ const maxRequestsPerSecond = 3.0; /// Base class for layout widgets for all widget types. abstract class LayoutExplorerWidget extends StatefulWidget { - const LayoutExplorerWidget( - this.inspectorController, { - super.key, - }); + const LayoutExplorerWidget(this.inspectorController, {super.key}); final InspectorController inspectorController; } /// Base class for state objects for layout widgets for all widget types. -abstract class LayoutExplorerWidgetState extends State +abstract class LayoutExplorerWidgetState< + W extends LayoutExplorerWidget, + L extends LayoutProperties +> + extends State with TickerProviderStateMixin implements InspectorServiceClient { LayoutExplorerWidgetState() { @@ -128,8 +128,9 @@ abstract class LayoutExplorerWidgetState[black, yellow, yellow, black], - [0.25, 0.25, 0.75, 0.75], - TileMode.repeated, - ); + static final indicatorPaint = + Paint() + ..shader = ui.Gradient.linear( + const Offset(0.0, 0.0), + const Offset(10.0, 10.0), + [black, yellow, yellow, black], + [0.25, 0.25, 0.75, 0.75], + TileMode.repeated, + ); @override void paint(Canvas canvas, Size size) { 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 0ebf49b5f85..bcc87573a7c 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 @@ -133,12 +133,7 @@ Widget buildUnderline() { return Container( height: 1.0, decoration: const BoxDecoration( - border: Border( - bottom: BorderSide( - color: textColor, - width: 0.0, - ), - ), + border: Border(bottom: BorderSide(color: textColor, width: 0.0)), ), ); } diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/utils.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/utils.dart index 4c31bc22d23..7df3b6bf920 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/utils.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/utils.dart @@ -32,12 +32,12 @@ class BorderLayout extends StatelessWidget { this.bottomHeight, this.center, }) : assert( - left != null || - top != null || - right != null || - bottom != null || - center != null, - ); + left != null || + top != null || + right != null || + bottom != null || + center != null, + ); final Widget? center; final Widget? top; @@ -160,17 +160,19 @@ class WidgetVisualizer extends StatelessWidget { width: isSelected ? _borderSelectedWidth : _borderUnselectedWidth, ), - color: isSelected - ? theme.canvasColor.brighten() - : theme.canvasColor.darken(), - boxShadow: isSelected - ? [ - BoxShadow( - color: Colors.black.withAlpha(255 ~/ 2), - blurRadius: 20, - ), - ] - : null, + color: + isSelected + ? theme.canvasColor.brighten() + : theme.canvasColor.darken(), + boxShadow: + isSelected + ? [ + BoxShadow( + color: Colors.black.withAlpha(255 ~/ 2), + blurRadius: 20, + ), + ] + : null, ), child: Stack( children: [ @@ -185,12 +187,14 @@ class WidgetVisualizer extends StatelessWidget { ), Container( margin: EdgeInsets.only( - right: overflowSide == OverflowSide.right - ? _overflowIndicatorSize - : 0.0, - bottom: overflowSide == OverflowSide.bottom - ? _overflowIndicatorSize - : 0.0, + right: + overflowSide == OverflowSide.right + ? _overflowIndicatorSize + : 0.0, + bottom: + overflowSide == OverflowSide.bottom + ? _overflowIndicatorSize + : 0.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -204,10 +208,11 @@ class WidgetVisualizer extends StatelessWidget { Flexible( child: Container( constraints: BoxConstraints( - maxWidth: largeTitle - ? defaultMaxRenderWidth - : minRenderWidth * - widgetTitleMaxWidthPercentage, + maxWidth: + largeTitle + ? defaultMaxRenderWidth + : minRenderWidth * + widgetTitleMaxWidthPercentage, ), decoration: BoxDecoration(color: borderColor), padding: const EdgeInsets.all(4.0), @@ -242,15 +247,15 @@ class WidgetVisualizer extends StatelessWidget { class AnimatedLayoutProperties implements LayoutProperties { AnimatedLayoutProperties(this.begin, this.end, this.animation) - : assert(begin.children.length == end.children.length), - _children = [ - for (var i = 0; i < begin.children.length; i++) - AnimatedLayoutProperties( - begin.children[i], - end.children[i], - animation, - ), - ]; + : assert(begin.children.length == end.children.length), + _children = [ + for (var i = 0; i < begin.children.length; i++) + AnimatedLayoutProperties( + begin.children[i], + end.children[i], + animation, + ), + ]; final T begin; final T end; @@ -313,10 +318,10 @@ class AnimatedLayoutProperties final constraintsLocal = constraints!; return constraintsLocal.hasBoundedWidth ? LayoutProperties.describeAxis( - constraintsLocal.minWidth, - constraintsLocal.maxWidth, - 'w', - ) + constraintsLocal.minWidth, + constraintsLocal.maxWidth, + 'w', + ) : 'w=unconstrained'; } @@ -325,10 +330,10 @@ class AnimatedLayoutProperties final constraintsLocal = constraints!; return constraintsLocal.hasBoundedHeight ? LayoutProperties.describeAxis( - constraintsLocal.minHeight, - constraintsLocal.maxHeight, - 'h', - ) + constraintsLocal.minHeight, + constraintsLocal.maxHeight, + 'h', + ) : 'h=unconstrained'; } @@ -416,10 +421,7 @@ class AnimatedLayoutProperties } class LayoutExplorerBackground extends StatelessWidget { - const LayoutExplorerBackground({ - super.key, - required this.colorScheme, - }); + const LayoutExplorerBackground({super.key, required this.colorScheme}); final ColorScheme colorScheme; diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widget_constraints.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widget_constraints.dart index 39f9f61edf0..6dc4cc250cb 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widget_constraints.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widget_constraints.dart @@ -30,7 +30,8 @@ class VisualizeWidthAndHeightWithConstraints extends StatelessWidget { @override Widget build(BuildContext context) { final propertiesLocal = properties; - final showChildrenWidthsSum = propertiesLocal is FlexLayoutProperties && + final showChildrenWidthsSum = + propertiesLocal is FlexLayoutProperties && propertiesLocal.isOverflowWidth; final bottomHeight = widthAndConstraintIndicatorSize; final rightWidth = heightAndConstraintIndicatorSize; @@ -43,24 +44,22 @@ class VisualizeWidthAndHeightWithConstraints extends StatelessWidget { child: dimensionDescription( TextSpan( children: [ - TextSpan( - text: propertiesLocal.describeHeight(), - ), + TextSpan(text: propertiesLocal.describeHeight()), if (propertiesLocal.constraints != null) ...[ if (!showOverflowHeight) const TextSpan(text: '\n'), TextSpan( text: ' (${propertiesLocal.describeHeightConstraints()})', - style: propertiesLocal.constraints!.hasBoundedHeight || - !warnIfUnconstrained - ? null - : TextStyle( - color: colorScheme.unconstrainedColor, - ), + style: + propertiesLocal.constraints!.hasBoundedHeight || + !warnIfUnconstrained + ? null + : TextStyle(color: colorScheme.unconstrainedColor), ), ], if (showOverflowHeight) TextSpan( - text: '\nchildren take: ' + text: + '\nchildren take: ' '${toStringAsFixed(sum(propertiesLocal.childrenHeights))}', ), ], @@ -95,10 +94,7 @@ class VisualizeWidthAndHeightWithConstraints extends StatelessWidget { ), ), ), - if (displayHeightOutsideArrow) - Flexible( - child: heightDescription, - ), + if (displayHeightOutsideArrow) Flexible(child: heightDescription), ], ); }, @@ -113,15 +109,17 @@ class VisualizeWidthAndHeightWithConstraints extends StatelessWidget { if (!showChildrenWidthsSum) const TextSpan(text: '\n'), TextSpan( text: '(${propertiesLocal.describeWidthConstraints()})', - style: propertiesLocal.constraints!.hasBoundedWidth || - !warnIfUnconstrained - ? null - : TextStyle(color: colorScheme.unconstrainedColor), + style: + propertiesLocal.constraints!.hasBoundedWidth || + !warnIfUnconstrained + ? null + : TextStyle(color: colorScheme.unconstrainedColor), ), ], if (showChildrenWidthsSum) TextSpan( - text: '\nchildren take ' + text: + '\nchildren take ' '${toStringAsFixed(sum(propertiesLocal.childrenWidths))}', ), ], 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 77ca92664c6..2128ca986a9 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 @@ -5,10 +5,7 @@ import 'package:flutter/material.dart'; class WidgetTheme { - const WidgetTheme({ - this.iconAsset, - this.color = otherWidgetColor, - }); + const WidgetTheme({this.iconAsset, this.color = otherWidgetColor}); final String? iconAsset; final Color color; @@ -175,15 +172,17 @@ class WidgetTheme { 'Tab': tabTheme, 'TabBar': tabTheme, 'TabBarView': tabTheme, - 'BottomNavigationBar': - WidgetTheme(iconAsset: WidgetIcons.bottomNavigationBar), + 'BottomNavigationBar': WidgetTheme( + iconAsset: WidgetIcons.bottomNavigationBar, + ), 'CupertinoTabScaffold': tabTheme, 'CupertinoTabView': tabTheme, // Other 'Scaffold': WidgetTheme(iconAsset: WidgetIcons.scaffold), - 'CircularProgressIndicator': - WidgetTheme(iconAsset: WidgetIcons.circularProgress), + 'CircularProgressIndicator': WidgetTheme( + iconAsset: WidgetIcons.circularProgress, + ), 'Card': WidgetTheme(iconAsset: WidgetIcons.card), 'Divider': WidgetTheme(iconAsset: WidgetIcons.divider), 'AlertDialog': WidgetTheme(iconAsset: WidgetIcons.alertDialog), diff --git a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_controls.dart b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_controls.dart index 5f7b0181813..3a08faa49ca 100644 --- a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_controls.dart +++ b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_controls.dart @@ -35,10 +35,9 @@ class InspectorControls extends StatelessWidget { children: [ ValueListenableBuilder( valueListenable: serviceConnection - .serviceManager.serviceExtensionManager - .hasServiceExtension( - extensions.toggleSelectWidgetMode.extension, - ), + .serviceManager + .serviceExtensionManager + .hasServiceExtension(extensions.toggleSelectWidgetMode.extension), builder: (_, selectModeSupported, _) { return ServiceExtensionButtonGroup( fillColor: activeButtonColor, @@ -128,10 +127,7 @@ class InspectorServiceExtensionButtonGroup extends StatelessWidget { /// Toggle button that allows showing/hiding the implementation widgets in the /// widget tree. class ShowImplementationWidgetsButton extends StatelessWidget { - const ShowImplementationWidgetsButton({ - super.key, - required this.controller, - }); + const ShowImplementationWidgetsButton({super.key, required this.controller}); final v2.InspectorController controller; @@ -145,12 +141,13 @@ class ShowImplementationWidgetsButton extends StatelessWidget { isSelected: !isHidden, message: 'Show widgets created by the Flutter framework or other packages.', - label: isScreenWiderThan( - context, - InspectorControls.minScreenWidthForTextBeforeTruncating, - ) - ? 'Show Implementation Widgets' - : 'Show', + label: + isScreenWiderThan( + context, + InspectorControls.minScreenWidthForTextBeforeTruncating, + ) + ? 'Show Implementation Widgets' + : 'Show', onPressed: controller.toggleImplementationWidgetsVisibility, icon: Icons.code, minScreenWidthForTextBeforeScaling: diff --git a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart index abfd30bf3bc..d1a18dd5bde 100644 --- a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart +++ b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart @@ -46,8 +46,10 @@ class InspectorScreenSwitcher extends StatefulWidget { class _InspectorScreenSwitcherState extends State with AutoDisposeMixin, - ProvidedControllerMixin { + ProvidedControllerMixin< + InspectorScreenController, + InspectorScreenSwitcher + > { bool get shouldShowInspectorV2 => FeatureFlags.inspectorV2 && preferences.inspector.inspectorV2Enabled.value; @@ -58,10 +60,12 @@ class _InspectorScreenSwitcherState extends State if (!initController()) return; addAutoDisposeListener(preferences.inspector.inspectorV2Enabled, () async { - controller.legacyInspectorController - .setVisibleToUser(!shouldShowInspectorV2); - await controller.v2InspectorController - .setVisibleToUser(shouldShowInspectorV2); + controller.legacyInspectorController.setVisibleToUser( + !shouldShowInspectorV2, + ); + await controller.v2InspectorController.setVisibleToUser( + shouldShowInspectorV2, + ); }); } diff --git a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_settings_dialog.dart b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_settings_dialog.dart index fab1af9b773..e5efd27dc79 100644 --- a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_settings_dialog.dart +++ b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_settings_dialog.dart @@ -36,13 +36,11 @@ class FlutterInspectorSettingsDialog extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - ...dialogSubHeader( - theme, - 'General', - ), + ...dialogSubHeader(theme, 'General'), CheckboxSetting( - notifier: preferences.inspector.hoverEvalModeEnabled - as ValueNotifier, + notifier: + preferences.inspector.hoverEvalModeEnabled + as ValueNotifier, title: 'Enable hover inspection', description: 'Hovering over any widget displays its properties and values.', @@ -51,8 +49,9 @@ class FlutterInspectorSettingsDialog extends StatelessWidget { const SizedBox(height: largeSpacing), if (inspectorV2Enabled) ...[ CheckboxSetting( - notifier: preferences.inspector.autoRefreshEnabled - as ValueNotifier, + notifier: + preferences.inspector.autoRefreshEnabled + as ValueNotifier, title: 'Enable auto-refreshing of the widget tree', description: 'The widget tree will automatically be refreshed after a hot-reload.', @@ -85,15 +84,11 @@ class FlutterInspectorSettingsDialog extends StatelessWidget { style: theme.subtleTextStyle, ), const SizedBox(height: denseSpacing), - const Expanded( - child: PubRootDirectorySection(), - ), + const Expanded(child: PubRootDirectorySection()), ], ), ), - actions: const [ - DialogCloseButton(), - ], + actions: const [DialogCloseButton()], ); }, ); @@ -146,13 +141,11 @@ class InspectorDefaultDetailsViewOption extends StatelessWidget { void _onChanged(InspectorDetailsViewType? value) { if (value != null) { preferences.inspector.setDefaultInspectorDetailsView(value); - final item = value.name == InspectorDetailsViewType.layoutExplorer.name - ? gac.defaultDetailsViewToLayoutExplorer - : gac.defaultDetailsViewToWidgetDetails; - ga.select( - gac.inspector, - item, - ); + final item = + value.name == InspectorDetailsViewType.layoutExplorer.name + ? gac.defaultDetailsViewToLayoutExplorer + : gac.defaultDetailsViewToWidgetDetails; + ga.select(gac.inspector, item); } } } @@ -174,16 +167,18 @@ class PubRootDirectorySection extends StatelessWidget { entries: preferences.inspector.pubRootDirectories, textFieldLabel: 'Enter a new package directory', isRefreshing: preferences.inspector.isRefreshingPubRootDirectories, - onEntryAdded: (p0) => unawaited( - preferences.inspector.addPubRootDirectories( - [p0], - shouldCache: true, - ), - ), - onEntryRemoved: (p0) => - unawaited(preferences.inspector.removePubRootDirectories([p0])), - onRefreshTriggered: () => - unawaited(preferences.inspector.loadPubRootDirectories()), + onEntryAdded: + (p0) => unawaited( + preferences.inspector.addPubRootDirectories([ + p0, + ], shouldCache: true), + ), + onEntryRemoved: + (p0) => unawaited( + preferences.inspector.removePubRootDirectories([p0]), + ), + onRefreshTriggered: + () => unawaited(preferences.inspector.loadPubRootDirectories()), ), ); }, diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart index ed257bd74d1..e640e373eb5 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart @@ -41,26 +41,24 @@ final _log = Logger('inspector_controller'); /// Data pattern containing the properties and render properties for a widget /// tree node. -typedef WidgetTreeNodeProperties = ({ - /// Properties defined directly on the widget. - List widgetProperties, +typedef WidgetTreeNodeProperties = + ({ + /// Properties defined directly on the widget. + List widgetProperties, - /// Properties defined on the widget's render object. - List renderProperties, + /// Properties defined on the widget's render object. + List renderProperties, - /// Layout properties for the widget. - LayoutProperties? layoutProperties, -}); + /// Layout properties for the widget. + LayoutProperties? layoutProperties, + }); /// This class is based on the InspectorPanel class from the Flutter IntelliJ /// plugin with some refactors to make it more of a true controller than a view. class InspectorController extends DisposableController with AutoDisposeControllerMixin implements InspectorServiceClient { - InspectorController({ - required this.inspectorTree, - required this.treeType, - }) { + InspectorController({required this.inspectorTree, required this.treeType}) { unawaited(_init()); } @@ -112,10 +110,10 @@ class InspectorController extends DisposableController if (_supportsToggleSelectWidgetMode.value) { serviceConnection.serviceManager.serviceExtensionManager .setServiceExtensionState( - extensions.enableOnDeviceInspector.extension, - enabled: true, - value: true, - ); + extensions.enableOnDeviceInspector.extension, + enabled: true, + value: true, + ); } }); @@ -165,9 +163,10 @@ class InspectorController extends DisposableController IsolateRef? _mainIsolate; - ValueListenable get _supportsToggleSelectWidgetMode => - serviceConnection.serviceManager.serviceExtensionManager - .hasServiceExtension(extensions.toggleSelectWidgetMode.extension); + ValueListenable get _supportsToggleSelectWidgetMode => serviceConnection + .serviceManager + .serviceExtensionManager + .hasServiceExtension(extensions.toggleSelectWidgetMode.extension); Future _onClientChange(bool added) async { if (!added && _clientCount == 0) { @@ -238,9 +237,11 @@ class InspectorController extends DisposableController ValueListenable get selectedNodeProperties => _selectedNodeProperties; - final _selectedNodeProperties = ValueNotifier( - (widgetProperties: [], renderProperties: [], layoutProperties: null), - ); + final _selectedNodeProperties = ValueNotifier(( + widgetProperties: [], + renderProperties: [], + layoutProperties: null, + )); /// Whether the implementation widgets are hidden in the widget tree. ValueListenable get implementationWidgetsHidden => @@ -389,14 +390,8 @@ class InspectorController extends DisposableController if (!firstInspectorTreeLoadCompleted) { // We do not want to complete this timing operation because the force // refresh will skew the results. - ga.cancelTimingOperation( - InspectorScreen.id, - gac.pageReady, - ); - ga.select( - gac.inspector, - gac.refreshEmptyTree, - ); + ga.cancelTimingOperation(InspectorScreen.id, gac.pageReady); + ga.select(gac.inspector, gac.refreshEmptyTree); firstInspectorTreeLoadCompleted = true; } await onForceRefresh(); @@ -435,9 +430,7 @@ class InspectorController extends DisposableController // We need to start by querying the inspector service to find out the // current state of the UI. final inspectorRef = DevToolsQueryParams.load().inspectorRef; - await updateSelectionFromService( - inspectorRef: inspectorRef, - ); + await updateSelectionFromService(inspectorRef: inspectorRef); } else { if (_disposed) return; if (inspectorService is InspectorService) { @@ -506,8 +499,9 @@ class InspectorController extends DisposableController expandChildren: true, ); inspectorTree.root = rootNode; - final selectedNode = - _determineNewSelection(newSelection ?? selectedDiagnostic); + final selectedNode = _determineNewSelection( + newSelection ?? selectedDiagnostic, + ); refreshSelection(selectedNode); _implementationWidgetsHidden.value = hideImplementationWidgets; } catch (error, st) { @@ -528,8 +522,10 @@ class InspectorController extends DisposableController // TODO(https://github.com/flutter/devtools/issues/8481): Consider using a // variation of a path-finding algorithm to determine the new selection, // instead of looking for the first matching descendant. - final (closestUnchangedAncestor, distanceToAncestor) = - _findClosestUnchangedAncestor(previousSelection); + final ( + closestUnchangedAncestor, + distanceToAncestor, + ) = _findClosestUnchangedAncestor(previousSelection); if (closestUnchangedAncestor == null) return inspectorTree.root?.diagnostic; const distanceOffset = 3; @@ -706,9 +702,7 @@ class InspectorController extends DisposableController unawaited(updateSelectionFromService()); } - Future updateSelectionFromService({ - String? inspectorRef, - }) async { + Future updateSelectionFromService({String? inspectorRef}) async { final selectionGroups = _selectionGroups; if (selectionGroups == null) { // Already disposed. Ignore this requested to update selection. @@ -739,8 +733,9 @@ class InspectorController extends DisposableController // user selected an implementation widget in the app while implementation // widgets are hidden in the tree. if (implementationWidgetsHidden.value && newSelection != null) { - final isInTree = - valueToInspectorTreeNode.containsKey(newSelection.valueRef); + final isInTree = valueToInspectorTreeNode.containsKey( + newSelection.valueRef, + ); final hasParent = newSelection.parent != null; final isImplementationWidget = !isInTree && !hasParent; if (isImplementationWidget) { @@ -890,15 +885,17 @@ class InspectorController extends DisposableController void _updateSelectedErrorFromNode(InspectorTreeNode? node) { final inspectorRef = node?.diagnostic?.valueRef.id; - final errors = serviceConnection.errorBadgeManager - .erroredItemsForPage(InspectorScreen.id) - .value; + final errors = + serviceConnection.errorBadgeManager + .erroredItemsForPage(InspectorScreen.id) + .value; // Check whether the node that was just selected has any errors associated // with it. - var errorIndex = inspectorRef != null - ? errors.keys.toList().indexOf(inspectorRef) - : null; + var errorIndex = + inspectorRef != null + ? errors.keys.toList().indexOf(inspectorRef) + : null; if (errorIndex == -1) { errorIndex = null; } @@ -908,8 +905,10 @@ class InspectorController extends DisposableController if (errorIndex != null) { // Mark the error as "seen" as this will render slightly differently // so the user can track which errored nodes they've viewed. - serviceConnection.errorBadgeManager - .markErrorAsRead(InspectorScreen.id, errors[inspectorRef!]!); + serviceConnection.errorBadgeManager.markErrorAsRead( + InspectorScreen.id, + errors[inspectorRef!]!, + ); // Also clear the error badge since new errors may have arrived while // the inspector was visible (normally they're cleared when visiting // the screen) and visiting an errored node seems an appropriate @@ -922,14 +921,13 @@ class InspectorController extends DisposableController void selectErrorByIndex(int index) { _selectedErrorIndex.value = index; - final errors = serviceConnection.errorBadgeManager - .erroredItemsForPage(InspectorScreen.id) - .value; + final errors = + serviceConnection.errorBadgeManager + .erroredItemsForPage(InspectorScreen.id) + .value; unawaited( - updateSelectionFromService( - inspectorRef: errors.keys.elementAt(index), - ), + updateSelectionFromService(inspectorRef: errors.keys.elementAt(index)), ); } diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_data_models.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_data_models.dart index 120f5663c66..4e865fba6d4 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_data_models.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_data_models.dart @@ -72,17 +72,18 @@ List computeRenderSizes({ } List transformToRenderSize(double largestRenderSize) => [ - for (final s in sizes) - (s - smallestSize) * - (largestRenderSize - smallestRenderSize) / - (largestSize - smallestSize) + - smallestRenderSize, - ]; + for (final s in sizes) + (s - smallestSize) * + (largestRenderSize - smallestRenderSize) / + (largestSize - smallestSize) + + smallestRenderSize, + ]; var renderSizes = transformToRenderSize(largestRenderSize); if (useMaxSizeAvailable && sum(renderSizes) < maxSizeAvailable) { - largestRenderSize = (maxSizeAvailable - n * smallestRenderSize) * + largestRenderSize = + (maxSizeAvailable - n * smallestRenderSize) * (largestSize - smallestSize) / sum([for (final s in sizes) s - smallestSize]) + smallestRenderSize; @@ -92,46 +93,46 @@ List computeRenderSizes({ } /// Data pattern containing a widget's widths or heights. -typedef WidgetSizes = ({ - /// Whether this record represents a widget's widths or heights. - SizeType type, - - /// Either the widget's left (if [type] is [SizeType.widths]) or top (if - /// [type] is [SizeType.heights]) padding. - double paddingA, - - /// Either the widget's width (if [type] is [SizeType.widths]) or height (if - /// [type] is [SizeType.heights]). - double widgetSize, - - /// Either the widget's right (if [type] is [SizeType.widths]) or bottom (if - /// [type] is [SizeType.heights]) padding. - double paddingB, -}); - -enum SizeType { - widths, - heights, -} +typedef WidgetSizes = + ({ + /// Whether this record represents a widget's widths or heights. + SizeType type, + + /// Either the widget's left (if [type] is [SizeType.widths]) or top (if + /// [type] is [SizeType.heights]) padding. + double paddingA, + + /// Either the widget's width (if [type] is [SizeType.widths]) or height (if + /// [type] is [SizeType.heights]). + double widgetSize, + + /// Either the widget's right (if [type] is [SizeType.widths]) or bottom (if + /// [type] is [SizeType.heights]) padding. + double paddingB, + }); + +enum SizeType { widths, heights } // TODO(albertusangga): Move this to [RemoteDiagnosticsNode] once dart:html app is removed /// Represents parsed layout information for a specific [RemoteDiagnosticsNode]. class LayoutProperties { LayoutProperties(this.node, {int copyLevel = 1}) - : description = node.description, - size = node.size!, - constraints = node.constraints, - isFlex = node.isFlex, - flexFactor = node.flexFactor, - flexFit = node.flexFit, - children = copyLevel == 0 - ? [] - : node.childrenNow - .where((child) => child.size != null) - .map( - (child) => LayoutProperties(child, copyLevel: copyLevel - 1), - ) - .toList(growable: false) { + : description = node.description, + size = node.size!, + constraints = node.constraints, + isFlex = node.isFlex, + flexFactor = node.flexFactor, + flexFit = node.flexFit, + children = + copyLevel == 0 + ? [] + : node.childrenNow + .where((child) => child.size != null) + .map( + (child) => + LayoutProperties(child, copyLevel: copyLevel - 1), + ) + .toList(growable: false) { for (final child in children) { child.parent = this; } @@ -194,10 +195,10 @@ class LayoutProperties { if (constraintsLocal == null) return ''; return constraintsLocal.hasBoundedWidth ? describeAxis( - constraintsLocal.minWidth, - constraintsLocal.maxWidth, - 'w', - ) + constraintsLocal.minWidth, + constraintsLocal.maxWidth, + 'w', + ) : 'width is unconstrained'; } @@ -206,10 +207,10 @@ class LayoutProperties { if (constraintsLocal == null) return ''; return constraintsLocal.hasBoundedHeight ? describeAxis( - constraintsLocal.minHeight, - constraintsLocal.maxHeight, - 'h', - ) + constraintsLocal.minHeight, + constraintsLocal.maxHeight, + 'h', + ) : 'height is unconstrained'; } @@ -245,8 +246,9 @@ class LayoutProperties { final parentElement = node.parentRenderElement; // Fall back to this node's properties if there is no parent. if (parentElement == null) return this; - final parentProperties = - parentElement.computeLayoutProperties(forFlexLayout: false); + final parentProperties = parentElement.computeLayoutProperties( + forFlexLayout: false, + ); return parentProperties ?? this; } @@ -310,10 +312,7 @@ class LayoutProperties { /// /// See also: /// * [OverflowIndicatorPainter] -enum OverflowSide { - right, - bottom, -} +enum OverflowSide { right, bottom } // TODO(jacobr): is it possible to overflow on multiple sides? // TODO(jacobr): do we need to worry about overflowing on the left side in RTL @@ -344,10 +343,7 @@ extension MainAxisAlignmentExtension on MainAxisAlignment { /// Encapsulation of [widths] and [heights] for the layout. class LayoutWidthsAndHeights { - LayoutWidthsAndHeights({ - required this.widths, - required this.heights, - }); + LayoutWidthsAndHeights({required this.widths, required this.heights}); final WidgetSizes widths; final WidgetSizes heights; @@ -452,8 +448,9 @@ class FlexLayoutProperties extends LayoutProperties { static FlexLayoutProperties _buildNode(RemoteDiagnosticsNode node) { final renderObjectJson = node.renderObject!.json; - final properties = (renderObjectJson['properties'] as List) - .cast>(); + final properties = + (renderObjectJson['properties'] as List) + .cast>(); final data = { for (final property in properties) @@ -463,16 +460,19 @@ class FlexLayoutProperties extends LayoutProperties { return FlexLayoutProperties._fromNode( node, direction: _directionUtils.enumEntry(data['direction']) ?? Axis.vertical, - mainAxisAlignment: - _mainAxisAlignmentUtils.enumEntry(data['mainAxisAlignment']), + mainAxisAlignment: _mainAxisAlignmentUtils.enumEntry( + data['mainAxisAlignment'], + ), mainAxisSize: _mainAxisSizeUtils.enumEntry(data['mainAxisSize']), - crossAxisAlignment: - _crossAxisAlignmentUtils.enumEntry(data['crossAxisAlignment']), - textDirection: _textDirectionUtils.enumEntry(data['textDirection']) ?? + crossAxisAlignment: _crossAxisAlignmentUtils.enumEntry( + data['crossAxisAlignment'], + ), + textDirection: + _textDirectionUtils.enumEntry(data['textDirection']) ?? TextDirection.ltr, verticalDirection: _verticalDirectionUtils.enumEntry(data['verticalDirection']) ?? - VerticalDirection.down, + VerticalDirection.down, textBaseline: _textBaselineUtils.enumEntry(data['textBaseline']), ); } @@ -513,10 +513,11 @@ class FlexLayoutProperties extends LayoutProperties { num get totalFlex { if (children.isEmpty) return 0; - _totalFlex ??= children - .map((child) => child.flexFactor ?? 0) - .reduce((value, element) => value + element) - .toInt(); + _totalFlex ??= + children + .map((child) => child.flexFactor ?? 0) + .reduce((value, element) => value + element) + .toInt(); return _totalFlex!; } @@ -650,11 +651,12 @@ class FlexLayoutProperties extends LayoutProperties { ); } else { // uniform cross axis sizes. - double size = crossAxisAlignment == CrossAxisAlignment.stretch - ? maxSizeAvailable(axis) - : largestSize / - math.max(dimension(axis), 1.0) * - maxSizeAvailable(axis); + double size = + crossAxisAlignment == CrossAxisAlignment.stretch + ? maxSizeAvailable(axis) + : largestSize / + math.max(dimension(axis), 1.0) * + maxSizeAvailable(axis); size = math.max(size, smallestRenderSize(axis)); return sizes.map((_) => size).toList(); } @@ -663,9 +665,10 @@ class FlexLayoutProperties extends LayoutProperties { final widths = renderSizes(Axis.horizontal); final heights = renderSizes(Axis.vertical); - final renderFreeSpace = freeSpace > 0.0 - ? (isMainAxisHorizontal ? widths.last : heights.last) - : 0.0; + final renderFreeSpace = + freeSpace > 0.0 + ? (isMainAxisHorizontal ? widths.last : heights.last) + : 0.0; final renderLeadingSpace = leadingSpace(renderFreeSpace); final renderBetweenSpace = betweenSpace(renderFreeSpace); @@ -712,11 +715,11 @@ class FlexLayoutProperties extends LayoutProperties { for (var i = 0; i < children.length; ++i) { childrenRenderProps.add( RenderProperties( - axis: direction, - size: Size(widths[i], heights[i]), - offset: Offset.zero, - realSize: displayChildren[i].size, - ) + axis: direction, + size: Size(widths[i], heights[i]), + offset: Offset.zero, + realSize: displayChildren[i].size, + ) ..mainAxisOffset = calculateMainAxisOffset(i) ..crossAxisOffset = calculateCrossAxisOffset(i) ..layoutProperties = displayChildren[i], @@ -757,7 +760,8 @@ class FlexLayoutProperties extends LayoutProperties { displayMainAxisAlignment != MainAxisAlignment.end) { spaces.add( renderPropsWithFullCrossAxisDimension.clone() - ..mainAxisOffset = childrenRenderProps.last.mainAxisDimension + + ..mainAxisOffset = + childrenRenderProps.last.mainAxisDimension + childrenRenderProps.last.mainAxisOffset ..mainAxisDimension = renderLeadingSpace ..mainAxisRealDimension = actualLeadingSpace, @@ -795,13 +799,15 @@ class FlexLayoutProperties extends LayoutProperties { spaces.add(space.clone()..crossAxisOffset = 0.0); spaces.add( space.clone() - ..crossAxisOffset = renderProperties.crossAxisDimension + + ..crossAxisOffset = + renderProperties.crossAxisDimension + renderProperties.crossAxisOffset, ); } else { - space.crossAxisOffset = crossAxisAlignment == CrossAxisAlignment.end - ? 0 - : renderProperties.crossAxisDimension; + space.crossAxisOffset = + crossAxisAlignment == CrossAxisAlignment.end + ? 0 + : renderProperties.crossAxisDimension; spaces.add(space); } } @@ -809,18 +815,24 @@ class FlexLayoutProperties extends LayoutProperties { } static final _directionUtils = EnumUtils(Axis.values); - static final _mainAxisAlignmentUtils = - EnumUtils(MainAxisAlignment.values); - static final _mainAxisSizeUtils = - EnumUtils(MainAxisSize.values); - static final _crossAxisAlignmentUtils = - EnumUtils(CrossAxisAlignment.values); - static final _textDirectionUtils = - EnumUtils(TextDirection.values); - static final _verticalDirectionUtils = - EnumUtils(VerticalDirection.values); - static final _textBaselineUtils = - EnumUtils(TextBaseline.values); + static final _mainAxisAlignmentUtils = EnumUtils( + MainAxisAlignment.values, + ); + static final _mainAxisSizeUtils = EnumUtils( + MainAxisSize.values, + ); + static final _crossAxisAlignmentUtils = EnumUtils( + CrossAxisAlignment.values, + ); + static final _textDirectionUtils = EnumUtils( + TextDirection.values, + ); + static final _verticalDirectionUtils = EnumUtils( + VerticalDirection.values, + ); + static final _textBaselineUtils = EnumUtils( + TextBaseline.values, + ); } /// RenderProperties contains information for rendering a [LayoutProperties] node @@ -832,12 +844,12 @@ class RenderProperties { Size? realSize, this.layoutProperties, this.isFreeSpace = false, - }) : width = size?.width ?? 0.0, - height = size?.height ?? 0.0, - realWidth = realSize?.width ?? 0.0, - realHeight = realSize?.height ?? 0.0, - dx = offset?.dx ?? 0.0, - dy = offset?.dy ?? 0.0; + }) : width = size?.width ?? 0.0, + height = size?.height ?? 0.0, + realWidth = realSize?.width ?? 0.0, + realHeight = realSize?.height ?? 0.0, + dx = offset?.dx ?? 0.0, + dy = offset?.dy ?? 0.0; final Axis axis; diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart index 7adb7948a67..1cd1752ccc7 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart @@ -122,18 +122,13 @@ class InspectorScreenBodyState extends State final widgetTrees = SplitPane( axis: splitAxis, initialFractions: const [0.33, 0.67], - children: [ - inspectorTree, - WidgetDetails(controller: controller), - ], + children: [inspectorTree, WidgetDetails(controller: controller)], ); return Column( children: [ InspectorControls(controller: controller), const SizedBox(height: intermediateSpacing), - Expanded( - child: widgetTrees, - ), + Expanded(child: widgetTrees), ], ); } @@ -149,24 +144,28 @@ class InspectorScreenBodyState extends State constraints: constraints, onRefreshInspectorPressed: _refreshInspector, onSearchVisibleToggle: _onSearchVisibleToggle, - searchFieldBuilder: () => - StatelessSearchField( - controller: _inspectorTreeController, - searchFieldEnabled: true, - shouldRequestFocus: searchVisible, - supportsNavigation: true, - onClose: _onSearchVisibleToggle, - ), + searchFieldBuilder: + () => StatelessSearchField( + controller: _inspectorTreeController, + searchFieldEnabled: true, + shouldRequestFocus: searchVisible, + supportsNavigation: true, + onClose: _onSearchVisibleToggle, + ), ), Expanded( child: ValueListenableBuilder( valueListenable: serviceConnection.errorBadgeManager .erroredItemsForPage(InspectorScreen.id), builder: (_, LinkedHashMap errors, _) { - final inspectableErrors = errors.map( - (key, value) => - MapEntry(key, value as InspectableWidgetError), - ) as LinkedHashMap; + final inspectableErrors = + errors.map( + (key, value) => MapEntry( + key, + value as InspectableWidgetError, + ), + ) + as LinkedHashMap; return Stack( children: [ InspectorTree( @@ -179,15 +178,17 @@ class InspectorScreenBodyState extends State if (errors.isNotEmpty) ValueListenableBuilder( valueListenable: controller.selectedErrorIndex, - builder: (_, selectedErrorIndex, _) => Positioned( - top: 0, - right: 0, - child: ErrorNavigator( - errors: inspectableErrors, - errorIndex: selectedErrorIndex, - onSelectError: controller.selectErrorByIndex, - ), - ), + builder: + (_, selectedErrorIndex, _) => Positioned( + top: 0, + right: 0, + child: ErrorNavigator( + errors: inspectableErrors, + errorIndex: selectedErrorIndex, + onSelectError: + controller.selectErrorByIndex, + ), + ), ), ], ); @@ -253,18 +254,18 @@ class InspectorTreeControls extends StatelessWidget { ), ...!isSearchVisible ? [ - const Spacer(), - ToolbarAction( - icon: Icons.search, - onPressed: onSearchVisibleToggle, - tooltip: 'Search Tree', - ), - ] + const Spacer(), + ToolbarAction( + icon: Icons.search, + onPressed: onSearchVisibleToggle, + tooltip: 'Search Tree', + ), + ] : [ - constraints.maxWidth >= _searchBreakpoint - ? _buildSearchControls() - : const Spacer(), - ], + constraints.maxWidth >= _searchBreakpoint + ? _buildSearchControls() + : const Spacer(), + ], ToolbarAction( icon: Icons.refresh, onPressed: onRefreshInspectorPressed, @@ -274,10 +275,7 @@ class InspectorTreeControls extends StatelessWidget { ), ), if (isSearchVisible && constraints.maxWidth < _searchBreakpoint) - _controlsContainer( - context, - Row(children: [_buildSearchControls()]), - ), + _controlsContainer(context, Row(children: [_buildSearchControls()])), ], ); } @@ -286,9 +284,7 @@ class InspectorTreeControls extends StatelessWidget { return Container( height: defaultHeaderHeight, decoration: BoxDecoration( - border: Border( - bottom: defaultBorderSide(Theme.of(context)), - ), + border: Border(bottom: defaultBorderSide(Theme.of(context))), ), child: child, ); @@ -321,9 +317,10 @@ class ErrorNavigator extends StatelessWidget { @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; - final label = errorIndex != null - ? 'Error ${errorIndex! + 1}/${errors.length}' - : 'Errors: ${errors.length}'; + final label = + errorIndex != null + ? 'Error ${errorIndex! + 1}/${errors.length}' + : 'Errors: ${errors.length}'; return Container( color: colorScheme.errorContainer, child: Padding( @@ -337,9 +334,7 @@ class ErrorNavigator extends StatelessWidget { padding: const EdgeInsets.only(right: denseSpacing), child: Text( label, - style: TextStyle( - color: colorScheme.onErrorContainer, - ), + style: TextStyle(color: colorScheme.onErrorContainer), ), ), _ErrorNavigatorButton( diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_tree_controller.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_tree_controller.dart index 0c00081f93a..1c7cae337c2 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_tree_controller.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_tree_controller.dart @@ -114,11 +114,12 @@ class InspectorTreeController extends DisposableController gac.inspector, gac.inspectorTreeControllerInitialized, nonInteraction: true, - screenMetricsProvider: () => InspectorScreenMetrics.v2( - inspectorTreeControllerId: gaId, - rootSetCount: _rootSetCount, - rowCount: _rowsInTree.value.length, - ), + screenMetricsProvider: + () => InspectorScreenMetrics.v2( + inspectorTreeControllerId: gaId, + rootSetCount: _rootSetCount, + rowCount: _rowsInTree.value.length, + ), ); } @@ -161,10 +162,7 @@ class InspectorTreeController extends DisposableController set root(InspectorTreeNode? node) { if (node != null) { - _updateRows( - node: node, - updateSearchableRows: true, - ); + _updateRows(node: node, updateSearchableRows: true); } _root = node; @@ -172,11 +170,12 @@ class InspectorTreeController extends DisposableController gac.inspector, gac.inspectorTreeControllerRootChange, nonInteraction: true, - screenMetricsProvider: () => InspectorScreenMetrics.v2( - inspectorTreeControllerId: gaId, - rootSetCount: ++_rootSetCount, - rowCount: _rowsInTree.value.length, - ), + screenMetricsProvider: + () => InspectorScreenMetrics.v2( + inspectorTreeControllerId: gaId, + rootSetCount: ++_rootSetCount, + rowCount: _rowsInTree.value.length, + ), ); } @@ -321,8 +320,10 @@ class InspectorTreeController extends DisposableController final selectionLocal = selection; final diagnostic = selectionLocal?.diagnostic; - final toggledHideableGroup = - _maybeToggleHideableGroup(diagnostic, showGroup: false); + final toggledHideableGroup = _maybeToggleHideableGroup( + diagnostic, + showGroup: false, + ); if (toggledHideableGroup) return; // This logic is consistent with how IntelliJ handles tree navigation on @@ -350,8 +351,10 @@ class InspectorTreeController extends DisposableController final selectionLocal = selection; final diagnostic = selectionLocal?.diagnostic; - final toggledHideableGroup = - _maybeToggleHideableGroup(diagnostic, showGroup: true); + final toggledHideableGroup = _maybeToggleHideableGroup( + diagnostic, + showGroup: true, + ); if (toggledHideableGroup) return; // This logic is consistent with how IntelliJ handles tree navigation on @@ -371,12 +374,15 @@ class InspectorTreeController extends DisposableController refreshTree( updateTreeAction: () { - final nodeToSelect = selection == null - ? root - : rowAtIndex( - (_rowIndexFromNode(selection!) + indexOffset) - .clamp(0, _numRows - 1), - )?.node; + final nodeToSelect = + selection == null + ? root + : rowAtIndex( + (_rowIndexFromNode(selection!) + indexOffset).clamp( + 0, + _numRows - 1, + ), + )?.node; setSelectedNode(nodeToSelect); return true; }, @@ -392,7 +398,8 @@ class InspectorTreeController extends DisposableController }) { final isHideableGroupLeader = diagnostic != null && diagnostic.isHideableGroupLeader; - final shouldToggle = isHideableGroupLeader && + final shouldToggle = + isHideableGroupLeader && (showGroup ? diagnostic.groupIsHidden : !diagnostic.groupIsHidden); if (shouldToggle) { @@ -478,7 +485,8 @@ class InspectorTreeController extends DisposableController index: currentIdx, ticks: ticks, depth: depth, - lineToParent: !node.isProperty && + lineToParent: + !node.isProperty && currentIdx != 0 && node.parent!.showLinesToChildren, hasSingleChild: node.children.length == 1, @@ -491,7 +499,8 @@ class InspectorTreeController extends DisposableController final parentDepth = depth; final childrenDepth = children.length > 1 ? parentDepth + 1 : parentDepth; for (final child in children) { - final shouldAddTick = children.length > 1 && + final shouldAddTick = + children.length > 1 && children.last != child && !children.last.isProperty && node.diagnostic?.shouldIndent == true; @@ -499,10 +508,7 @@ class InspectorTreeController extends DisposableController buildRowsHelper( child, depth: childrenDepth, - ticks: [ - ...ticks, - if (shouldAddTick) parentDepth, - ], + ticks: [...ticks, if (shouldAddTick) parentDepth], ); } } @@ -542,10 +548,7 @@ class InspectorTreeController extends DisposableController void onSelectNode(InspectorTreeNode? node) { setSelectedNode(node); - ga.select( - gac.inspector, - gac.treeNodeSelection, - ); + ga.select(gac.inspector, gac.treeNodeSelection); final diagnostic = node?.diagnostic; if (diagnostic != null && diagnostic.groupIsHidden) { diagnostic.hideableGroupLeader?.toggleHiddenGroup(); @@ -658,8 +661,9 @@ class InspectorTreeController extends DisposableController if (diagnosticsNode.hasChildren || diagnosticsNode.inlineProperties.isNotEmpty) { if (diagnosticsNode.childrenReady || !diagnosticsNode.hasChildren) { - final styleIsMultiline = - expandPropertiesByDefault(diagnosticsNode.style); + final styleIsMultiline = expandPropertiesByDefault( + diagnosticsNode.style, + ); setupChildren( diagnosticsNode, node, @@ -730,12 +734,7 @@ class InspectorTreeController extends DisposableController try { final children = await diagnostic.children; if (treeNode.hasPlaceholderChildren || treeNode.children.isEmpty) { - setupChildren( - diagnostic, - treeNode, - children, - expandChildren: true, - ); + setupChildren(diagnostic, treeNode, children, expandChildren: true); refreshTree( updateTreeAction: () { nodeChanged(treeNode); @@ -776,8 +775,9 @@ class InspectorTreeController extends DisposableController if (searchPreviousMatches) { final previousMatches = searchMatches.value; for (final previousMatch in previousMatches) { - if (previousMatch.node.diagnostic!.searchValue - .caseInsensitiveContains(search)) { + if (previousMatch.node.diagnostic!.searchValue.caseInsensitiveContains( + search, + )) { matches.add(previousMatch); } } @@ -792,21 +792,17 @@ class InspectorTreeController extends DisposableController if (search.isEmpty || inspectorService == null || inspectorService.isDisposed) { - assert( - () { - debugPrint('Search completed, no search'); - return true; - }(), - ); + assert(() { + debugPrint('Search completed, no search'); + return true; + }()); return matches; } - assert( - () { - debugPrint('Search started: $_searchTarget'); - return true; - }(), - ); + assert(() { + debugPrint('Search started: $_searchTarget'); + return true; + }()); for (final row in _searchableCachedRows) { final diagnostic = row!.node.diagnostic; @@ -823,14 +819,12 @@ class InspectorTreeController extends DisposableController // Widget search end } - assert( - () { - debugPrint( - 'Search completed with $debugStatsWidgets widgets, $debugStatsSearchOps ops', - ); - return true; - }(), - ); + assert(() { + debugPrint( + 'Search completed with $debugStatsWidgets widgets, $debugStatsSearchOps ops', + ); + return true; + }()); return matches; } @@ -950,21 +944,21 @@ class _InspectorTreeState extends State } // TODO(devoncarew): Commented out as per flutter/devtools/pull/2001. -// void _onScrollYChange() { -// if (controller == null) return; -// -// // If the vertical position is already being animated we should not trigger -// // a new animation of the horizontal position as a more direct animation of -// // the horizontal position has already been triggered. -// if (currentAnimateY != null) return; -// -// final x = _computeTargetX(_scrollControllerY.offset); -// _scrollControllerX.animateTo( -// x, -// duration: defaultDuration, -// curve: defaultCurve, -// ); -// } + // void _onScrollYChange() { + // if (controller == null) return; + // + // // If the vertical position is already being animated we should not trigger + // // a new animation of the horizontal position as a more direct animation of + // // the horizontal position has already been triggered. + // if (currentAnimateY != null) return; + // + // final x = _computeTargetX(_scrollControllerY.offset); + // _scrollControllerX.animateTo( + // x, + // duration: defaultDuration, + // curve: defaultCurve, + // ); + // } @override Future waitForClientsThenScrollToRect( @@ -988,12 +982,14 @@ class _InspectorTreeState extends State final initialX = rect.left; final initialY = rect.top; - final yOffsetAtViewportTop = _scrollControllerY.hasClients - ? _scrollControllerY.offset - : _scrollControllerY.initialScrollOffset; - final xOffsetAtViewportLeft = _scrollControllerX.hasClients - ? _scrollControllerX.offset - : _scrollControllerX.initialScrollOffset; + final yOffsetAtViewportTop = + _scrollControllerY.hasClients + ? _scrollControllerY.offset + : _scrollControllerY.initialScrollOffset; + final xOffsetAtViewportLeft = + _scrollControllerX.hasClients + ? _scrollControllerX.offset + : _scrollControllerX.initialScrollOffset; final viewPortInScrollControllerSpace = Rect.fromLTWH( xOffsetAtViewportLeft, @@ -1008,8 +1004,9 @@ class _InspectorTreeState extends State (rect.centerLeft.dx + rect.center.dx) / 2, rect.center.dy, ); - final isRectInViewPort = - viewPortInScrollControllerSpace.contains(centerLeftHalf); + final isRectInViewPort = viewPortInScrollControllerSpace.contains( + centerLeftHalf, + ); if (isRectInViewPort) { // The rect is already in view, don't scroll return; @@ -1079,9 +1076,7 @@ class _InspectorTreeState extends State /// Pad [initialY] so that a row would be placed in the vertical center of /// the screen. - double _padTargetY({ - required double initialY, - }) { + double _padTargetY({required double initialY}) { return initialY - (safeViewportHeight / 2) + inspectorRowHeight / 2; } @@ -1158,7 +1153,8 @@ class _InspectorTreeState extends State controller: _scrollControllerX, child: ConstrainedBox( constraints: BoxConstraints( - maxWidth: treeControllerLocal.rowWidth + + maxWidth: + treeControllerLocal.rowWidth + treeControllerLocal.maxRowIndent, ), // TODO(kenz): this scrollbar needs to be sticky to the right side of @@ -1179,29 +1175,29 @@ class _InspectorTreeState extends State offsetControllerViewportDimension: viewportWidth, child: ListView.custom( itemExtent: inspectorRowHeight, - childrenDelegate: SliverChildBuilderDelegate( - (context, index) { - if (index == rows.length) { - return SizedBox(height: inspectorRowHeight); - } - final row = - treeControllerLocal.rowAtIndex(index)!; - final inspectorRef = - row.node.diagnostic?.valueRef.id; - return _InspectorTreeRowWidget( - key: PageStorageKey(row.node), - inspectorTreeState: this, - row: row, - scrollControllerX: _scrollControllerX, - viewportWidth: viewportWidth, - error: widget.widgetErrors != null && - inspectorRef != null - ? widget.widgetErrors![inspectorRef] - : null, - ); - }, - childCount: rows.length + 1, - ), + childrenDelegate: SliverChildBuilderDelegate(( + context, + index, + ) { + if (index == rows.length) { + return SizedBox(height: inspectorRowHeight); + } + final row = treeControllerLocal.rowAtIndex(index)!; + final inspectorRef = + row.node.diagnostic?.valueRef.id; + return _InspectorTreeRowWidget( + key: PageStorageKey(row.node), + inspectorTreeState: this, + row: row, + scrollControllerX: _scrollControllerX, + viewportWidth: viewportWidth, + error: + widget.widgetErrors != null && + inspectorRef != null + ? widget.widgetErrors![inspectorRef] + : null, + ); + }, childCount: rows.length + 1), controller: _scrollControllerY, ), ), @@ -1222,9 +1218,10 @@ class _InspectorTreeState extends State bool get wantKeepAlive => true; } -Paint _defaultPaint(ColorScheme colorScheme) => Paint() - ..color = colorScheme.treeGuidelineColor - ..strokeWidth = chartLineStrokeWidth; +Paint _defaultPaint(ColorScheme colorScheme) => + Paint() + ..color = colorScheme.treeGuidelineColor + ..strokeWidth = chartLineStrokeWidth; /// The distance (on the x-axis) between the expand/collapse and the start of /// the row, as determined by a percentage of the [inspectorColumnIndent]. @@ -1269,7 +1266,8 @@ class _RowPainter extends CustomPainter { final distanceFromExpandCollapseToRowStart = inspectorColumnIndent * _expandCollapseToRowStartXDistancePercentage; for (final tick in row.ticks) { - final expandCollapseX = _controller.getDepthIndent(tick) - + final expandCollapseX = + _controller.getDepthIndent(tick) - distanceFromExpandCollapseToRowStart; // Draw a vertical line for each tick identifying a connection between // an ancestor of this node and some other node in the tree. @@ -1282,11 +1280,13 @@ class _RowPainter extends CustomPainter { // If this row is itself connected to a parent then draw the L shaped line // to make that connection. if (row.lineToParent) { - final parentExpandCollapseX = _controller.getDepthIndent(row.depth - 1) - + final parentExpandCollapseX = + _controller.getDepthIndent(row.depth - 1) - distanceFromExpandCollapseToRowStart; - final width = showExpandCollapse - ? inspectorColumnIndent * 0.6 - : inspectorColumnIndent; + final width = + showExpandCollapse + ? inspectorColumnIndent * 0.6 + : inspectorColumnIndent; canvas.drawLine( Offset(parentExpandCollapseX, 0.0), Offset(parentExpandCollapseX, inspectorRowHeight * 0.5), @@ -1310,13 +1310,15 @@ class _RowPainter extends CustomPainter { final subordinates = node.diagnostic?.hideableGroupSubordinates ?? []; final groupIsHidden = node.diagnostic?.groupIsHidden ?? false; - final lastHiddenSubordinateHasNoChildren = groupIsHidden && + final lastHiddenSubordinateHasNoChildren = + groupIsHidden && subordinates.isNotEmpty && subordinates.last.childrenNow.isEmpty; if (expandedWithSingleChild && !lastHiddenSubordinateHasNoChildren) { final distanceFromIconCenterToRowStart = inspectorColumnIndent * _iconCenterToRowStartXDistancePercentage; - final iconCenterX = _controller.getDepthIndent(row.depth) - + final iconCenterX = + _controller.getDepthIndent(row.depth) - distanceFromIconCenterToRowStart; // Draw a line from the bottom of the current row's icon to the top of the // child row's icon: @@ -1389,9 +1391,10 @@ class InspectorRowContent extends StatelessWidget { Color? backgroundColor; if (row.isSelected) { - backgroundColor = hasError - ? colorScheme.errorContainer - : colorScheme.selectedRowBackgroundColor; + backgroundColor = + hasError + ? colorScheme.errorContainer + : colorScheme.selectedRowBackgroundColor; } final node = row.node; @@ -1410,19 +1413,16 @@ class InspectorRowContent extends StatelessWidget { children: [ node.showExpandCollapse ? InkWell( - onTap: onToggle, - child: RotationTransition( - turns: expandArrowAnimation, - child: Icon( - Icons.expand_more, - size: defaultIconSize, - ), - ), - ) - : const SizedBox( - width: expandCollapseWidth, - height: defaultSpacing, + onTap: onToggle, + child: RotationTransition( + turns: expandArrowAnimation, + child: Icon(Icons.expand_more, size: defaultIconSize), ), + ) + : const SizedBox( + width: expandCollapseWidth, + height: defaultSpacing, + ), Expanded( child: Container( color: backgroundColor, @@ -1450,30 +1450,32 @@ class InspectorRowContent extends StatelessWidget { nodeDescriptionHighlightStyle: searchValue.isEmpty || !row.isSearchMatch ? DiagnosticsTextStyles.regular( - Theme.of(context).colorScheme, - ) + Theme.of(context).colorScheme, + ) : row.isSelected - ? theme.searchMatchHighlightStyleFocused - : theme.searchMatchHighlightStyle, - actionLabel: isHideableGroupLeader - ? diagnostic!.groupIsHidden - ? '(expand)' - : '(collapse)' - : null, - actionCallback: isHideableGroupLeader - ? () { - controller.refreshTree( - updateTreeAction: () { - controller.toggleHiddenGroup(node); - return true; - }, - ); - } - : null, - customDescription: isHideableGroupLeader && - diagnostic!.groupIsHidden - ? '${diagnostic.hideableGroupSubordinates!.length + 1} more widgets...' - : null, + ? theme.searchMatchHighlightStyleFocused + : theme.searchMatchHighlightStyle, + actionLabel: + isHideableGroupLeader + ? diagnostic!.groupIsHidden + ? '(expand)' + : '(collapse)' + : null, + actionCallback: + isHideableGroupLeader + ? () { + controller.refreshTree( + updateTreeAction: () { + controller.toggleHiddenGroup(node); + return true; + }, + ); + } + : null, + customDescription: + isHideableGroupLeader && diagnostic!.groupIsHidden + ? '${diagnostic.hideableGroupSubordinates!.length + 1} more widgets...' + : null, customIconName: isHideableGroupLeader && diagnostic!.groupIsHidden ? 'HiddenGroup' @@ -1492,8 +1494,10 @@ class InspectorRowContent extends StatelessWidget { // Wrap with tooltip if there is an error for this node's widget. if (hasError) { - rowWidget = - DevToolsTooltip(message: error!.errorMessage, child: rowWidget); + rowWidget = DevToolsTooltip( + message: error!.errorMessage, + child: rowWidget, + ); } return CustomPaint( diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/box/box.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/box/box.dart index d221d7a1f35..21cb5c90544 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/box/box.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/box/box.dart @@ -180,11 +180,7 @@ class BoxLayoutExplorerWidget extends StatelessWidget { Container( width: constraints.maxWidth, height: constraints.maxHeight, - decoration: BoxDecoration( - border: Border.all( - color: widgetColor, - ), - ), + decoration: BoxDecoration(border: Border.all(color: widgetColor)), child: Stack( children: [ ..._paddingWidgets( @@ -354,9 +350,10 @@ WidgetSizes _simpleFractionalLayout({ final paddingASize = sizes.paddingA; final paddingBSize = sizes.paddingB; - final paddingFraction = paddingASize > 0 && paddingBSize > 0 - ? _narrowPaddingVisualizerPercent - : _widePaddingVisualizerPercent; + final paddingFraction = + paddingASize > 0 && paddingBSize > 0 + ? _narrowPaddingVisualizerPercent + : _widePaddingVisualizerPercent; final paddingAFraction = paddingASize > 0 ? paddingFraction : 0.0; final paddingBFraction = paddingBSize > 0 ? paddingFraction : 0.0; diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/flex/flex.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/flex/flex.dart index c63b04b882d..5a0a0b75a61 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/flex/flex.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/flex/flex.dart @@ -29,10 +29,7 @@ import 'utils.dart'; double get alignmentDropdownMaxSize => scaleByFontFactor(140.0); class FlexLayoutExplorerWidget extends LayoutExplorerWidget { - const FlexLayoutExplorerWidget( - super.inspectorController, { - super.key, - }); + const FlexLayoutExplorerWidget(super.inspectorController, {super.key}); static bool shouldDisplay(RemoteDiagnosticsNode node) { return (node.isFlex) || (node.parent?.isFlex ?? false); @@ -43,8 +40,12 @@ class FlexLayoutExplorerWidget extends LayoutExplorerWidget { FlexLayoutExplorerWidgetState(); } -class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< - FlexLayoutExplorerWidget, FlexLayoutProperties> { +class FlexLayoutExplorerWidgetState + extends + LayoutExplorerWidgetState< + FlexLayoutExplorerWidget, + FlexLayoutProperties + > { final scrollController = ScrollController(); Axis get direction => properties!.direction; @@ -57,9 +58,10 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< ? colorScheme.mainAxisColor : colorScheme.crossAxisColor; - Color verticalColor(ColorScheme colorScheme) => properties!.isMainAxisVertical - ? colorScheme.mainAxisColor - : colorScheme.crossAxisColor; + Color verticalColor(ColorScheme colorScheme) => + properties!.isMainAxisVertical + ? colorScheme.mainAxisColor + : colorScheme.crossAxisColor; Color horizontalTextColor(ColorScheme colorScheme) => properties!.isMainAxisHorizontal @@ -120,9 +122,10 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< Widget _buildAxisAlignmentDropdown(Axis axis, ThemeData theme) { final colorScheme = theme.colorScheme; - final color = axis == direction - ? colorScheme.mainAxisTextColor - : colorScheme.crossAxisTextColor; + final color = + axis == direction + ? colorScheme.mainAxisTextColor + : colorScheme.crossAxisTextColor; List alignmentEnumEntries; Object? selected; final propertiesLocal = properties!; @@ -150,9 +153,10 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< isExpanded: true, // Avoid showing an underline for the main axis and cross-axis drop downs. underline: const SizedBox(), - iconEnabledColor: axis == propertiesLocal.direction - ? colorScheme.mainAxisColor - : colorScheme.crossAxisColor, + iconEnabledColor: + axis == propertiesLocal.direction + ? colorScheme.mainAxisColor + : colorScheme.crossAxisColor, selectedItemBuilder: (context) { return [ for (final alignment in alignmentEnumEntries) @@ -173,13 +177,13 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< child: Image.asset( (axis == direction) ? mainAxisAssetImageUrl( - direction, - alignment as MainAxisAlignment, - ) + direction, + alignment as MainAxisAlignment, + ) : crossAxisAssetImageUrl( - direction, - alignment as CrossAxisAlignment, - ), + direction, + alignment as CrossAxisAlignment, + ), height: axisAlignmentAssetImageHeight, fit: BoxFit.fitHeight, color: color, @@ -212,13 +216,13 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< child: Image.asset( (axis == direction) ? mainAxisAssetImageUrl( - direction, - alignment as MainAxisAlignment, - ) + direction, + alignment as MainAxisAlignment, + ) : crossAxisAssetImageUrl( - direction, - alignment as CrossAxisAlignment, - ), + direction, + alignment as CrossAxisAlignment, + ), fit: BoxFit.fitHeight, color: color, ), @@ -234,13 +238,14 @@ class FlexLayoutExplorerWidgetState extends LayoutExplorerWidgetState< // if the axis is the main axis the type should be [MainAxisAlignment] // if the axis is the cross axis the type should be [CrossAxisAlignment] FlexLayoutProperties changedProperties; - changedProperties = axis == direction - ? propertiesLocal.copyWith( - mainAxisAlignment: newSelection as MainAxisAlignment?, - ) - : propertiesLocal.copyWith( - crossAxisAlignment: newSelection as CrossAxisAlignment?, - ); + changedProperties = + axis == direction + ? propertiesLocal.copyWith( + mainAxisAlignment: newSelection as MainAxisAlignment?, + ) + : propertiesLocal.copyWith( + crossAxisAlignment: newSelection as CrossAxisAlignment?, + ); final valueRef = propertiesLocal.node.valueRef; markAsDirty(); await objectGroup!.invokeSetFlexProperties( @@ -450,9 +455,7 @@ class _VisualizeFlexChildrenState extends State { final contents = Container( decoration: BoxDecoration( - border: Border.all( - color: theme.primaryColorLight, - ), + border: Border.all(color: theme.primaryColorLight), ), margin: const EdgeInsets.only(top: margin, left: margin), child: LayoutBuilder( @@ -464,21 +467,23 @@ class _VisualizeFlexChildrenState extends State { return axis == Axis.horizontal ? maxWidth : maxHeight; } - final childrenAndMainAxisSpacesRenderProps = - widget.properties.childrenRenderProperties( - smallestRenderWidth: minRenderWidth, - largestRenderWidth: defaultMaxRenderWidth, - smallestRenderHeight: minRenderHeight, - largestRenderHeight: defaultMaxRenderHeight, - maxSizeAvailable: maxSizeAvailable, - ); - - final renderProperties = childrenAndMainAxisSpacesRenderProps - .where((renderProps) => !renderProps.isFreeSpace) - .toList(); - final mainAxisSpaces = childrenAndMainAxisSpacesRenderProps - .where((renderProps) => renderProps.isFreeSpace) - .toList(); + final childrenAndMainAxisSpacesRenderProps = widget.properties + .childrenRenderProperties( + smallestRenderWidth: minRenderWidth, + largestRenderWidth: defaultMaxRenderWidth, + smallestRenderHeight: minRenderHeight, + largestRenderHeight: defaultMaxRenderHeight, + maxSizeAvailable: maxSizeAvailable, + ); + + final renderProperties = + childrenAndMainAxisSpacesRenderProps + .where((renderProps) => !renderProps.isFreeSpace) + .toList(); + final mainAxisSpaces = + childrenAndMainAxisSpacesRenderProps + .where((renderProps) => renderProps.isFreeSpace) + .toList(); final crossAxisSpaces = widget.properties.crossAxisSpaces( childrenRenderProperties: renderProperties, maxSizeAvailable: maxSizeAvailable, @@ -524,22 +529,27 @@ class _VisualizeFlexChildrenState extends State { scrollDirection: widget.properties.direction, controller: widget.scrollController, child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: maxWidth, - minHeight: maxHeight, - maxWidth: widget.direction == Axis.horizontal - ? sum( - childrenAndMainAxisSpacesRenderProps - .map((renderSize) => renderSize.width), - ) - : maxWidth, - maxHeight: widget.direction == Axis.vertical - ? sum( - childrenAndMainAxisSpacesRenderProps - .map((renderSize) => renderSize.height), - ) - : maxHeight, - ).normalize(), + constraints: + BoxConstraints( + minWidth: maxWidth, + minHeight: maxHeight, + maxWidth: + widget.direction == Axis.horizontal + ? sum( + childrenAndMainAxisSpacesRenderProps.map( + (renderSize) => renderSize.width, + ), + ) + : maxWidth, + maxHeight: + widget.direction == Axis.vertical + ? sum( + childrenAndMainAxisSpacesRenderProps.map( + (renderSize) => renderSize.height, + ), + ) + : maxHeight, + ).normalize(), child: Stack( children: [ LayoutExplorerBackground(colorScheme: colorScheme), @@ -597,10 +607,7 @@ class FlexChildVisualizer extends StatelessWidget { void onChangeFlexFit(FlexFit? newFlexFit) async { state.markAsDirty(); - await objectGroup!.invokeSetFlexFit( - properties.node.valueRef, - newFlexFit!, - ); + await objectGroup!.invokeSetFlexFit(properties.node.valueRef, newFlexFit!); } Widget _buildFlexFactorChangerDropdown( @@ -612,9 +619,10 @@ class FlexChildVisualizer extends StatelessWidget { Widget buildMenuitemChild(int? flexFactor) { return Text( 'flex: $flexFactor', - style: flexFactor == propertiesLocal.flexFactor - ? theme.boldTextStyle.copyWith(color: emphasizedTextColor) - : theme.regularTextStyleWithColor(emphasizedTextColor), + style: + flexFactor == propertiesLocal.flexFactor + ? theme.boldTextStyle.copyWith(color: emphasizedTextColor) + : theme.regularTextStyleWithColor(emphasizedTextColor), ); } @@ -639,9 +647,9 @@ class FlexChildVisualizer extends StatelessWidget { Widget _buildFlexFitChangerDropdown(ThemeData theme) { Widget flexFitDescription(FlexFit flexFit) => Text( - 'fit: ${flexFit.name}', - style: theme.regularTextStyleWithColor(emphasizedTextColor), - ); + 'fit: ${flexFit.name}', + style: theme.regularTextStyleWithColor(emphasizedTextColor), + ); final propertiesLocal = properties; @@ -674,14 +682,13 @@ class FlexChildVisualizer extends StatelessWidget { // TODO(https://github.com/flutter/devtools/issues/4058) allow more dynamic // flex factor input final currentFlexFactor = properties.flexFactor?.toInt() ?? 0; - final currentMaxFlexFactor = - math.max(currentFlexFactor, maximumFlexFactorOptions); + final currentMaxFlexFactor = math.max( + currentFlexFactor, + maximumFlexFactorOptions, + ); return Container( - margin: const EdgeInsets.only( - top: margin, - left: margin, - ), + margin: const EdgeInsets.only(top: margin, left: margin), child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -719,15 +726,20 @@ class FlexChildVisualizer extends StatelessWidget { final horizontal = rootLocal.isMainAxisHorizontal; late Size size; - size = propertiesLocal.hasFlexFactor - ? SizeTween( - begin: Size( - horizontal ? minRenderWidth - entranceMargin : renderSize.width, - vertical ? minRenderHeight - entranceMargin : renderSize.height, - ), - end: renderSize, - ).evaluate(state.entranceCurve)! - : renderSize; + size = + propertiesLocal.hasFlexFactor + ? SizeTween( + begin: Size( + horizontal + ? minRenderWidth - entranceMargin + : renderSize.width, + vertical + ? minRenderHeight - entranceMargin + : renderSize.height, + ), + end: renderSize, + ).evaluate(state.entranceCurve)! + : renderSize; // Not-expanded widgets enter much faster. return Opacity( opacity: min([state.entranceCurve.value * 5, 1.0]), diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/flex/utils.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/flex/utils.dart index 26792d0166a..15f318b34c1 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/flex/utils.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/flex/utils.dart @@ -23,11 +23,7 @@ String mainAxisAssetImageUrl(Axis direction, MainAxisAlignment alignment) { class AnimatedFlexLayoutProperties extends AnimatedLayoutProperties implements FlexLayoutProperties { - AnimatedFlexLayoutProperties( - super.begin, - super.end, - super.animation, - ); + AnimatedFlexLayoutProperties(super.begin, super.end, super.animation); @override CrossAxisAlignment? get crossAxisAlignment => end.crossAxisAlignment; @@ -85,7 +81,8 @@ class AnimatedFlexLayoutProperties } @override - double get crossAxisDimension => lerpDouble( + double get crossAxisDimension => + lerpDouble( begin.crossAxisDimension, end.crossAxisDimension, animation.value, @@ -119,7 +116,8 @@ class AnimatedFlexLayoutProperties bool get isMainAxisVertical => end.isMainAxisVertical; @override - double get mainAxisDimension => lerpDouble( + double get mainAxisDimension => + lerpDouble( begin.mainAxisDimension, end.mainAxisDimension, animation.value, diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/arrow.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/arrow.dart index 766de8a7d0b..8f6c9d94849 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/arrow.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/arrow.dart @@ -11,16 +11,12 @@ const defaultArrowColor = Colors.white; const defaultArrowStrokeWidth = 2.0; const defaultDistanceToArrow = 4.0; -enum ArrowType { - up, - left, - right, - down, -} +enum ArrowType { up, left, right, down } -Axis axis(ArrowType type) => (type == ArrowType.up || type == ArrowType.down) - ? Axis.vertical - : Axis.horizontal; +Axis axis(ArrowType type) => + (type == ArrowType.up || type == ArrowType.down) + ? Axis.vertical + : Axis.horizontal; /// Widget that draws a bidirectional arrow around another widget. /// @@ -35,12 +31,12 @@ class ArrowWrapper extends StatelessWidget { double? arrowHeadSize, this.arrowStrokeWidth = defaultArrowStrokeWidth, this.childMarginFromArrow = defaultDistanceToArrow, - }) : assert(childMarginFromArrow > 0.0), - direction = axis(type), - isBidirectional = false, - startArrowType = type, - endArrowType = type, - arrowHeadSize = arrowHeadSize ?? defaultIconSize; + }) : assert(childMarginFromArrow > 0.0), + direction = axis(type), + isBidirectional = false, + startArrowType = type, + endArrowType = type, + arrowHeadSize = arrowHeadSize ?? defaultIconSize; const ArrowWrapper.bidirectional({ super.key, @@ -50,13 +46,13 @@ class ArrowWrapper extends StatelessWidget { required this.arrowHeadSize, this.arrowStrokeWidth = defaultArrowStrokeWidth, this.childMarginFromArrow = defaultDistanceToArrow, - }) : assert(arrowHeadSize >= 0.0), - assert(childMarginFromArrow >= 0.0), - isBidirectional = true, - startArrowType = - direction == Axis.horizontal ? ArrowType.left : ArrowType.up, - endArrowType = - direction == Axis.horizontal ? ArrowType.right : ArrowType.down; + }) : assert(arrowHeadSize >= 0.0), + assert(childMarginFromArrow >= 0.0), + isBidirectional = true, + startArrowType = + direction == Axis.horizontal ? ArrowType.left : ArrowType.up, + endArrowType = + direction == Axis.horizontal ? ArrowType.right : ArrowType.down; final Color arrowColor; final double arrowHeadSize; @@ -96,10 +92,11 @@ class ArrowWrapper extends StatelessWidget { headSize: arrowHeadSize, strokeWidth: arrowStrokeWidth, type: startArrowType, - shouldDrawHead: isBidirectional - ? true - : (startArrowType == ArrowType.left || - startArrowType == ArrowType.up), + shouldDrawHead: + isBidirectional + ? true + : (startArrowType == ArrowType.left || + startArrowType == ArrowType.up), ), ), ), @@ -115,10 +112,11 @@ class ArrowWrapper extends StatelessWidget { headSize: arrowHeadSize, strokeWidth: arrowStrokeWidth, type: endArrowType, - shouldDrawHead: isBidirectional - ? true - : (endArrowType == ArrowType.right || - endArrowType == ArrowType.down), + shouldDrawHead: + isBidirectional + ? true + : (endArrowType == ArrowType.right || + endArrowType == ArrowType.down), ), ), ), @@ -137,15 +135,15 @@ class ArrowWidget extends StatelessWidget { this.shouldDrawHead = true, this.strokeWidth = defaultArrowStrokeWidth, required this.type, - }) : assert(headSize > 0.0), - assert(strokeWidth > 0.0), - _painter = _ArrowPainter( - headSize: headSize, - color: color, - strokeWidth: strokeWidth, - type: type, - shouldDrawHead: shouldDrawHead, - ); + }) : assert(headSize > 0.0), + assert(strokeWidth > 0.0), + _painter = _ArrowPainter( + headSize: headSize, + color: color, + strokeWidth: strokeWidth, + type: type, + shouldDrawHead: shouldDrawHead, + ); final Color color; @@ -162,10 +160,7 @@ class ArrowWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return CustomPaint( - painter: _painter, - child: Container(), - ); + return CustomPaint(painter: _painter, child: Container()); } } @@ -177,7 +172,7 @@ class _ArrowPainter extends CustomPainter { this.shouldDrawHead = true, required this.type, }) : // the height of an equilateral triangle - headHeight = 0.5 * sqrt(3) * headSize; + headHeight = 0.5 * sqrt(3) * headSize; final Color color; final double headSize; @@ -204,9 +199,10 @@ class _ArrowPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - final paint = Paint() - ..color = color - ..strokeWidth = strokeWidth; + final paint = + Paint() + ..color = color + ..strokeWidth = strokeWidth; final originX = size.width / 2, originY = size.height / 2; Offset lineStartingPoint = Offset.zero; @@ -239,11 +235,12 @@ class _ArrowPainter extends CustomPainter { p3 = Offset(originX + headSizeDividedBy2, startingY); break; } - final path = Path() - ..moveTo(p1.dx, p1.dy) - ..lineTo(p2.dx, p2.dy) - ..lineTo(p3.dx, p3.dy) - ..close(); + final path = + Path() + ..moveTo(p1.dx, p1.dy) + ..lineTo(p2.dx, p2.dy) + ..lineTo(p3.dx, p3.dy) + ..close(); canvas.drawPath(path, paint); switch (type) { @@ -281,10 +278,6 @@ class _ArrowPainter extends CustomPainter { break; } } - canvas.drawLine( - lineStartingPoint, - lineEndingPoint, - paint, - ); + canvas.drawLine(lineStartingPoint, lineEndingPoint, paint); } } diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/dimension.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/dimension.dart index dbf3e3f2365..c59af1efeb2 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/dimension.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/dimension.dart @@ -15,9 +15,10 @@ Widget dimensionDescription( final text = Text.rich( description, textAlign: TextAlign.center, - style: overflow - ? overflowingDimensionIndicatorTextStyle(colorScheme) - : dimensionIndicatorTextStyle, + style: + overflow + ? overflowingDimensionIndicatorTextStyle(colorScheme) + : dimensionIndicatorTextStyle, overflow: TextOverflow.ellipsis, ); if (overflow) { diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/free_space.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/free_space.dart index 25b9c20d493..81482e5f844 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/free_space.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/free_space.dart @@ -12,10 +12,7 @@ import 'dimension.dart'; import 'theme.dart'; class FreeSpaceVisualizerWidget extends StatelessWidget { - const FreeSpaceVisualizerWidget( - this.renderProperties, { - super.key, - }); + const FreeSpaceVisualizerWidget(this.renderProperties, {super.key}); final RenderProperties renderProperties; @@ -32,9 +29,7 @@ class FreeSpaceVisualizerWidget extends StatelessWidget { children: [ Flexible( child: dimensionDescription( - TextSpan( - text: widthDescription, - ), + TextSpan(text: widthDescription), false, colorScheme, ), @@ -108,9 +103,7 @@ class PaddingVisualizerWidget extends StatelessWidget { children: [ Flexible( child: dimensionDescription( - TextSpan( - text: widthDescription, - ), + TextSpan(text: widthDescription), false, colorScheme, ), diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/layout_explorer_widget.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/layout_explorer_widget.dart index 17cb72b3e8f..c799b4030cc 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/layout_explorer_widget.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/layout_explorer_widget.dart @@ -20,17 +20,17 @@ const maxRequestsPerSecond = 3.0; /// Base class for layout widgets for all widget types. abstract class LayoutExplorerWidget extends StatefulWidget { - const LayoutExplorerWidget( - this.inspectorController, { - super.key, - }); + const LayoutExplorerWidget(this.inspectorController, {super.key}); final InspectorController inspectorController; } /// Base class for state objects for layout widgets for all widget types. -abstract class LayoutExplorerWidgetState extends State +abstract class LayoutExplorerWidgetState< + W extends LayoutExplorerWidget, + L extends LayoutProperties +> + extends State with TickerProviderStateMixin implements InspectorServiceClient { LayoutExplorerWidgetState() { @@ -128,8 +128,9 @@ abstract class LayoutExplorerWidgetState[black, yellow, yellow, black], - [0.25, 0.25, 0.75, 0.75], - TileMode.repeated, - ); + static final indicatorPaint = + Paint() + ..shader = ui.Gradient.linear( + const Offset(0.0, 0.0), + const Offset(10.0, 10.0), + [black, yellow, yellow, black], + [0.25, 0.25, 0.75, 0.75], + TileMode.repeated, + ); @override void paint(Canvas canvas, Size size) { diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/theme.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/theme.dart index 24ab3f574c1..76f44d1db04 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/theme.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/theme.dart @@ -133,12 +133,7 @@ Widget buildUnderline() { return Container( height: 1.0, decoration: const BoxDecoration( - border: Border( - bottom: BorderSide( - color: textColor, - width: 0.0, - ), - ), + border: Border(bottom: BorderSide(color: textColor, width: 0.0)), ), ); } diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/utils.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/utils.dart index f151ce7b9d3..4be0064fc83 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/utils.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/utils.dart @@ -33,12 +33,12 @@ class BorderLayout extends StatelessWidget { this.bottomHeight, this.center, }) : assert( - left != null || - top != null || - right != null || - bottom != null || - center != null, - ); + left != null || + top != null || + right != null || + bottom != null || + center != null, + ); final Widget? center; final Widget? top; @@ -161,17 +161,19 @@ class WidgetVisualizer extends StatelessWidget { width: isSelected ? _borderSelectedWidth : _borderUnselectedWidth, ), - color: isSelected - ? theme.canvasColor.brighten() - : theme.canvasColor.darken(), - boxShadow: isSelected - ? [ - BoxShadow( - color: Colors.black.withAlpha(255 ~/ 2), - blurRadius: 10, - ), - ] - : null, + color: + isSelected + ? theme.canvasColor.brighten() + : theme.canvasColor.darken(), + boxShadow: + isSelected + ? [ + BoxShadow( + color: Colors.black.withAlpha(255 ~/ 2), + blurRadius: 10, + ), + ] + : null, ), child: Stack( children: [ @@ -186,26 +188,29 @@ class WidgetVisualizer extends StatelessWidget { ), Container( margin: EdgeInsets.only( - right: overflowSide == OverflowSide.right - ? _overflowIndicatorSize - : 0.0, - bottom: overflowSide == OverflowSide.bottom - ? _overflowIndicatorSize - : 0.0, + right: + overflowSide == OverflowSide.right + ? _overflowIndicatorSize + : 0.0, + bottom: + overflowSide == OverflowSide.bottom + ? _overflowIndicatorSize + : 0.0, ), - child: isFlex - ? FlexWidgetVisualizer( - title: title, - largeTitle: largeTitle, - borderColor: borderColor, - hint: hint, - child: child, - ) - : BoxWidgetVisualizer( - borderColor: borderColor, - title: title, - properties: properties, - ), + child: + isFlex + ? FlexWidgetVisualizer( + title: title, + largeTitle: largeTitle, + borderColor: borderColor, + hint: hint, + child: child, + ) + : BoxWidgetVisualizer( + borderColor: borderColor, + title: title, + properties: properties, + ), ), ], ), @@ -251,9 +256,10 @@ class FlexWidgetVisualizer extends StatelessWidget { Flexible( child: Container( constraints: BoxConstraints( - maxWidth: largeTitle - ? defaultMaxRenderWidth - : minRenderWidth * widgetTitleMaxWidthPercentage, + maxWidth: + largeTitle + ? defaultMaxRenderWidth + : minRenderWidth * widgetTitleMaxWidthPercentage, ), decoration: BoxDecoration(color: borderColor), padding: const EdgeInsets.all(densePadding), @@ -298,12 +304,7 @@ class BoxWidgetVisualizer extends StatelessWidget { return Column( mainAxisSize: MainAxisSize.min, children: [ - Center( - child: WidgetLabel( - labelColor: borderColor, - labelText: title, - ), - ), + Center(child: WidgetLabel(labelColor: borderColor, labelText: title)), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -354,9 +355,7 @@ class WidgetLabel extends StatelessWidget { ), child: Text( labelText, - style: theme.regularTextStyleWithColor( - colorScheme.widgetNameColor, - ), + style: theme.regularTextStyleWithColor(colorScheme.widgetNameColor), overflow: TextOverflow.ellipsis, ), ); @@ -366,15 +365,15 @@ class WidgetLabel extends StatelessWidget { class AnimatedLayoutProperties implements LayoutProperties { AnimatedLayoutProperties(this.begin, this.end, this.animation) - : assert(begin.children.length == end.children.length), - _children = [ - for (var i = 0; i < begin.children.length; i++) - AnimatedLayoutProperties( - begin.children[i], - end.children[i], - animation, - ), - ]; + : assert(begin.children.length == end.children.length), + _children = [ + for (var i = 0; i < begin.children.length; i++) + AnimatedLayoutProperties( + begin.children[i], + end.children[i], + animation, + ), + ]; final T begin; final T end; @@ -446,10 +445,10 @@ class AnimatedLayoutProperties final constraintsLocal = constraints!; return constraintsLocal.hasBoundedWidth ? LayoutProperties.describeAxis( - constraintsLocal.minWidth, - constraintsLocal.maxWidth, - 'w', - ) + constraintsLocal.minWidth, + constraintsLocal.maxWidth, + 'w', + ) : 'w=unconstrained'; } @@ -458,10 +457,10 @@ class AnimatedLayoutProperties final constraintsLocal = constraints!; return constraintsLocal.hasBoundedHeight ? LayoutProperties.describeAxis( - constraintsLocal.minHeight, - constraintsLocal.maxHeight, - 'h', - ) + constraintsLocal.minHeight, + constraintsLocal.maxHeight, + 'h', + ) : 'h=unconstrained'; } @@ -549,10 +548,7 @@ class AnimatedLayoutProperties } class LayoutExplorerBackground extends StatelessWidget { - const LayoutExplorerBackground({ - super.key, - required this.colorScheme, - }); + const LayoutExplorerBackground({super.key, required this.colorScheme}); final ColorScheme colorScheme; @@ -598,15 +594,17 @@ class PositionedBackgroundLabel extends StatelessWidget { Widget build(BuildContext context) { return Column( // Push to the bottom if there is no padding on the top. - mainAxisAlignment: !hasTopPadding && hasBottomPadding - ? MainAxisAlignment.end - : MainAxisAlignment.start, + mainAxisAlignment: + !hasTopPadding && hasBottomPadding + ? MainAxisAlignment.end + : MainAxisAlignment.start, children: [ Row( // Push to the right if there is no padding on the left. - mainAxisAlignment: (!hasLeftPadding && hasRightPadding) - ? MainAxisAlignment.end - : MainAxisAlignment.start, + mainAxisAlignment: + (!hasLeftPadding && hasRightPadding) + ? MainAxisAlignment.end + : MainAxisAlignment.start, children: [ Flexible( child: WidgetLabel( diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/widget_constraints.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/widget_constraints.dart index f3dc52dba5d..593f9fcb092 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/widget_constraints.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/widget_constraints.dart @@ -30,7 +30,8 @@ class VisualizeWidthAndHeightWithConstraints extends StatelessWidget { @override Widget build(BuildContext context) { final propertiesLocal = properties; - final showChildrenWidthsSum = propertiesLocal is FlexLayoutProperties && + final showChildrenWidthsSum = + propertiesLocal is FlexLayoutProperties && propertiesLocal.isOverflowWidth; final bottomHeight = widthAndConstraintIndicatorSize; final rightWidth = heightAndConstraintIndicatorSize; @@ -43,24 +44,22 @@ class VisualizeWidthAndHeightWithConstraints extends StatelessWidget { child: dimensionDescription( TextSpan( children: [ - TextSpan( - text: propertiesLocal.describeHeight(), - ), + TextSpan(text: propertiesLocal.describeHeight()), if (propertiesLocal.constraints != null) ...[ if (!showOverflowHeight) const TextSpan(text: '\n'), TextSpan( text: ' (${propertiesLocal.describeHeightConstraints()})', - style: propertiesLocal.constraints!.hasBoundedHeight || - !warnIfUnconstrained - ? null - : TextStyle( - color: colorScheme.unconstrainedColor, - ), + style: + propertiesLocal.constraints!.hasBoundedHeight || + !warnIfUnconstrained + ? null + : TextStyle(color: colorScheme.unconstrainedColor), ), ], if (showOverflowHeight) TextSpan( - text: '\nchildren take: ' + text: + '\nchildren take: ' '${toStringAsFixed(sum(propertiesLocal.childrenHeights))}', ), ], @@ -95,10 +94,7 @@ class VisualizeWidthAndHeightWithConstraints extends StatelessWidget { ), ), ), - if (displayHeightOutsideArrow) - Flexible( - child: heightDescription, - ), + if (displayHeightOutsideArrow) Flexible(child: heightDescription), ], ); }, @@ -113,15 +109,17 @@ class VisualizeWidthAndHeightWithConstraints extends StatelessWidget { if (!showChildrenWidthsSum) const TextSpan(text: '\n'), TextSpan( text: '(${propertiesLocal.describeWidthConstraints()})', - style: propertiesLocal.constraints!.hasBoundedWidth || - !warnIfUnconstrained - ? null - : TextStyle(color: colorScheme.unconstrainedColor), + style: + propertiesLocal.constraints!.hasBoundedWidth || + !warnIfUnconstrained + ? null + : TextStyle(color: colorScheme.unconstrainedColor), ), ], if (showChildrenWidthsSum) TextSpan( - text: '\nchildren take ' + text: + '\nchildren take ' '${toStringAsFixed(sum(propertiesLocal.childrenWidths))}', ), ], diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/widgets_theme.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/widgets_theme.dart index 4f560406a46..1b620543f71 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/widgets_theme.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/widgets_theme.dart @@ -5,10 +5,7 @@ import 'package:flutter/material.dart'; class WidgetTheme { - const WidgetTheme({ - this.iconAsset, - this.color = otherWidgetColor, - }); + const WidgetTheme({this.iconAsset, this.color = otherWidgetColor}); final String? iconAsset; final Color color; @@ -175,15 +172,17 @@ class WidgetTheme { 'Tab': tabTheme, 'TabBar': tabTheme, 'TabBarView': tabTheme, - 'BottomNavigationBar': - WidgetTheme(iconAsset: WidgetIcons.bottomNavigationBar), + 'BottomNavigationBar': WidgetTheme( + iconAsset: WidgetIcons.bottomNavigationBar, + ), 'CupertinoTabScaffold': tabTheme, 'CupertinoTabView': tabTheme, // Other 'Scaffold': WidgetTheme(iconAsset: WidgetIcons.scaffold), - 'CircularProgressIndicator': - WidgetTheme(iconAsset: WidgetIcons.circularProgress), + 'CircularProgressIndicator': WidgetTheme( + iconAsset: WidgetIcons.circularProgress, + ), 'Card': WidgetTheme(iconAsset: WidgetIcons.card), 'Divider': WidgetTheme(iconAsset: WidgetIcons.divider), 'AlertDialog': WidgetTheme(iconAsset: WidgetIcons.alertDialog), diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/widget_properties/properties_view.dart b/packages/devtools_app/lib/src/screens/inspector_v2/widget_properties/properties_view.dart index d1e9282d618..501a5eb962c 100644 --- a/packages/devtools_app/lib/src/screens/inspector_v2/widget_properties/properties_view.dart +++ b/packages/devtools_app/lib/src/screens/inspector_v2/widget_properties/properties_view.dart @@ -163,12 +163,11 @@ class _DetailsTableState extends State { List _getTabsInOrder({ required bool renderTabExists, required bool flexExplorerTabExists, - }) => - [ - _widgetPropertiesTab, - if (renderTabExists) _renderObjectTab, - if (flexExplorerTabExists) _flexExplorerTab, - ]; + }) => [ + _widgetPropertiesTab, + if (renderTabExists) _renderObjectTab, + if (flexExplorerTabExists) _flexExplorerTab, + ]; } /// Displays a widget's properties, including the layout properties and a @@ -243,7 +242,8 @@ class _PropertiesViewState extends State { return LayoutBuilder( builder: (context, constraints) { - final horizontalLayout = constraints.maxWidth > + final horizontalLayout = + constraints.maxWidth > (PropertiesView.layoutExplorerWidth * PropertiesView.scaleFactorForVerticalLayout); @@ -275,9 +275,10 @@ class _PropertiesViewState extends State { ), if (layoutPropertiesList != null) Padding( - padding: horizontalLayout - ? const EdgeInsets.only(left: largeSpacing) - : const EdgeInsets.only(bottom: largeSpacing), + padding: + horizontalLayout + ? const EdgeInsets.only(left: largeSpacing) + : const EdgeInsets.only(bottom: largeSpacing), child: layoutPropertiesList, ), ], @@ -345,9 +346,9 @@ class LayoutPropertiesList extends StatelessWidget { LayoutWidthsAndHeights? get widthsAndHeights => widgetHeights != null && widgetWidths != null ? LayoutWidthsAndHeights( - widths: widgetWidths!, - heights: widgetHeights!, - ) + widths: widgetWidths!, + heights: widgetHeights!, + ) : null; @override @@ -370,34 +371,16 @@ class LayoutPropertiesList extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - LayoutPropertyItem( - name: 'height', - value: widgetHeight, - ), - LayoutPropertyItem( - name: 'width', - value: widgetWidth, - ), + LayoutPropertyItem(name: 'height', value: widgetHeight), + LayoutPropertyItem(name: 'width', value: widgetWidth), if (hasTopPadding) - LayoutPropertyItem( - name: 'top padding', - value: topPadding, - ), + LayoutPropertyItem(name: 'top padding', value: topPadding), if (hasBottomPadding) - LayoutPropertyItem( - name: 'bottom padding', - value: bottomPadding, - ), + LayoutPropertyItem(name: 'bottom padding', value: bottomPadding), if (hasLeftPadding) - LayoutPropertyItem( - name: 'left padding', - value: leftPadding, - ), + LayoutPropertyItem(name: 'left padding', value: leftPadding), if (hasRightPadding) - LayoutPropertyItem( - name: 'right padding', - value: rightPadding, - ), + LayoutPropertyItem(name: 'right padding', value: rightPadding), ], ); } @@ -424,10 +407,7 @@ class LayoutPropertyItem extends StatelessWidget { text: '$name: ', style: theme.subtleTextStyle, children: [ - TextSpan( - text: toStringAsFixed(value), - style: theme.fixedFontStyle, - ), + TextSpan(text: toStringAsFixed(value), style: theme.fixedFontStyle), ], ), ), @@ -455,10 +435,7 @@ class PropertiesTable extends StatelessWidget { controller: scrollController, itemCount: properties.length, itemBuilder: (context, index) { - return PropertyItem( - index: index, - properties: properties, - ); + return PropertyItem(index: index, properties: properties); }, ), ); @@ -519,10 +496,7 @@ class PropertyItem extends StatelessWidget { /// A widget property's name. class PropertyName extends StatelessWidget { - const PropertyName({ - super.key, - required this.property, - }); + const PropertyName({super.key, required this.property}); final RemoteDiagnosticsNode property; @@ -539,10 +513,7 @@ class PropertyName extends StatelessWidget { /// A widget property's value. class PropertyValue extends StatelessWidget { - const PropertyValue({ - super.key, - required this.property, - }); + const PropertyValue({super.key, required this.property}); final RemoteDiagnosticsNode property; @@ -561,10 +532,7 @@ class PropertyValue extends StatelessWidget { /// Wraps a text widget with the correct amount of padding for the table. class PaddedText extends StatelessWidget { - const PaddedText({ - super.key, - required this.child, - }); + const PaddedText({super.key, required this.child}); final Widget child; diff --git a/packages/devtools_app/lib/src/screens/logging/_log_details.dart b/packages/devtools_app/lib/src/screens/logging/_log_details.dart index f0c75763b8d..02f285ed4b9 100644 --- a/packages/devtools_app/lib/src/screens/logging/_log_details.dart +++ b/packages/devtools_app/lib/src/screens/logging/_log_details.dart @@ -21,8 +21,9 @@ class LogDetails extends StatefulWidget { @override State createState() => _LogDetailsState(); - static const copyToClipboardButtonKey = - Key('log_details_copy_to_clipboard_button'); + static const copyToClipboardButtonKey = Key( + 'log_details_copy_to_clipboard_button', + ); } class _LogDetailsState extends State @@ -85,17 +86,18 @@ class _LogDetailsState extends State controller: scrollController, child: SingleChildScrollView( controller: scrollController, - child: preferences.logging.detailsFormat.value == - LoggingDetailsFormat.text || - (log?.encodedDetails ?? '').isEmpty - ? Padding( - padding: const EdgeInsets.all(denseSpacing), - child: SelectableText( - log?.prettyPrinted() ?? '', - textAlign: TextAlign.left, - ), - ) - : JsonViewer(encodedJson: log!.encodedDetails), + child: + preferences.logging.detailsFormat.value == + LoggingDetailsFormat.text || + (log?.encodedDetails ?? '').isEmpty + ? Padding( + padding: const EdgeInsets.all(denseSpacing), + child: SelectableText( + log?.prettyPrinted() ?? '', + textAlign: TextAlign.left, + ), + ) + : JsonViewer(encodedJson: log!.encodedDetails), ), ), ); @@ -149,22 +151,19 @@ class LogDetailsFormatButton extends StatelessWidget { return currentlyUsingTextFormat ? Padding( - // This padding aligns this button with the copy button. - padding: const EdgeInsets.only(bottom: borderPadding), - child: SmallAction( - tooltip: tooltip, - onPressed: togglePreference, - child: Text( - ' { } ', - style: Theme.of(context).regularTextStyle, - ), - ), - ) - : ToolbarAction( - icon: Icons.text_fields, + // This padding aligns this button with the copy button. + padding: const EdgeInsets.only(bottom: borderPadding), + child: SmallAction( tooltip: tooltip, onPressed: togglePreference, - size: defaultIconSize, - ); + child: Text(' { } ', style: Theme.of(context).regularTextStyle), + ), + ) + : ToolbarAction( + icon: Icons.text_fields, + tooltip: tooltip, + onPressed: togglePreference, + size: defaultIconSize, + ); } } diff --git a/packages/devtools_app/lib/src/screens/logging/_message_column.dart b/packages/devtools_app/lib/src/screens/logging/_message_column.dart index 9027f332e44..0c12b9ecbf9 100644 --- a/packages/devtools_app/lib/src/screens/logging/_message_column.dart +++ b/packages/devtools_app/lib/src/screens/logging/_message_column.dart @@ -76,10 +76,7 @@ class MessageColumn extends ColumnData theme.regularTextStyle, ), if (hasSummary && hasDetails()) - TextSpan( - text: ' • ', - style: theme.subtleTextStyle, - ), + TextSpan(text: ' • ', style: theme.subtleTextStyle), if (hasDetails()) ...processAnsiTerminalCodes( detailsComputed ? data.details! : '', diff --git a/packages/devtools_app/lib/src/screens/logging/_when_column.dart b/packages/devtools_app/lib/src/screens/logging/_when_column.dart index 7cd1c2684c6..c9a872b8c73 100644 --- a/packages/devtools_app/lib/src/screens/logging/_when_column.dart +++ b/packages/devtools_app/lib/src/screens/logging/_when_column.dart @@ -8,11 +8,7 @@ import '../../shared/table/table_data.dart'; import 'logging_controller.dart'; class WhenColumn extends ColumnData { - WhenColumn() - : super( - 'When', - fixedWidthPx: scaleByFontFactor(80), - ); + WhenColumn() : super('When', fixedWidthPx: scaleByFontFactor(80)); @override bool get supportsSorting => false; @@ -24,14 +20,18 @@ class WhenColumn extends ColumnData { int getValue(LogData dataObject) => dataObject.timestamp ?? -1; @override - String getDisplayValue(LogData dataObject) => dataObject.timestamp == null - ? '' - : timeFormat - .format(DateTime.fromMillisecondsSinceEpoch(dataObject.timestamp!)); + String getDisplayValue(LogData dataObject) => + dataObject.timestamp == null + ? '' + : timeFormat.format( + DateTime.fromMillisecondsSinceEpoch(dataObject.timestamp!), + ); @override - String getTooltip(LogData dataObject) => dataObject.timestamp == null - ? '' - : dateTimeFormat - .format(DateTime.fromMillisecondsSinceEpoch(dataObject.timestamp!)); + String getTooltip(LogData dataObject) => + dataObject.timestamp == null + ? '' + : dateTimeFormat.format( + DateTime.fromMillisecondsSinceEpoch(dataObject.timestamp!), + ); } 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 a3e1a2b3a3e..9471bac08d3 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart @@ -37,14 +37,11 @@ final dateTimeFormat = DateFormat('HH:mm:ss.SSS (MM/dd/yy)'); bool _verboseDebugging = false; -typedef OnShowDetails = void Function({ - String? text, - InspectorTreeController? tree, -}); +typedef OnShowDetails = + void Function({String? text, InspectorTreeController? tree}); -typedef CreateLoggingTree = InspectorTreeController Function({ - VoidCallback? onSelectionChange, -}); +typedef CreateLoggingTree = + InspectorTreeController Function({VoidCallback? onSelectionChange}); typedef ZoneDescription = ({String? name, int? identityHashCode}); @@ -96,14 +93,10 @@ class LoggingController extends DisposableController _handleConnectionStart(serviceConnection.serviceManager.service!); autoDisposeStreamSubscription( - serviceConnection.serviceManager.service!.onIsolateEvent - .listen((event) { - messageBus.addEvent( - BusEvent( - 'debugger', - data: event, - ), - ); + serviceConnection.serviceManager.service!.onIsolateEvent.listen(( + event, + ) { + messageBus.addEvent(BusEvent('debugger', data: event)); }), ); } @@ -136,8 +129,9 @@ class LoggingController extends DisposableController SettingFilter( id: _minLogLevelFilterId, name: 'Hide logs below the minimum log level', - includeCallback: (LogData element, int currentFilterValue) => - element.level >= currentFilterValue, + includeCallback: + (LogData element, int currentFilterValue) => + element.level >= currentFilterValue, enabledCallback: (int filterValue) => filterValue > Level.ALL.value, possibleValues: _possibleLogLevels.map((l) => l.value).toList(), possibleValueDisplays: _possibleLogLevels.map((l) => l.name).toList(), @@ -147,18 +141,26 @@ class LoggingController extends DisposableController true) ...[ ToggleFilter( id: _verboseFlutterFrameworkFilterId, - name: 'Hide verbose Flutter framework logs (initialization, frame ' + name: + 'Hide verbose Flutter framework logs (initialization, frame ' 'times, image sizes)', - includeCallback: (log) => !_verboseFlutterFrameworkLogKinds - .any((kind) => kind.caseInsensitiveEquals(log.kind)), + includeCallback: + (log) => + !_verboseFlutterFrameworkLogKinds.any( + (kind) => kind.caseInsensitiveEquals(log.kind), + ), defaultValue: true, ), ToggleFilter( id: _verboseFlutterServiceFilterId, - name: 'Hide verbose Flutter service logs (service extension state ' + name: + 'Hide verbose Flutter service logs (service extension state ' 'changes)', - includeCallback: (log) => !_verboseFlutterServiceLogKinds - .any((kind) => kind.caseInsensitiveEquals(log.kind)), + includeCallback: + (log) => + !_verboseFlutterServiceLogKinds.any( + (kind) => kind.caseInsensitiveEquals(log.kind), + ), defaultValue: true, ), ], @@ -171,8 +173,8 @@ class LoggingController extends DisposableController ]; static final _possibleLogLevels = Level.LEVELS - // Omit Level.OFF from the possible minimum levels. - .where((level) => level != Level.OFF); + // Omit Level.OFF from the possible minimum levels. + .where((level) => level != Level.OFF); static const _kindFilterId = 'logging-kind-filter'; static const _isolateFilterId = 'logging-isolate-filter'; @@ -245,9 +247,11 @@ class LoggingController extends DisposableController String label; - label = totalCount == showingCount - ? nf.format(totalCount) - : 'showing ${nf.format(showingCount)} of ' '${nf.format(totalCount)}'; + label = + totalCount == showingCount + ? nf.format(totalCount) + : 'showing ${nf.format(showingCount)} of ' + '${nf.format(totalCount)}'; label = '$label ${pluralize('event', totalCount)}'; @@ -349,8 +353,9 @@ class LoggingController extends DisposableController ), ); } else if (e.extensionKind == FlutterEvent.serviceExtensionStateChanged) { - final changedInfo = - ServiceExtensionStateChangedInfo.from(e.extensionData!.data); + final changedInfo = ServiceExtensionStateChangedInfo.from( + e.extensionData!.data, + ); log( LogData( @@ -412,7 +417,8 @@ class LoggingController extends DisposableController final time = ((newSpace.time! + oldSpace.time!) * 1000).round(); - final summary = '${isolateRef['name']} • ' + final summary = + '${isolateRef['name']} • ' '${e.json!['reason']} collection in $time ms • ' '${printBytes(usedBytes, unit: ByteUnit.mb, includeUnit: true)} used of ' '${printBytes(capacityBytes, unit: ByteUnit.mb, includeUnit: true)}'; @@ -442,8 +448,9 @@ class LoggingController extends DisposableController final logRecord = _LogRecord(eventJson['logRecord']); - String? loggerName = - _valueAsString(InstanceRef.parse(logRecord.loggerName)); + String? loggerName = _valueAsString( + InstanceRef.parse(logRecord.loggerName), + ); if (loggerName == null || loggerName.isEmpty) { loggerName = 'log'; } @@ -477,16 +484,22 @@ class LoggingController extends DisposableController _isNotNull(stackTrace)) { detailsComputer = () async { // Get the full string value of the message. - String result = - await _retrieveFullStringValue(service, e.isolate!, messageRef); + String result = await _retrieveFullStringValue( + service, + e.isolate!, + messageRef, + ); // Get information about the error object. Some users of the // dart:developer log call may pass a data payload in the `error` // field, encoded as a json encoded string, so handle that case. if (_isNotNull(error)) { if (error!.valueAsString != null) { - final errorString = - await _retrieveFullStringValue(service, e.isolate!, error); + final errorString = await _retrieveFullStringValue( + service, + e.isolate!, + error, + ); result += '\n\n$errorString'; } else { // Call `toString()` on the error object and display that. @@ -703,7 +716,8 @@ class LoggingController extends DisposableController final queryFilter = filter.queryFilter; if (!queryFilter.isEmpty) { final filteredOutByQueryFilterArgument = queryFilter - .filterArguments.values + .filterArguments + .values .any((argument) => !argument.matchesValue(log)); if (filteredOutByQueryFilterArgument) return false; @@ -722,17 +736,20 @@ class LoggingController extends DisposableController final zone = log.zone; final matchesZoneName = zone?.name?.caseInsensitiveContains(substring) ?? false; - final matchesZoneIdentity = zone?.identityHashCode - ?.toString() - .caseInsensitiveContains(substring) ?? + final matchesZoneIdentity = + zone?.identityHashCode?.toString().caseInsensitiveContains( + substring, + ) ?? false; if (matchesZoneName || matchesZoneIdentity) return true; - final matchesSummary = log.summary != null && + final matchesSummary = + log.summary != null && log.summary!.caseInsensitiveContains(substring); if (matchesSummary) return true; - final matchesDetails = log.details != null && + final matchesDetails = + log.details != null && log.details!.caseInsensitiveContains(substring); if (matchesDetails) return true; } @@ -884,17 +901,15 @@ class LogData with SearchableDataMixin { final originalDetails = _details; // Fetch details immediately on creation. unawaited( - compute().catchError( - (Object? error) { - // On error, set the value of details to its original value. - _details = originalDetails; - _detailsComputed.value = true; - error_handling.reportError( - 'Error fetching details for $kind log' - '${error != null ? ': $error' : ''}.', - ); - }, - ), + compute().catchError((Object? error) { + // On error, set the value of details to its original value. + _details = originalDetails; + _detailsComputed.value = true; + error_handling.reportError( + 'Error fetching details for $kind log' + '${error != null ? ': $error' : ''}.', + ); + }), ); } diff --git a/packages/devtools_app/lib/src/screens/logging/logging_controls.dart b/packages/devtools_app/lib/src/screens/logging/logging_controls.dart index 880dfee8a72..e6f939aef4a 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_controls.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_controls.dart @@ -38,14 +38,15 @@ class LoggingControls extends StatelessWidget { // TODO(kenz): fix focus issue when state is refreshed child: ValueListenableBuilder( valueListenable: controller.filteredData, - builder: (context, _, _) => SearchField( - searchFieldWidth: - isScreenWiderThan(context, _loggingMinVerboseWidth) - ? wideSearchFieldWidth - : defaultSearchFieldWidth, - searchController: controller, - searchFieldEnabled: controller.filteredData.value.isNotEmpty, - ), + builder: + (context, _, _) => SearchField( + searchFieldWidth: + isScreenWiderThan(context, _loggingMinVerboseWidth) + ? wideSearchFieldWidth + : defaultSearchFieldWidth, + searchController: controller, + searchFieldEnabled: controller.filteredData.value.isNotEmpty, + ), ), ), const SizedBox(width: denseSpacing), @@ -57,9 +58,10 @@ class LoggingControls extends StatelessWidget { ), const SizedBox(width: denseSpacing), CopyToClipboardControl( - dataProvider: () => controller.filteredData.value - .map((e) => '${e.timestamp} [${e.kind}] ${e.prettyPrinted()}') - .joinWithTrailing('\n'), + dataProvider: + () => controller.filteredData.value + .map((e) => '${e.timestamp} [${e.kind}] ${e.prettyPrinted()}') + .joinWithTrailing('\n'), tooltip: 'Copy filtered logs', ), const SizedBox(width: denseSpacing), @@ -91,8 +93,9 @@ class LoggingSettingsDialog extends StatefulWidget { class _LoggingSettingsDialogState extends State { static const _retentionLimitHeight = 48.0; - final temporaryRetentionLimit = - ValueNotifier(preferences.logging.retentionLimit.value); + final temporaryRetentionLimit = ValueNotifier( + preferences.logging.retentionLimit.value, + ); @override void dispose() { @@ -112,7 +115,8 @@ class _LoggingSettingsDialogState extends State { height: _retentionLimitHeight, child: PositiveIntegerSetting( title: 'Limit for the number of logs retained.', - subTitle: 'Once the limit is reached, the first ' + subTitle: + 'Once the limit is reached, the first ' '$defaultLogBufferReductionSize logs will be dropped.', notifier: temporaryRetentionLimit, minimumValue: defaultLogBufferReductionSize, 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 965c484b3e0..4beb4c1cd04 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_screen.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_screen.dart @@ -79,9 +79,10 @@ class _LoggingScreenState extends State Expanded( child: SplitPane( axis: splitAxis, - initialFractions: splitAxis == Axis.vertical - ? const [0.8, 0.2] - : const [0.7, 0.3], + initialFractions: + splitAxis == Axis.vertical + ? const [0.8, 0.2] + : const [0.7, 0.3], children: [ RoundedOutlinedBorder( clip: true, diff --git a/packages/devtools_app/lib/src/screens/logging/metadata.dart b/packages/devtools_app/lib/src/screens/logging/metadata.dart index b74d2874fb3..925b57a89df 100644 --- a/packages/devtools_app/lib/src/screens/logging/metadata.dart +++ b/packages/devtools_app/lib/src/screens/logging/metadata.dart @@ -161,13 +161,15 @@ abstract class MetadataChip extends StatelessWidget { decoration: BoxDecoration( color: backgroundColor, borderRadius: BorderRadius.circular(_borderRadius), - border: outlined - ? Border.all(color: theme.colorScheme.subtleTextColor) - : null, + border: + outlined + ? Border.all(color: theme.colorScheme.subtleTextColor) + : null, ), - margin: includeLeadingMargin - ? const EdgeInsets.only(left: denseSpacing) - : null, + margin: + includeLeadingMargin + ? const EdgeInsets.only(left: denseSpacing) + : null, padding: const EdgeInsets.symmetric( horizontal: horizontalPadding, vertical: verticalPadding, @@ -323,9 +325,10 @@ class ZoneChip extends MetadataChip { super.foregroundColor, super.outlined = false, }) : super( - text: name, - tooltip: identityHashCode != null - ? 'Zone identityHashCode: $identityHashCode' - : null, - ); + text: name, + tooltip: + identityHashCode != null + ? 'Zone identityHashCode: $identityHashCode' + : null, + ); } diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 79457d188e2..c9a30b9595f 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -34,10 +34,7 @@ class MemoryController extends DisposableController @visibleForTesting ProfilePaneController? connectedProfile, }) { unawaited( - _init( - connectedDiff: connectedDiff, - connectedProfile: connectedProfile, - ), + _init(connectedDiff: connectedDiff, connectedProfile: connectedProfile), ); } @@ -115,11 +112,13 @@ class MemoryController extends DisposableController chart = MemoryChartPaneController(data: offlineData?.chart ?? ChartData()); - final rootPackage = isConnected - ? serviceConnection.serviceManager.rootInfoNow().package! - : null; + final rootPackage = + isConnected + ? serviceConnection.serviceManager.rootInfoNow().package! + : null; - diff = diffPaneController ?? + diff = + diffPaneController ?? offlineData?.diff ?? DiffPaneController( loader: @@ -127,7 +126,8 @@ class MemoryController extends DisposableController rootPackage: rootPackage, ); - profile = profilePaneController ?? + profile = + profilePaneController ?? offlineData?.profile ?? ProfilePaneController(rootPackage: rootPackage!); @@ -172,9 +172,7 @@ class MemoryController extends DisposableController }); diff.core.classFilter.addListener(() { - theProfile.setFilter( - diff.core.classFilter.value, - ); + theProfile.setFilter(diff.core.classFilter.value); }); } @@ -186,7 +184,11 @@ class MemoryController extends DisposableController try { await serviceConnection.serviceManager.service!.getAllocationProfile( (serviceConnection - .serviceManager.isolateManager.selectedIsolate.value?.id)!, + .serviceManager + .isolateManager + .selectedIsolate + .value + ?.id)!, gc: true, ); chart.data.timeline.addGCEvent(); diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart index 399d155e460..55094408208 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart @@ -97,9 +97,7 @@ class _DisconnectedMemoryScreenBodyState roundedTopBorder: false, includeTopBorder: false, ), - Expanded( - child: DiffPane(diffController: diffController), - ), + Expanded(child: DiffPane(diffController: diffController)), ], ), ); diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_tabs.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_tabs.dart index 9456612ef7b..02bb802c4c6 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_tabs.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_tabs.dart @@ -39,39 +39,33 @@ class MemoryTabView extends StatelessWidget { } TabAndView _diff() => ( - tab: DevToolsTab.create( - key: MemoryScreenKeys.diffTab, - gaPrefix: _gaPrefix, - tabName: 'Diff Snapshots', - ), - tabView: KeepAliveWrapper( - child: DiffPane( - diffController: controller.diff, - ), - ), - ); + tab: DevToolsTab.create( + key: MemoryScreenKeys.diffTab, + gaPrefix: _gaPrefix, + tabName: 'Diff Snapshots', + ), + tabView: KeepAliveWrapper(child: DiffPane(diffController: controller.diff)), + ); TabAndView _profile() => ( - tab: DevToolsTab.create( - key: MemoryScreenKeys.profileTab, - tabName: 'Profile Memory', - gaPrefix: _gaPrefix, - ), - tabView: KeepAliveWrapper( - child: AllocationProfileTableView( - controller: controller.profile!, - ), - ), - ); + tab: DevToolsTab.create( + key: MemoryScreenKeys.profileTab, + tabName: 'Profile Memory', + gaPrefix: _gaPrefix, + ), + tabView: KeepAliveWrapper( + child: AllocationProfileTableView(controller: controller.profile!), + ), + ); TabAndView _trace() => ( - tab: DevToolsTab.create( - key: MemoryScreenKeys.traceTab, - tabName: 'Trace Instances', - gaPrefix: _gaPrefix, - ), - tabView: KeepAliveWrapper( - child: TracingPane(controller: controller.trace!), - ), - ); + tab: DevToolsTab.create( + key: MemoryScreenKeys.traceTab, + tabName: 'Trace Instances', + gaPrefix: _gaPrefix, + ), + tabView: KeepAliveWrapper( + child: TracingPane(controller: controller.trace!), + ), + ); } diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart index 9016ba02c64..2fd997f913d 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -12,14 +12,7 @@ import '../../panes/tracing/tracing_pane_controller.dart'; import '../../shared/heap/class_filter.dart'; @visibleForTesting -enum Json { - selectedTab, - classFilter, - diffData, - profileData, - chartData, - trace; -} +enum Json { selectedTab, classFilter, diffData, profileData, chartData, trace } class OfflineMemoryData with Serializable { OfflineMemoryData( diff --git a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart index 2581327c8ed..c753e6e6caa 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart @@ -74,13 +74,8 @@ class _ConnectedMemoryBodyState extends State onSave: controller.exportData, ), const SizedBox(height: intermediateSpacing), - MemoryChartPane( - chart: controller.chart, - keyFocusNode: _focusNode, - ), - Expanded( - child: MemoryTabView(controller), - ), + MemoryChartPane(chart: controller.chart, keyFocusNode: _focusNode), + Expanded(child: MemoryTabView(controller)), ], ); }, diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_connection.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_connection.dart index db8794eab32..f2a55defe39 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_connection.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_connection.dart @@ -61,41 +61,42 @@ class ChartVmConnection extends DisposableController }); autoDisposeStreamSubscription( - serviceConnection.serviceManager.service!.onExtensionEvent - .listen(_memoryTracker.onMemoryData), + serviceConnection.serviceManager.service!.onExtensionEvent.listen( + _memoryTracker.onMemoryData, + ), ); autoDisposeStreamSubscription( - serviceConnection.serviceManager.service!.onGCEvent - .listen(_memoryTracker.onGCEvent), + serviceConnection.serviceManager.service!.onGCEvent.listen( + _memoryTracker.onGCEvent, + ), ); autoDisposeStreamSubscription( - serviceConnection.serviceManager.service!.onIsolateEvent - .listen(_memoryTracker.onIsolateEvent), + serviceConnection.serviceManager.service!.onIsolateEvent.listen( + _memoryTracker.onIsolateEvent, + ), ); - _polling = DebounceTimer.periodic( - chartUpdateDelay, - () async { - if (!_isConnected) { - _polling?.cancel(); - return; - } - try { - await _memoryTracker.pollMemory(); - } catch (e, trace) { - // TODO (polina-c): remove after fixing https://github.com/flutter/devtools/issues/7808 - // and https://github.com/flutter/devtools/issues/7722 - final isDisconnectionError = e.toString().contains('connection') || - trace.toString().contains('isFlutterApp'); - - if (_isConnected && !isDisconnectionError) { - rethrow; - } + _polling = DebounceTimer.periodic(chartUpdateDelay, () async { + if (!_isConnected) { + _polling?.cancel(); + return; + } + try { + await _memoryTracker.pollMemory(); + } catch (e, trace) { + // TODO (polina-c): remove after fixing https://github.com/flutter/devtools/issues/7808 + // and https://github.com/flutter/devtools/issues/7722 + final isDisconnectionError = + e.toString().contains('connection') || + trace.toString().contains('isFlutterApp'); + + if (_isConnected && !isDisconnectionError) { + rethrow; } - }, - ); + } + }); initialized = true; } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_data.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_data.dart index 7c795214790..a7bbe36ede6 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_data.dart @@ -9,12 +9,7 @@ import '../../../shared/primitives/memory_timeline.dart'; import '../data/primitives.dart'; @visibleForTesting -enum Json { - isDeviceAndroid, - timeline, - interval, - isLegendVisible; -} +enum Json { isDeviceAndroid, timeline, interval, isLegendVisible } /// Chart data, that should be saved when transferred to offline data mode. class ChartData with Serializable { @@ -23,8 +18,8 @@ class ChartData with Serializable { MemoryTimeline? timeline, ChartInterval interval = ChartInterval.theDefault, bool isLegendVisible = false, - }) : _displayInterval = ValueNotifier(interval), - _isLegendVisible = ValueNotifier(isLegendVisible) { + }) : _displayInterval = ValueNotifier(interval), + _isLegendVisible = ValueNotifier(isLegendVisible) { this.timeline = timeline ?? MemoryTimeline(); } @@ -35,7 +30,8 @@ class ChartData with Serializable { json[Json.timeline.name], MemoryTimeline.fromJson, ), - interval: ChartInterval.byName(json[Json.interval.name]) ?? + interval: + ChartInterval.byName(json[Json.interval.name]) ?? ChartInterval.theDefault, isLegendVisible: json[Json.isLegendVisible.name] as bool? ?? false, ); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index def2bbb27cc..4daab0b2e6b 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -72,7 +72,8 @@ class MemoryChartPaneController extends DisposableController if (!isChartVisible.value) return; assert(data.isDeviceAndroid != null || _chartConnection!.initialized); data.isDeviceAndroid ??= _chartConnection!.isDeviceAndroid; - isAndroidChartVisible.value = data.isDeviceAndroid! && + isAndroidChartVisible.value = + data.isDeviceAndroid! && preferences.memory.androidCollectionEnabled.value; } @@ -82,10 +83,11 @@ class MemoryChartPaneController extends DisposableController if (!isChartVisible.value) return; if (!offlineDataController.showingOfflineData.value) { if (_chartConnection == null) { - _chartConnection ??= _chartConnection = ChartVmConnection( - data.timeline, - isAndroidChartVisible: isAndroidChartVisible, - ); + _chartConnection ??= + _chartConnection = ChartVmConnection( + data.timeline, + isAndroidChartVisible: isAndroidChartVisible, + ); if (serviceConnection.serviceManager.connectedState.value.connected) { _chartConnection!.init(); resume(); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/android_chart_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/android_chart_controller.dart index cf74319ca70..c30ac0284b2 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/android_chart_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/android_chart_controller.dart @@ -30,10 +30,7 @@ class AndroidChartController extends ChartController { this.memoryTimeline, { required this.paused, List sharedLabels = const [], - }) : super( - name: 'Android', - sharedLabelTimestamps: sharedLabels, - ) { + }) : super(name: 'Android', sharedLabelTimestamps: sharedLabels) { setupData(); addAutoDisposeListener(memoryTimeline.sampleAdded, () { @@ -276,19 +273,13 @@ class AndroidChartController extends ChartController { final graphicValue = adb.graphics.toDouble(); addDataToTrace( AndroidTraceName.graphics.index, - chart_trace.Data( - timestamp, - graphicValue, - ), + chart_trace.Data(timestamp, graphicValue), ); final nativeHeapValue = adb.nativeHeap.toDouble(); addDataToTrace( AndroidTraceName.nativeHeap.index, - chart_trace.Data( - timestamp, - nativeHeapValue, - ), + chart_trace.Data(timestamp, nativeHeapValue), ); final javaHeapValue = adb.javaHeap.toDouble(); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/event_chart_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/event_chart_controller.dart index 768ac39648f..23e29228204 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/event_chart_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/event_chart_controller.dart @@ -53,12 +53,12 @@ enum _EventsTraceName { /// Their y-position is such that the symbols won't overlap. class EventChartController extends ChartController { EventChartController(this.memoryTimeline, {required this.paused}) - : super( - displayYLabels: false, - displayXAxis: false, - displayXLabels: false, - name: 'Event Pane', - ) { + : super( + displayYLabels: false, + displayXAxis: false, + displayXLabels: false, + name: 'Event Pane', + ) { setFixedYRange(_Sizes.visibleVm, _Sizes.extensions); setupData(); @@ -78,10 +78,7 @@ class EventChartController extends ChartController { final chartDataLength = timestampsLength; final dataLength = memoryTimeline.data.length; - final dataRange = memoryTimeline.data.getRange( - chartDataLength, - dataLength, - ); + final dataRange = memoryTimeline.data.getRange(chartDataLength, dataLength); dataRange.forEach(addSample); } @@ -258,9 +255,7 @@ class EventChartController extends ChartController { name: _EventsTraceName.gc.toString(), ); assert(gcIndex == _EventsTraceName.gc.index); - assert( - trace(gcIndex).name == _EventsTraceName.values[gcIndex].toString(), - ); + assert(trace(gcIndex).name == _EventsTraceName.values[gcIndex].toString()); assert(traces.length == _EventsTraceName.values.length); } @@ -290,10 +285,7 @@ class EventChartController extends ChartController { // User events snapshot, auto-snapshot, manual GC, are plotted on the top-line // of the event pane (visible Events). - final data = chart_trace.Data( - sample.timestamp, - _Sizes.visible, - ); + final data = chart_trace.Data(sample.timestamp, _Sizes.visible); if (events.isEventGC) { // Plot manual requested GC on the visibleEvent Y coordinate. @@ -312,10 +304,7 @@ class EventChartController extends ChartController { if (sample.memoryEventInfo.isEventAllocationAccumulator) { final allocationEvent = events.allocationAccumulator!; - final data = chart_trace.Data( - sample.timestamp, - _Sizes.visibleMonitor, - ); + final data = chart_trace.Data(sample.timestamp, _Sizes.visibleMonitor); if (allocationEvent.isReset) { addDataToTrace(_EventsTraceName.monitorReset.index, data); } else if (allocationEvent.isStart) { diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/vm_chart_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/vm_chart_controller.dart index dd2a3fd03fb..c1ca585d75e 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/vm_chart_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/charts/vm_chart_controller.dart @@ -26,7 +26,7 @@ class _Colors { class VMChartController extends ChartController { VMChartController(this.memoryTimeline, {required this.paused}) - : super(name: 'VM Memory') { + : super(name: 'VM Memory') { setupData(); addAutoDisposeListener(memoryTimeline.sampleAdded, () { @@ -45,10 +45,7 @@ class VMChartController extends ChartController { final chartDataLength = timestampsLength; final dataLength = memoryTimeline.data.length; - final dataRange = memoryTimeline.data.getRange( - chartDataLength, - dataLength, - ); + final dataRange = memoryTimeline.data.getRange(chartDataLength, dataLength); dataRange.forEach(addSample); } @@ -109,9 +106,7 @@ class VMChartController extends ChartController { ); final usedIndex = VmTraceName.used.index; - assert( - trace(usedIndex).name == VmTraceName.values[usedIndex].toString(), - ); + assert(trace(usedIndex).name == VmTraceName.values[usedIndex].toString()); final capacityIndex = VmTraceName.capacity.index; assert( @@ -120,9 +115,7 @@ class VMChartController extends ChartController { ); final rSSIndex = VmTraceName.rSS.index; - assert( - trace(rSSIndex).name == VmTraceName.values[rSSIndex].toString(), - ); + assert(trace(rSSIndex).name == VmTraceName.values[rSSIndex].toString()); final rasterLayerIndex = VmTraceName.rasterLayer.index; assert( @@ -166,9 +159,7 @@ class VMChartController extends ChartController { name: VmTraceName.used.toString(), ); assert(usedIndex == VmTraceName.used.index); - assert( - trace(usedIndex).name == VmTraceName.values[usedIndex].toString(), - ); + assert(trace(usedIndex).name == VmTraceName.values[usedIndex].toString()); // Heap Capacity final capacityIndex = createTrace( @@ -196,9 +187,7 @@ class VMChartController extends ChartController { name: VmTraceName.rSS.toString(), ); assert(rSSIndex == VmTraceName.rSS.index); - assert( - trace(rSSIndex).name == VmTraceName.values[rSSIndex].toString(), - ); + assert(trace(rSSIndex).name == VmTraceName.values[rSSIndex].toString()); final rasterLayerIndex = createTrace( chart_trace.ChartType.line, diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index 83dc227b2a3..036b3b9b221 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -18,17 +18,10 @@ import '../data/primitives.dart'; final _log = Logger('memory_protocol'); -enum _ContinuesState { - none, - stop, - next, -} +enum _ContinuesState { none, stop, next } class MemoryTracker { - MemoryTracker( - this.timeline, { - required this.isAndroidChartVisible, - }); + MemoryTracker(this.timeline, {required this.isAndroidChartVisible}); final MemoryTimeline timeline; @@ -101,7 +94,8 @@ class MemoryTracker { in serviceConnection.serviceManager.isolateManager.isolates.value) { try { isolateMemory[isolateRef] = await serviceConnection - .serviceManager.service! + .serviceManager + .service! .getMemoryUsage(isolateRef.id!); } on SentinelException { // Isolates can disappear during polling, so just swallow this exception. @@ -110,12 +104,13 @@ class MemoryTracker { // Polls for current Android meminfo using: // > adb shell dumpsys meminfo -d - _adbMemoryInfo = serviceConnection - .serviceManager.connectedState.value.connected && - serviceConnection.serviceManager.vm!.operatingSystem == 'android' && - isAndroidChartVisible.value - ? await _fetchAdbInfo() - : AdbMemoryInfo.empty(); + _adbMemoryInfo = + serviceConnection.serviceManager.connectedState.value.connected && + serviceConnection.serviceManager.vm!.operatingSystem == + 'android' && + isAndroidChartVisible.value + ? await _fetchAdbInfo() + : AdbMemoryInfo.empty(); // Query the engine's rasterCache estimate. rasterCache = await _fetchRasterCacheInfo(); @@ -153,9 +148,8 @@ class MemoryTracker { } /// Fetch ADB meminfo, ADB returns values in KB convert to total bytes. - Future _fetchAdbInfo() async => AdbMemoryInfo.fromJsonInKB( - (await serviceConnection.adbMemoryInfo).json!, - ); + Future _fetchAdbInfo() async => + AdbMemoryInfo.fromJsonInKB((await serviceConnection.adbMemoryInfo).json!); void _recalculate({bool fromGC = false}) { int used = 0; 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 8945ab6518b..884515f139b 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 @@ -107,14 +107,7 @@ const renderImage = 'image'; /// Name of each trace being charted, index order is the trace index /// too (order of trace creation top-down order). -enum VmTraceName { - external, - used, - capacity, - rSS, - rasterLayer, - rasterPicture, -} +enum VmTraceName { external, used, capacity, rSS, rasterLayer, rasterPicture } Map traceRender({ String? image, @@ -238,15 +231,13 @@ class ChartsValues { for (final event in eventInfo.extensionEvents?.events ?? []) { if (event.customEventName != null) { - events.add( - { - eventName: event.eventKind!, - customEvent: { - customEventName: event.customEventName, - customEventData: event.data, - }, + events.add({ + eventName: event.eventKind!, + customEvent: { + customEventName: event.customEventName, + customEventData: event.data, }, - ); + }); } else { events.add({ eventName: event.eventKind!, @@ -318,8 +309,9 @@ class ChartsValues { dashed: true, ); - final capacityValueDisplay = - formatNumeric(vmData[capacityJsonName] as num?); + final capacityValueDisplay = formatNumeric( + vmData[capacityJsonName] as num?, + ); vmDataDisplayed['$allocatedDisplay $capacityValueDisplay'] = traceRender( color: traces[VmTraceName.capacity.index].characteristics.color, dashed: true, @@ -330,21 +322,24 @@ class ChartsValues { color: traces[VmTraceName.used.index].characteristics.color, ); - final externalValueDisplay = - formatNumeric(vmData[externalJsonName] as num?); + final externalValueDisplay = formatNumeric( + vmData[externalJsonName] as num?, + ); vmDataDisplayed['$externalDisplay $externalValueDisplay'] = traceRender( color: traces[VmTraceName.external.index].characteristics.color, ); - final layerValueDisplay = - formatNumeric(vmData[rasterLayerJsonName] as num?); + final layerValueDisplay = formatNumeric( + vmData[rasterLayerJsonName] as num?, + ); vmDataDisplayed['$layerDisplay $layerValueDisplay'] = traceRender( color: traces[VmTraceName.rasterLayer.index].characteristics.color, dashed: true, ); - final pictureValueDisplay = - formatNumeric(vmData[rasterPictureJsonName] as num?); + final pictureValueDisplay = formatNumeric( + vmData[rasterPictureJsonName] as num?, + ); vmDataDisplayed['$pictureDisplay $pictureValueDisplay'] = traceRender( color: traces[VmTraceName.rasterPicture.index].characteristics.color, dashed: true, @@ -363,62 +358,67 @@ class ChartsValues { final totalValueDisplay = formatNumeric(data[adbTotalJsonName] as num?); androidDataDisplayed['$androidTotalDisplay $totalValueDisplay'] = traceRender( - color: traces[AndroidTraceName.total.index].characteristics.color, - dashed: true, - ); + color: traces[AndroidTraceName.total.index].characteristics.color, + dashed: true, + ); // Other trace final otherValueDisplay = formatNumeric(data[adbOtherJsonName] as num?); androidDataDisplayed['$androidOtherDisplay $otherValueDisplay'] = traceRender( - color: traces[AndroidTraceName.other.index].characteristics.color, - ); + color: traces[AndroidTraceName.other.index].characteristics.color, + ); // Native heap trace - final nativeValueDisplay = - formatNumeric(data[adbNativeHeapJsonName] as num?); + final nativeValueDisplay = formatNumeric( + data[adbNativeHeapJsonName] as num?, + ); androidDataDisplayed['$androidNativeDisplay $nativeValueDisplay'] = traceRender( - color: traces[AndroidTraceName.nativeHeap.index].characteristics.color, - ); + color: + traces[AndroidTraceName.nativeHeap.index].characteristics.color, + ); // Graphics trace - final graphicsValueDisplay = - formatNumeric(data[adbGraphicsJsonName] as num?); + final graphicsValueDisplay = formatNumeric( + data[adbGraphicsJsonName] as num?, + ); androidDataDisplayed['$androidGraphicsDisplay $graphicsValueDisplay'] = traceRender( - color: traces[AndroidTraceName.graphics.index].characteristics.color, - ); + color: + traces[AndroidTraceName.graphics.index].characteristics.color, + ); // Code trace final codeValueDisplay = formatNumeric(data[adbCodeJsonName] as num?); androidDataDisplayed['$androidCodeDisplay $codeValueDisplay'] = traceRender( - color: traces[AndroidTraceName.code.index].characteristics.color, - ); + color: traces[AndroidTraceName.code.index].characteristics.color, + ); // Java heap trace final javaValueDisplay = formatNumeric(data[adbJavaHeapJsonName] as num?); androidDataDisplayed['$androidJavaDisplay $javaValueDisplay'] = traceRender( - color: traces[AndroidTraceName.javaHeap.index].characteristics.color, - ); + color: + traces[AndroidTraceName.javaHeap.index].characteristics.color, + ); // Stack trace final stackValueDisplay = formatNumeric(data[adbStackJsonName] as num?); androidDataDisplayed['$androidStackDisplay $stackValueDisplay'] = traceRender( - color: traces[AndroidTraceName.stack.index].characteristics.color, - ); + color: traces[AndroidTraceName.stack.index].characteristics.color, + ); } return androidDataDisplayed; } String? formatNumeric(num? number) => prettyPrintBytes( - number, - mbFractionDigits: 2, - includeUnit: true, - roundingPoint: 0.7, - ); + number, + mbFractionDigits: 2, + includeUnit: true, + roundingPoint: 0.7, + ); } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart index 73da8bf1c94..32d7abf447d 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart @@ -87,11 +87,7 @@ class _ChartControlPaneState extends State ), ], const SizedBox(height: denseSpacing), - Row( - children: [ - _LegendButton(chartController: widget.chart), - ], - ), + Row(children: [_LegendButton(chartController: widget.chart)]), const SizedBox(height: denseSpacing), IntervalDropdown(chartController: widget.chart), const SizedBox(height: denseSpacing), @@ -110,17 +106,19 @@ class _LegendButton extends StatelessWidget { Widget build(BuildContext context) { return ValueListenableBuilder( valueListenable: chartController.data.isLegendVisible, - builder: (_, legendVisible, _) => GaDevToolsButton( - onPressed: chartController.data.toggleLegendVisibility, - gaScreen: gac.memory, - gaSelection: legendVisible - ? gac.MemoryEvents.hideChartLegend.name - : gac.MemoryEvents.showChartLegend.name, - icon: legendVisible ? Icons.close : Icons.storage, - label: 'Legend', - tooltip: 'Toggle visibility of the chart legend', - minScreenWidthForTextBeforeScaling: memoryControlsMinVerboseWidth, - ), + builder: + (_, legendVisible, _) => GaDevToolsButton( + onPressed: chartController.data.toggleLegendVisibility, + gaScreen: gac.memory, + gaSelection: + legendVisible + ? gac.MemoryEvents.hideChartLegend.name + : gac.MemoryEvents.showChartLegend.name, + icon: legendVisible ? Icons.close : Icons.storage, + label: 'Legend', + tooltip: 'Toggle visibility of the chart legend', + minScreenWidthForTextBeforeScaling: memoryControlsMinVerboseWidth, + ), ); } } @@ -140,8 +138,9 @@ class _ChartHelpLink extends StatelessWidget { MoreInfoLink( url: DocLinks.chart.value, gaScreenName: '', - gaSelectedItemDescription: - gac.topicDocumentationLink(_documentationTopic), + gaSelectedItemDescription: gac.topicDocumentationLink( + _documentationTopic, + ), ), ], child: const Column( diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart index 4651e1bb3c8..9d573523a2c 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart @@ -102,11 +102,7 @@ class _MemoryChartPaneState extends State timestamp: value.timestamp ?? _timestamp, ); - _showHover( - context, - allValues, - details.globalPosition, - ); + _showHover(context, allValues, details.globalPosition); }); } @@ -135,9 +131,7 @@ class _MemoryChartPaneState extends State } // There is no listener passed, so SetState will be invoked. - addAutoDisposeListener( - widget.chart.isAndroidChartVisible, - ); + addAutoDisposeListener(widget.chart.isAndroidChartVisible); } @override @@ -201,9 +195,7 @@ class _MemoryChartPaneState extends State }, ), // Chart control pane. - ChartControlPane( - chart: widget.chart, - ), + ChartControlPane(chart: widget.chart), ], ), ); @@ -231,13 +223,15 @@ class _MemoryChartPaneState extends State return []; } - final androidDataDisplayed = - chartsValues.androidDataToDisplay(widget.chart.android.traces); + final androidDataDisplayed = chartsValues.androidDataToDisplay( + widget.chart.android.traces, + ); // Separator between Android data. // TODO(terry): Why Center widget doesn't work (parent width is bigger/centered too far right). // Is it centering on a too wide Overlay? - final width = _hoverWidth - + final width = + _hoverWidth - totalDividerLineHorizontalSpace - DashedLine.defaultDashWidth; final dashedColor = Colors.grey.shade600; @@ -266,8 +260,9 @@ class _MemoryChartPaneState extends State final focusColor = theme.focusColor; final colorScheme = theme.colorScheme; - final box = MemoryChartPane.hoverKey.currentContext!.findRenderObject() - as RenderBox; + final box = + MemoryChartPane.hoverKey.currentContext!.findRenderObject() + as RenderBox; final renderBoxWidth = box.size.width; // Display hover to left of right side of position. @@ -278,11 +273,12 @@ class _MemoryChartPaneState extends State double totalHoverHeight; int totalTraces; - totalTraces = widget.chart.isAndroidChartVisible.value - ? chartsValues.vmData.entries.length - - 1 + - chartsValues.androidData.entries.length - : chartsValues.vmData.entries.length - 1; + totalTraces = + widget.chart.isAndroidChartVisible.value + ? chartsValues.vmData.entries.length - + 1 + + chartsValues.androidData.entries.length + : chartsValues.vmData.entries.length - 1; totalHoverHeight = _computeHoverHeight( chartsValues.eventCount, @@ -294,40 +290,41 @@ class _MemoryChartPaneState extends State final overlayState = Overlay.of(context); _hoverOverlayEntry ??= OverlayEntry( - builder: (context) => Positioned( - top: position.dy + _hoverYOffset, - left: xPosition, - height: totalHoverHeight, - child: Container( - padding: const EdgeInsets.only(top: 5, bottom: 8), - decoration: BoxDecoration( - color: colorScheme.defaultBackgroundColor, - border: Border.all( - color: focusColor, - width: _hoverCardBorderWidth, - ), - borderRadius: defaultBorderRadius, - ), - width: _hoverWidth, - child: ListView( - children: [ - Container( - width: _hoverWidth, - padding: const EdgeInsets.only(bottom: 4), - child: Text( - 'Time $displayTimestamp', - style: theme.legendTextStyle, - textAlign: TextAlign.center, + builder: + (context) => Positioned( + top: position.dy + _hoverYOffset, + left: xPosition, + height: totalHoverHeight, + child: Container( + padding: const EdgeInsets.only(top: 5, bottom: 8), + decoration: BoxDecoration( + color: colorScheme.defaultBackgroundColor, + border: Border.all( + color: focusColor, + width: _hoverCardBorderWidth, ), + borderRadius: defaultBorderRadius, ), - ..._displayEventsInHover(chartsValues), - ..._displayVmDataInHover(chartsValues), - ..._displayAndroidDataInHover(chartsValues), - ..._displayExtensionEventsInHover(chartsValues), - ], + width: _hoverWidth, + child: ListView( + children: [ + Container( + width: _hoverWidth, + padding: const EdgeInsets.only(bottom: 4), + child: Text( + 'Time $displayTimestamp', + style: theme.legendTextStyle, + textAlign: TextAlign.center, + ), + ), + ..._displayEventsInHover(chartsValues), + ..._displayVmDataInHover(chartsValues), + ..._displayAndroidDataInHover(chartsValues), + ..._displayExtensionEventsInHover(chartsValues), + ], + ), + ), ), - ), - ), ); overlayState.insert(_hoverOverlayEntry!); @@ -343,9 +340,10 @@ class _MemoryChartPaneState extends State for (final entry in dataToDisplay.entries) { final keys = entry.value.keys; - final image = keys.contains(renderImage) - ? entry.value[renderImage] as String? - : null; + final image = + keys.contains(renderImage) + ? entry.value[renderImage] as String? + : null; final color = keys.contains(renderLine) ? entry.value[renderLine] as Color? : null; final dashedLine = @@ -404,24 +402,17 @@ class _MemoryChartPaneState extends State traceColor = dashed ? createDashWidget(colorPatch) : createSolidLine(colorPatch); } else { - traceColor = image == null - ? const SizedBox() - : scaleImage - ? Image( - image: AssetImage(image), - width: 20, - height: 10, - ) - : Image( - image: AssetImage(image), - ); + traceColor = + image == null + ? const SizedBox() + : scaleImage + ? Image(image: AssetImage(image), width: 20, height: 10) + : Image(image: AssetImage(image)); } return [ traceColor, - const PaddedDivider( - padding: EdgeInsets.only(left: denseRowSpacing), - ), + const PaddedDivider(padding: EdgeInsets.only(left: denseRowSpacing)), Text(displayName, style: theme.legendTextStyle), Text(displayValue, style: theme.legendTextStyle), ]; @@ -439,9 +430,7 @@ class _MemoryChartPaneState extends State ); return Container( margin: const EdgeInsets.only(left: 5, bottom: 2), - child: Row( - children: rowChildren, - ), + child: Row(children: rowChildren), ); } @@ -459,9 +448,7 @@ class _MemoryChartPaneState extends State List _displayExtensionEventsInHover(ChartsValues chartsValues) { return [ if (chartsValues.hasExtensionEvents) - ..._extensionEvents( - allEvents: chartsValues.extensionEvents, - ), + ..._extensionEvents(allEvents: chartsValues.extensionEvents), ]; } @@ -528,9 +515,7 @@ class _MemoryChartPaneState extends State children: [ Container( padding: const EdgeInsets.only(left: 6.0), - child: Image( - image: AssetImage(eventLegendAsset(eventsLength)), - ), + child: Image(image: AssetImage(eventLegendAsset(eventsLength))), ), const SizedBox(width: denseSpacing), Text( @@ -539,10 +524,7 @@ class _MemoryChartPaneState extends State ), ], ); - return [ - title, - ...widgets, - ]; + return [title, ...widgets]; } String _decodeEventValues(Map event) { diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/interval_dropdown.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/interval_dropdown.dart index 04b44ffaa04..d6cbf21db74 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/interval_dropdown.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/interval_dropdown.dart @@ -23,16 +23,14 @@ class _IntervalDropdownState extends State { @override Widget build(BuildContext context) { final displayTypes = - ChartInterval.values.map>( - ( - ChartInterval value, - ) { - return DropdownMenuItem( - value: value, - child: Text(value.displayName), - ); - }, - ).toList(); + ChartInterval.values.map>(( + ChartInterval value, + ) { + return DropdownMenuItem( + value: value, + child: Text(value.displayName), + ); + }).toList(); return RoundedDropDownButton( isDense: true, diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/legend.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/legend.dart index b578d16c0bc..738633dc3c1 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/legend.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/legend.dart @@ -49,12 +49,7 @@ class MemoryChartLegend extends StatelessWidget { while (iterator.moveNext()) { final leftEntry = iterator.current; final rightEntry = iterator.moveNext() ? iterator.current : null; - legendRows.add( - _LegendRow( - entry1: leftEntry, - entry2: rightEntry, - ), - ); + legendRows.add(_LegendRow(entry1: leftEntry, entry2: rightEntry)); } final vms = vmLegendContent(chartController.vm); @@ -66,11 +61,7 @@ class MemoryChartLegend extends StatelessWidget { ); for (final entry in vms.entries) { - legendRows.add( - _LegendRow( - entry1: entry, - ), - ); + legendRows.add(_LegendRow(entry1: entry)); } if (isAndroidVisible) { @@ -83,11 +74,7 @@ class MemoryChartLegend extends StatelessWidget { ); for (final entry in androids.entries) { - legendRows.add( - _LegendRow( - entry1: entry, - ), - ); + legendRows.add(_LegendRow(entry1: entry)); } } @@ -111,10 +98,7 @@ class MemoryChartLegend extends StatelessWidget { } class _LegendRow extends StatelessWidget { - const _LegendRow({ - required this.entry1, - this.entry2, - }); + const _LegendRow({required this.entry1, this.entry2}); final MapEntry> entry1; final MapEntry>? entry2; @@ -138,9 +122,7 @@ class _LegendRow extends StatelessWidget { child: Text(name, style: legendEntry), ), ), - const PaddedDivider( - padding: EdgeInsets.only(left: denseRowSpacing), - ), + const PaddedDivider(padding: EdgeInsets.only(left: denseRowSpacing)), widget, ]); @@ -148,15 +130,18 @@ class _LegendRow extends StatelessWidget { } Widget legendSymbol(Map dataToDisplay) { - final image = dataToDisplay.containsKey(renderImage) - ? dataToDisplay[renderImage] as String? - : null; - final color = dataToDisplay.containsKey(renderLine) - ? dataToDisplay[renderLine] as Color? - : null; - final dashedLine = dataToDisplay.containsKey(renderDashed) - ? dataToDisplay[renderDashed] - : false; + final image = + dataToDisplay.containsKey(renderImage) + ? dataToDisplay[renderImage] as String? + : null; + final color = + dataToDisplay.containsKey(renderLine) + ? dataToDisplay[renderLine] as Color? + : null; + final dashedLine = + dataToDisplay.containsKey(renderDashed) + ? dataToDisplay[renderDashed] + : false; Widget traceColor; if (color != null) { @@ -205,8 +190,7 @@ enum _LegendCategory { vmGC('GC VM'), manualGC('Manual'), event('Event'), - events('Events'), - ; + events('Events'); const _LegendCategory(this.displayName); @@ -214,32 +198,22 @@ enum _LegendCategory { } Map> _eventLegendContent(bool isLight) => { - _LegendCategory.manualSnapshot.displayName: traceRender( - image: snapshotManualLegend, - ), - _LegendCategory.autoSnapshot.displayName: traceRender( - image: snapshotAutoLegend, - ), - _LegendCategory.monitor.displayName: traceRender( - image: monitorLegend, - ), - _LegendCategory.reset.displayName: traceRender( - image: isLight ? resetLightLegend : resetDarkLegend, - ), - _LegendCategory.vmGC.displayName: traceRender( - image: gcVMLegend, - ), - _LegendCategory.manualGC.displayName: traceRender( - image: gcManualLegend, - ), - // TODO: why do we need both a singular and plural legend entry for event? - _LegendCategory.event.displayName: traceRender( - image: eventLegendAsset(1), - ), - _LegendCategory.events.displayName: traceRender( - image: eventLegendAsset(2), - ), - }; + _LegendCategory.manualSnapshot.displayName: traceRender( + image: snapshotManualLegend, + ), + _LegendCategory.autoSnapshot.displayName: traceRender( + image: snapshotAutoLegend, + ), + _LegendCategory.monitor.displayName: traceRender(image: monitorLegend), + _LegendCategory.reset.displayName: traceRender( + image: isLight ? resetLightLegend : resetDarkLegend, + ), + _LegendCategory.vmGC.displayName: traceRender(image: gcVMLegend), + _LegendCategory.manualGC.displayName: traceRender(image: gcManualLegend), + // TODO: why do we need both a singular and plural legend entry for event? + _LegendCategory.event.displayName: traceRender(image: eventLegendAsset(1)), + _LegendCategory.events.displayName: traceRender(image: eventLegendAsset(2)), +}; Map> vmLegendContent( VMChartController vmChartController, diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/memory_chart.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/memory_chart.dart index df82209d3e9..bb8d2864393 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/memory_chart.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/memory_chart.dart @@ -42,9 +42,6 @@ class MemoryChartState extends State with AutoDisposeMixin { @override Widget build(BuildContext context) { - return SizedBox( - height: defaultChartHeight, - child: Chart(widget.chart), - ); + return SizedBox(height: defaultChartHeight, child: Chart(widget.chart)); } } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/control_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/control_pane.dart index a3938fe5cd4..53d4fa8756b 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/control_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/control_pane.dart @@ -26,18 +26,15 @@ class MemoryControlPane extends StatelessWidget { Widget build(BuildContext context) { // OfflineAwareControls are here to enable button to exit offline mode. return OfflineAwareControls( - controlsBuilder: (_) => Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const PrimaryControls(), - const Spacer(), - SecondaryControls( - isGcing: isGcing, - onGc: onGc, - onSave: onSave, + controlsBuilder: + (_) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const PrimaryControls(), + const Spacer(), + SecondaryControls(isGcing: isGcing, onGc: onGc, onSave: onSave), + ], ), - ], - ), gaScreen: ScreenMetaData.memory.id, ); } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/settings_dialog.dart b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/settings_dialog.dart index d67ad4272da..4f7f9e655e2 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/settings_dialog.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/settings_dialog.dart @@ -43,9 +43,7 @@ class MemorySettingsDialog extends StatelessWidget { ], ), ), - actions: const [ - DialogCloseButton(), - ], + actions: const [DialogCloseButton()], ); } } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart index b194ca14787..e3f203bac76 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart @@ -29,11 +29,7 @@ import 'class_data.dart'; import 'snapshot_item.dart'; @visibleForTesting -enum Json { - snapshots, - diffWith, - rootPackage; -} +enum Json { snapshots, diffWith, rootPackage } class DiffPaneController extends DisposableController with Serializable { DiffPaneController({ @@ -48,9 +44,13 @@ class DiffPaneController extends DisposableController with Serializable { } factory DiffPaneController.fromJson(Map json) { - final snapshots = (json[Json.snapshots.name] as List) - .map((e) => deserialize(e, SnapshotDataItem.fromJson)) - .toList(); + final snapshots = + (json[Json.snapshots.name] as List) + .map( + (e) => + deserialize(e, SnapshotDataItem.fromJson), + ) + .toList(); final diffWith = (json[Json.diffWith.name] as List).map((e) => e as int?).toList(); @@ -73,18 +73,21 @@ class DiffPaneController extends DisposableController with Serializable { @override Map toJson() { - final snapshots = core.snapshots.value - .whereType() - .where((s) => s.heap != null) - .toList(); - - final snapshotToIndex = - snapshots.asMap().map((index, item) => MapEntry(item, index)); + final snapshots = + core.snapshots.value + .whereType() + .where((s) => s.heap != null) + .toList(); + + final snapshotToIndex = snapshots.asMap().map( + (index, item) => MapEntry(item, index), + ); - final diffWithIndices = snapshots.map((item) { - final diffWith = item.diffWith.value; - return diffWith == null ? null : snapshotToIndex[diffWith]; - }).toList(); + final diffWithIndices = + snapshots.map((item) { + final diffWith = item.diffWith.value; + return diffWith == null ? null : snapshotToIndex[diffWith]; + }).toList(); return { Json.snapshots.name: snapshots, @@ -105,10 +108,7 @@ class DiffPaneController extends DisposableController with Serializable { bool get hasSnapshots => core.snapshots.value.length > 1; Future takeSnapshot() async { - ga.select( - gac.memory, - gac.MemoryEvents.diffTakeSnapshotControlPane.name, - ); + ga.select(gac.memory, gac.MemoryEvents.diffTakeSnapshotControlPane.name); final item = SnapshotDataItem( displayNumber: _nextDisplayNumber(), defaultName: selectedIsolateName ?? '', @@ -121,10 +121,7 @@ class DiffPaneController extends DisposableController with Serializable { /// /// Opens file selector and loads snapshots from the selected files. Future importSnapshots() async { - ga.select( - gac.memory, - gac.importFile, - ); + ga.select(gac.memory, gac.importFile); final files = await importRawFilesFromPicker(); if (files.isEmpty) return; @@ -189,10 +186,7 @@ class DiffPaneController extends DisposableController with Serializable { derived._updateValues(); } - void setDiffing( - SnapshotDataItem diffItem, - SnapshotDataItem? withItem, - ) { + void setDiffing(SnapshotDataItem diffItem, SnapshotDataItem? withItem) { diffItem.diffWith.value = withItem; derived._updateValues(); } @@ -249,9 +243,10 @@ class CoreData { SnapshotItem get selectedItem => _snapshots.value[_selectedSnapshotIndex.value]; - SnapshotDataItem? get selectedDataItem => selectedItem is SnapshotDataItem - ? selectedItem as SnapshotDataItem - : null; + SnapshotDataItem? get selectedDataItem => + selectedItem is SnapshotDataItem + ? selectedItem as SnapshotDataItem + : null; /// Full name for the selected class. /// @@ -324,8 +319,9 @@ class DerivedData extends DisposableController with AutoDisposeControllerMixin { /// Classes to show for currently selected item, if the item is not diffed. ValueListenable?> get singleClassesToShow => _singleClassesToShow; - final _singleClassesToShow = - ValueNotifier?>(null); + final _singleClassesToShow = ValueNotifier?>( + null, + ); /// Classes to show for currently selected item, if the item is diffed. ValueListenable?> get diffClassesToShow => @@ -425,16 +421,18 @@ class DerivedData extends DisposableController with AutoDisposeControllerMixin { if (classes is ClassDataList) { _singleClassesToShow.value = classes; _diffClassesToShow.value = null; - classesTableSingle.selection.value = classes.list - .singleWhereOrNull((d) => d.className == selectedClassName); + classesTableSingle.selection.value = classes.list.singleWhereOrNull( + (d) => d.className == selectedClassName, + ); classesTableDiff.selection.value = null; classData.value = classesTableSingle.selection.value; } else if (classes is ClassDataList) { _singleClassesToShow.value = null; _diffClassesToShow.value = classes; classesTableSingle.selection.value = null; - classesTableDiff.selection.value = classes.list - .singleWhereOrNull((d) => d.className == selectedClassName); + classesTableDiff.selection.value = classes.list.singleWhereOrNull( + (d) => d.className == selectedClassName, + ); classData.value = classesTableDiff.selection.value; } else if (classes == null) { _singleClassesToShow.value = null; @@ -483,10 +481,7 @@ class DerivedData extends DisposableController with AutoDisposeControllerMixin { // Make sure the method does not trigger itself recursively. assert(!_updatingValues); - ga.timeStart( - gac.memory, - gac.MemoryTime.updateValues.name, - ); + ga.timeStart(gac.memory, gac.MemoryTime.updateValues.name); _updatingValues = true; } @@ -494,10 +489,7 @@ class DerivedData extends DisposableController with AutoDisposeControllerMixin { void _endUpdatingValues() { _updatingValues = false; - ga.timeEnd( - gac.memory, - gac.MemoryTime.updateValues.name, - ); + ga.timeEnd(gac.memory, gac.MemoryTime.updateValues.name); _assertIntegrity(); } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/snapshot_item.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/snapshot_item.dart index a429c414c95..bfefe23dd51 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/snapshot_item.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/snapshot_item.dart @@ -23,13 +23,7 @@ class SnapshotDocItem extends SnapshotItem { } @visibleForTesting -enum Json { - defaultName, - displayNumber, - graph, - created, - nameOverride; -} +enum Json { defaultName, displayNumber, graph, created, nameOverride } class SnapshotDataItem extends SnapshotItem with Serializable @@ -47,14 +41,17 @@ class SnapshotDataItem extends SnapshotItem nameOverride: json[Json.nameOverride.name] as String?, ); - final graph = HeapSnapshotGraphEncodeDecode.instance - .decodeNullable(json[Json.graph.name]); + final graph = HeapSnapshotGraphEncodeDecode.instance.decodeNullable( + json[Json.graph.name], + ); if (graph == null) return result; final loader = HeapGraphLoaderDirect( graph: graph, - created: DateTimeEncodeDecode.instance - .decodeNullable(json[Json.created.name]) ?? + created: + DateTimeEncodeDecode.instance.decodeNullable( + json[Json.created.name], + ) ?? DateTime.now(), ); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/data/classes_diff.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/data/classes_diff.dart index 6710e70e741..94a509fe5e4 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/data/classes_diff.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/data/classes_diff.dart @@ -56,8 +56,9 @@ class ObjectSetDiff { HeapData data, ObjectSet originalSet, ) { - final excludeFromRetained = - originalSet.excludedFromRetainedSize.contains(index); + final excludeFromRetained = originalSet.excludedFromRetainedSize.contains( + index, + ); setToAlter.countInstance( data.graph, index, @@ -72,8 +73,9 @@ class ObjectSetDiff { HeapData data, ObjectSet originalSet, ) { - final excludeFromRetained = - originalSet.excludedFromRetainedSize.contains(index); + final excludeFromRetained = originalSet.excludedFromRetainedSize.contains( + index, + ); setToAlter.uncountInstance( data.graph, index, @@ -82,10 +84,7 @@ class ObjectSetDiff { ); } - static Map _hashCodeToIndexMap( - ObjectSet? ids, - HeapData? data, - ) { + static Map _hashCodeToIndexMap(ObjectSet? ids, HeapData? data) { if (ids == null || data == null) return const {}; return { for (final id in ids.indexes) data.graph.objects[id].identityHashCode: id, @@ -133,12 +132,17 @@ class DiffClassData extends ClassData { dataAfter: dataAfter, ), // PathFromRoot, ObjectSetStats - byPath: subtractMaps( + byPath: subtractMaps< + PathFromRoot, + ObjectSetStats, + ObjectSetStats, + ObjectSetStats + >( from: after?.byPath, subtract: before?.byPath, - subtractor: ({subtract, from}) => - ObjectSetStats.subtract(subtract: subtract, from: from), + subtractor: + ({subtract, from}) => + ObjectSetStats.subtract(subtract: subtract, from: from), ), ); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/data/heap_diff_data.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/data/heap_diff_data.dart index 252b6ac79d0..24ed9b1e203 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/data/heap_diff_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/data/heap_diff_data.dart @@ -28,16 +28,21 @@ HeapDiffData calculateHeapDiffData({ required HeapData before, required HeapData after, }) { - final classesByName = subtractMaps( + final classesByName = subtractMaps< + HeapClassName, + SingleClassData, + SingleClassData, + DiffClassData + >( from: after.classes!.asMap(), subtract: before.classes!.asMap(), - subtractor: ({subtract, from}) => DiffClassData.compare( - before: subtract, - after: from, - dataBefore: before, - dataAfter: after, - ), + subtractor: + ({subtract, from}) => DiffClassData.compare( + before: subtract, + after: from, + dataBefore: before, + dataAfter: after, + ), ); return HeapDiffData._( diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/data/heap_diff_store.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/data/heap_diff_store.dart index edc167efe2c..5d0e9c102a4 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/data/heap_diff_store.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/data/heap_diff_store.dart @@ -28,12 +28,17 @@ HeapDiffData _calculateDiffGaWrapper(_HeapCouple couple) { ga.timeSync( gac.memory, gac.MemoryTime.calculateDiff.name, - syncOperation: () => result = - calculateHeapDiffData(before: couple.before, after: couple.after), - screenMetricsProvider: () => MemoryScreenMetrics( - heapDiffObjectsBefore: couple.before.graph.objects.length, - heapDiffObjectsAfter: couple.after.graph.objects.length, - ), + syncOperation: + () => + result = calculateHeapDiffData( + before: couple.before, + after: couple.after, + ), + screenMetricsProvider: + () => MemoryScreenMetrics( + heapDiffObjectsBefore: couple.before.graph.objects.length, + heapDiffObjectsAfter: couple.after.graph.objects.length, + ), ); return result; } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/diff_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/diff_pane.dart index c937267de96..a139f1b6a1a 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/diff_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/diff_pane.dart @@ -36,9 +36,7 @@ class DiffPane extends StatelessWidget { child: SnapshotList(controller: diffController), ), OutlineDecoration.onlyLeft( - child: _SnapshotItemContent( - controller: diffController, - ), + child: _SnapshotItemContent(controller: diffController), ), ], ); @@ -74,8 +72,9 @@ class _SnapshotItemContent extends StatelessWidget { styleSheet: MarkdownStyleSheet( p: Theme.of(context).regularTextStyle, ), - onTapLink: (text, url, title) => - unawaited(launchUrlWithErrorHandling(url!)), + onTapLink: + (text, url, title) => + unawaited(launchUrlWithErrorHandling(url!)), ), ), const SizedBox(width: densePadding), @@ -93,8 +92,8 @@ class _SnapshotItemContent extends StatelessWidget { MoreInfoLink( url: DocLinks.diff.value, gaScreenName: gac.memory, - gaSelectedItemDescription: - gac.topicDocumentationLink(_documentationTopic), + gaSelectedItemDescription: gac + .topicDocumentationLink(_documentationTopic), ), ], ), @@ -128,11 +127,7 @@ class SnapshotInstanceItemPane extends StatelessWidget { child: SnapshotControlPane(controller: controller), ), ), - Expanded( - child: SnapshotView( - controller: controller, - ), - ), + Expanded(child: SnapshotView(controller: controller)), ], ); } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/class_details.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/class_details.dart index 231884c927e..135314b4f14 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/class_details.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/class_details.dart @@ -49,10 +49,7 @@ class HeapClassDetails extends StatelessWidget { ); } - return RetainingPathView( - data: pathData, - controller: pathController, - ); + return RetainingPathView(data: pathData, controller: pathController); }, ); @@ -60,12 +57,8 @@ class HeapClassDetails extends StatelessWidget { axis: Axis.horizontal, initialFractions: const [0.7, 0.3], children: [ - OutlineDecoration.onlyRight( - child: retainingPathsTable, - ), - OutlineDecoration.onlyLeft( - child: selectedPathView, - ), + OutlineDecoration.onlyRight(child: retainingPathsTable), + OutlineDecoration.onlyLeft(child: selectedPathView), ], ); } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/path.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/path.dart index 260ac361b75..a84f9a69883 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/path.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/path.dart @@ -30,10 +30,7 @@ class RetainingPathView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: densePadding), - _PathControlPane( - controller: controller, - data: data, - ), + _PathControlPane(controller: controller, data: data), Expanded( child: Padding( padding: const EdgeInsets.only( @@ -50,10 +47,7 @@ class RetainingPathView extends StatelessWidget { } class _PathControlPane extends StatelessWidget { - const _PathControlPane({ - required this.controller, - required this.data, - }); + const _PathControlPane({required this.controller, required this.data}); final PathData data; final RetainingPathController controller; @@ -87,33 +81,36 @@ class _PathControlPane extends StatelessWidget { const SizedBox(width: denseSpacing), ValueListenableBuilder( valueListenable: controller.hideStandard, - builder: (_, hideStandard, _) => DevToolsFilterButton( - onPressed: () { - ga.select( - gac.memory, - '${gac.MemoryEvents.diffPathFilter.name}-$hideStandard', - ); - controller.hideStandard.value = !controller.hideStandard.value; - }, - isFilterActive: hideStandard, - message: 'Hide standard libraries', - ), + builder: + (_, hideStandard, _) => DevToolsFilterButton( + onPressed: () { + ga.select( + gac.memory, + '${gac.MemoryEvents.diffPathFilter.name}-$hideStandard', + ); + controller.hideStandard.value = + !controller.hideStandard.value; + }, + isFilterActive: hideStandard, + message: 'Hide standard libraries', + ), ), const SizedBox(width: denseSpacing), ValueListenableBuilder( valueListenable: controller.invert, - builder: (_, invert, _) => DevToolsToggleButton( - onPressed: () { - ga.select( - gac.memory, - '${gac.MemoryEvents.diffPathInvert.name}-$invert', - ); - controller.invert.value = !controller.invert.value; - }, - isSelected: invert, - message: 'Invert the path', - icon: Icons.swap_horiz, - ), + builder: + (_, invert, _) => DevToolsToggleButton( + onPressed: () { + ga.select( + gac.memory, + '${gac.MemoryEvents.diffPathInvert.name}-$invert', + ); + controller.invert.value = !controller.invert.value; + }, + isSelected: invert, + message: 'Invert the path', + icon: Icons.swap_horiz, + ), ), ], ); @@ -129,10 +126,7 @@ class _PathView extends StatelessWidget { @override Widget build(BuildContext context) { return MultiValueListenableBuilder( - listenables: [ - controller.hideStandard, - controller.invert, - ], + listenables: [controller.hideStandard, controller.invert], builder: (_, values, _) { final hideStandard = values.first as bool; final invert = values.second as bool; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/paths.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/paths.dart index edc5ba8e0f6..b34a367e8a5 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/paths.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/class_details/paths.dart @@ -17,12 +17,13 @@ import '../../controller/class_data.dart'; class _RetainingPathColumn extends ColumnData { _RetainingPathColumn(String className) - : super.wide( - 'Shortest Retaining Path for Instances of $className', - titleTooltip: 'The shortest sequence of objects\n' - 'retaining $className instances from garbage collection.', - alignment: ColumnAlignment.left, - ); + : super.wide( + 'Shortest Retaining Path for Instances of $className', + titleTooltip: + 'The shortest sequence of objects\n' + 'retaining $className instances from garbage collection.', + alignment: ColumnAlignment.left, + ); @override String? getValue(PathData record) => @@ -34,13 +35,14 @@ class _RetainingPathColumn extends ColumnData { class _InstanceColumn extends ColumnData { _InstanceColumn(bool isDiff) - : super( - isDiff ? 'Instance\nDelta' : 'Instances', - titleTooltip: 'Number of instances of the class\n' - 'retained by the path.', - fixedWidthPx: scaleByFontFactor(80.0), - alignment: ColumnAlignment.right, - ); + : super( + isDiff ? 'Instance\nDelta' : 'Instances', + titleTooltip: + 'Number of instances of the class\n' + 'retained by the path.', + fixedWidthPx: scaleByFontFactor(80.0), + alignment: ColumnAlignment.right, + ); @override int getValue(PathData record) => record.objects.instanceCount; @@ -51,12 +53,12 @@ class _InstanceColumn extends ColumnData { class _ShallowSizeColumn extends ColumnData { _ShallowSizeColumn(bool isDiff) - : super( - isDiff ? 'Shallow\nSize Delta' : 'Shallow\nDart Size', - titleTooltip: SizeType.shallow.description, - fixedWidthPx: scaleByFontFactor(80.0), - alignment: ColumnAlignment.right, - ); + : super( + isDiff ? 'Shallow\nSize Delta' : 'Shallow\nDart Size', + titleTooltip: SizeType.shallow.description, + fixedWidthPx: scaleByFontFactor(80.0), + alignment: ColumnAlignment.right, + ); @override int getValue(PathData record) => record.objects.shallowSize; @@ -65,20 +67,18 @@ class _ShallowSizeColumn extends ColumnData { bool get numeric => true; @override - String getDisplayValue(PathData record) => prettyPrintBytes( - getValue(record), - includeUnit: true, - )!; + String getDisplayValue(PathData record) => + prettyPrintBytes(getValue(record), includeUnit: true)!; } class _RetainedSizeColumn extends ColumnData { _RetainedSizeColumn(bool isDiff) - : super( - isDiff ? 'Retained\nSize Delta' : 'Retained\nDart Size', - titleTooltip: SizeType.retained.description, - fixedWidthPx: scaleByFontFactor(80.0), - alignment: ColumnAlignment.right, - ); + : super( + isDiff ? 'Retained\nSize Delta' : 'Retained\nDart Size', + titleTooltip: SizeType.retained.description, + fixedWidthPx: scaleByFontFactor(80.0), + alignment: ColumnAlignment.right, + ); @override int getValue(PathData record) => record.objects.retainedSize; @@ -87,10 +87,8 @@ class _RetainedSizeColumn extends ColumnData { bool get numeric => true; @override - String getDisplayValue(PathData record) => prettyPrintBytes( - getValue(record), - includeUnit: true, - )!; + String getDisplayValue(PathData record) => + prettyPrintBytes(getValue(record), includeUnit: true)!; } class _RetainingPathTableColumns { @@ -133,11 +131,10 @@ class RetainingPathTable extends StatelessWidget { String dataKey, bool isDiff, String className, - ) => - _columnStore.putIfAbsent( - dataKey, - () => _RetainingPathTableColumns(isDiff, className), - ); + ) => _columnStore.putIfAbsent( + dataKey, + () => _RetainingPathTableColumns(isDiff, className), + ); @override Widget build(BuildContext context) { @@ -150,10 +147,11 @@ class RetainingPathTable extends StatelessWidget { data: _data, keyFactory: (e) => ValueKey(e.path), selectionNotifier: selection, - onItemSelected: (_) => ga.select( - gac.memory, - '${gac.MemoryEvents.diffPathSelect.name}-${isDiff ? "diff" : "single"}', - ), + onItemSelected: + (_) => ga.select( + gac.memory, + '${gac.MemoryEvents.diffPathSelect.name}-${isDiff ? "diff" : "single"}', + ), defaultSortColumn: columns.retainedSizeColumn, defaultSortDirection: SortDirection.descending, tallHeaders: true, diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_diff.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_diff.dart index d5f7baabaae..cf52e103212 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_diff.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_diff.dart @@ -19,24 +19,19 @@ import '../controller/class_data.dart'; import '../data/classes_diff.dart'; import 'instances.dart'; -enum _DataPart { - created, - deleted, - delta, - persisted, -} +enum _DataPart { created, deleted, delta, persisted } class _ClassNameColumn extends ColumnData implements ColumnRenderer, ColumnHeaderRenderer { _ClassNameColumn(this.diffData) - : super( - 'Class', - titleTooltip: 'Class name', - fixedWidthPx: scaleByFontFactor(200.0), - alignment: ColumnAlignment.left, - ); + : super( + 'Class', + titleTooltip: 'Class name', + fixedWidthPx: scaleByFontFactor(200.0), + alignment: ColumnAlignment.left, + ); final ClassesTableDiffData diffData; @@ -81,11 +76,11 @@ class _ClassNameColumn extends ColumnData class _InstanceColumn extends ColumnData implements ColumnRenderer { _InstanceColumn(this.dataPart, this.diffData) - : super( - columnTitle(dataPart), - fixedWidthPx: scaleByFontFactor(110.0), - alignment: ColumnAlignment.right, - ); + : super( + columnTitle(dataPart), + fixedWidthPx: scaleByFontFactor(110.0), + alignment: ColumnAlignment.right, + ); final _DataPart dataPart; @@ -146,9 +141,10 @@ class _InstanceColumn extends ColumnData return null; } - final heapCallback = dataPart == _DataPart.deleted - ? diffData.heapBefore - : diffData.heapAfter; + final heapCallback = + dataPart == _DataPart.deleted + ? diffData.heapBefore + : diffData.heapAfter; if (objects is! ObjectSet) { throw StateError( @@ -168,11 +164,11 @@ class _InstanceColumn extends ColumnData class _SizeColumn extends ColumnData { _SizeColumn(this.dataPart, this.sizeType) - : super( - columnTitle(dataPart), - fixedWidthPx: scaleByFontFactor(80.0), - alignment: ColumnAlignment.right, - ); + : super( + columnTitle(dataPart), + fixedWidthPx: scaleByFontFactor(80.0), + alignment: ColumnAlignment.right, + ); final _DataPart dataPart; final SizeType sizeType; @@ -270,16 +266,17 @@ class _SizeGroupTitle extends StatelessWidget { RoundedDropDownButton( isDense: true, value: sizeType, - onChanged: (SizeType? value) => - diffData.selectedSizeType.value = value!, - items: SizeType.values - .map( - (sizeType) => DropdownMenuItem( - value: sizeType, - child: Text(sizeType.displayName), - ), - ) - .toList(), + onChanged: + (SizeType? value) => diffData.selectedSizeType.value = value!, + items: + SizeType.values + .map( + (sizeType) => DropdownMenuItem( + value: sizeType, + child: Text(sizeType.displayName), + ), + ) + .toList(), ), const SizedBox(width: denseSpacing), const Text('Size'), @@ -292,11 +289,7 @@ class _SizeGroupTitle extends StatelessWidget { } class ClassesTableDiff extends StatelessWidget { - ClassesTableDiff({ - super.key, - required this.classes, - required this.diffData, - }) { + ClassesTableDiff({super.key, required this.classes, required this.diffData}) { _columns = { for (final sizeType in SizeType.values) sizeType: ClassesTableDiffColumns(sizeType, diffData), @@ -308,19 +301,13 @@ class ClassesTableDiff extends StatelessWidget { List _columnGroups() { return [ - ColumnGroup.fromText( - title: '', - range: const Range(0, 1), - ), + ColumnGroup.fromText(title: '', range: const Range(0, 1)), ColumnGroup.fromText( title: 'Instances', range: const Range(1, 5), tooltip: nonGcableInstancesColumnTooltip, ), - ColumnGroup( - title: _SizeGroupTitle(diffData), - range: const Range(5, 9), - ), + ColumnGroup(title: _SizeGroupTitle(diffData), range: const Range(5, 9)), ]; } @@ -344,10 +331,11 @@ class ClassesTableDiff extends StatelessWidget { dataKey: dataKey, keyFactory: (e) => Key(e.className.fullName), selectionNotifier: diffData.selection, - onItemSelected: (_) => ga.select( - gac.memory, - gac.MemoryEvents.diffClassDiffSelect.name, - ), + onItemSelected: + (_) => ga.select( + gac.memory, + gac.MemoryEvents.diffClassDiffSelect.name, + ), defaultSortColumn: columns.sizeDeltaColumn, defaultSortDirection: SortDirection.descending, ); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_single.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_single.dart index 8e2dfdb3dc8..cbe13e48890 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_single.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_single.dart @@ -24,12 +24,12 @@ class _ClassNameColumn extends ColumnData ColumnRenderer, ColumnHeaderRenderer { _ClassNameColumn(this.data) - : super( - 'Class', - titleTooltip: 'Class name', - fixedWidthPx: scaleByFontFactor(200.0), - alignment: ColumnAlignment.left, - ); + : super( + 'Class', + titleTooltip: 'Class name', + fixedWidthPx: scaleByFontFactor(200.0), + alignment: ColumnAlignment.left, + ); final ClassesTableSingleData data; @@ -74,12 +74,12 @@ class _ClassNameColumn extends ColumnData class _InstanceColumn extends ColumnData implements ColumnRenderer { _InstanceColumn(this.classData) - : super( - 'Instances', - titleTooltip: nonGcableInstancesColumnTooltip, - fixedWidthPx: scaleByFontFactor(80.0), - alignment: ColumnAlignment.right, - ); + : super( + 'Instances', + titleTooltip: nonGcableInstancesColumnTooltip, + fixedWidthPx: scaleByFontFactor(80.0), + alignment: ColumnAlignment.right, + ); final ClassesTableSingleData classData; @@ -108,12 +108,12 @@ class _InstanceColumn extends ColumnData class _ShallowSizeColumn extends ColumnData { _ShallowSizeColumn() - : super( - 'Shallow Dart Size', - titleTooltip: SizeType.shallow.description, - fixedWidthPx: scaleByFontFactor(120.0), - alignment: ColumnAlignment.right, - ); + : super( + 'Shallow Dart Size', + titleTooltip: SizeType.shallow.description, + fixedWidthPx: scaleByFontFactor(120.0), + alignment: ColumnAlignment.right, + ); @override int getValue(SingleClassData data) => data.objects.shallowSize; @@ -122,20 +122,18 @@ class _ShallowSizeColumn extends ColumnData { bool get numeric => true; @override - String getDisplayValue(SingleClassData data) => prettyPrintBytes( - getValue(data), - includeUnit: true, - )!; + String getDisplayValue(SingleClassData data) => + prettyPrintBytes(getValue(data), includeUnit: true)!; } class _RetainedSizeColumn extends ColumnData { _RetainedSizeColumn(this.classData) - : super( - 'Retained Dart Size', - titleTooltip: SizeType.retained.description, - fixedWidthPx: scaleByFontFactor(130.0), - alignment: ColumnAlignment.right, - ); + : super( + 'Retained Dart Size', + titleTooltip: SizeType.retained.description, + fixedWidthPx: scaleByFontFactor(130.0), + alignment: ColumnAlignment.right, + ); final ClassesTableSingleData classData; @@ -151,8 +149,10 @@ class _RetainedSizeColumn extends ColumnData { final bytes = prettyPrintRetainedSize(value)!; - final percents = - percent(value / classData.totalHeapSize(), fractionDigits: 0); + final percents = percent( + value / classData.totalHeapSize(), + fractionDigits: 0, + ); return '$bytes ($percents)'; } @@ -198,10 +198,11 @@ class ClassesTableSingle extends StatelessWidget { dataKey: dataKey, keyFactory: (e) => Key(e.className.fullName), selectionNotifier: classesData.selection, - onItemSelected: (_) => ga.select( - gac.memory, - gac.MemoryEvents.diffClassSingleSelect.name, - ), + onItemSelected: + (_) => ga.select( + gac.memory, + gac.MemoryEvents.diffClassSingleSelect.name, + ), defaultSortColumn: _columns.retainedSizeColumn, defaultSortDirection: SortDirection.descending, ); 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 2caf3fc06cf..083cd1ff6b7 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 @@ -25,10 +25,11 @@ class HeapInstanceTableCell extends StatelessWidget { super.key, required bool isSelected, this.liveItemsEnabled = true, - }) : _sampleObtainer = _shouldShowMenu(isSelected, objects) - ? SnapshotClassSampler(heapClass, objects, heap()) - : null, - _count = objects.instanceCount; + }) : _sampleObtainer = + _shouldShowMenu(isSelected, objects) + ? SnapshotClassSampler(heapClass, objects, heap()) + : null, + _count = objects.instanceCount; static bool _shouldShowMenu(bool isSelected, ObjectSet objects) => isSelected && objects.instanceCount > 0; @@ -42,10 +43,11 @@ class HeapInstanceTableCell extends StatelessWidget { Widget build(BuildContext context) { return InstanceViewWithContextMenu( count: _count, - menuBuilder: () => _buildHeapInstancesMenu( - sampler: _sampleObtainer, - liveItemsEnabled: liveItemsEnabled, - ), + menuBuilder: + () => _buildHeapInstancesMenu( + sampler: _sampleObtainer, + liveItemsEnabled: liveItemsEnabled, + ), ); } } @@ -62,10 +64,7 @@ List _buildHeapInstancesMenu({ } class _StoreAllAsVariableMenu extends StatelessWidget { - const _StoreAllAsVariableMenu( - this.sampler, { - required this.liveItemsEnabled, - }); + const _StoreAllAsVariableMenu(this.sampler, {required this.liveItemsEnabled}); final SnapshotClassSampler sampler; @@ -86,14 +85,14 @@ class _StoreAllAsVariableMenu extends StatelessWidget { String title, { required bool subclasses, required bool implementers, - }) => - MenuItemButton( - onPressed: () async => await sampler.allLiveToConsole( + }) => MenuItemButton( + onPressed: + () async => await sampler.allLiveToConsole( includeImplementers: implementers, includeSubclasses: subclasses, ), - child: Text(title), - ); + child: Text(title), + ); return SubmenuButton( menuChildren: [ @@ -112,10 +111,7 @@ class _StoreAllAsVariableMenu extends StatelessWidget { } class _StoreAsOneVariableMenu extends StatelessWidget { - const _StoreAsOneVariableMenu( - this.sampler, { - required this.liveItemsEnabled, - }); + const _StoreAsOneVariableMenu(this.sampler, {required this.liveItemsEnabled}); final SnapshotClassSampler sampler; final bool liveItemsEnabled; @@ -132,21 +128,23 @@ class _StoreAsOneVariableMenu extends StatelessWidget { return SubmenuButton( menuChildren: [ MenuItemButton( - onPressed: () => unawaited( - sampler.oneStaticToConsole( - sourceFeature: MemoryAreas.snapshotDiff.name, - ), - ), + onPressed: + () => unawaited( + sampler.oneStaticToConsole( + sourceFeature: MemoryAreas.snapshotDiff.name, + ), + ), child: const Text('Any'), ), MenuItemButton( - onPressed: liveItemsEnabled - ? () => unawaited( + onPressed: + liveItemsEnabled + ? () => unawaited( sampler.oneLiveStaticToConsole( sourceFeature: MemoryAreas.snapshotDiff.name, ), ) - : null, + : null, child: const Text('Any, not garbage collected'), ), ], diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_control_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_control_pane.dart index af6cb243e66..e5a12b3feb0 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_control_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_control_pane.dart @@ -29,10 +29,7 @@ class SnapshotControlPane extends StatelessWidget { children: [ Row( children: [ - _DiffDropdown( - current: current, - controller: controller, - ), + _DiffDropdown(current: current, controller: controller), const SizedBox(width: defaultSpacing), DownloadButton( tooltip: 'Download data in CSV format', @@ -47,9 +44,7 @@ class SnapshotControlPane extends StatelessWidget { ), if (current.heap!.footprint != null) Expanded( - child: _SnapshotSizeView( - footprint: current.heap!.footprint!, - ), + child: _SnapshotSizeView(footprint: current.heap!.footprint!), ), ], ); @@ -59,10 +54,7 @@ class SnapshotControlPane extends StatelessWidget { } class _DiffDropdown extends StatelessWidget { - _DiffDropdown({ - required this.current, - required this.controller, - }) { + _DiffDropdown({required this.current, required this.controller}) { final list = controller.core.snapshots.value; final diffWith = current.diffWith.value; // Check if diffWith was deleted from list. @@ -78,47 +70,47 @@ class _DiffDropdown extends StatelessWidget { controller.core.snapshots.value .whereType() .where((item) => item.isProcessed) - .map( - (item) { - return DropdownMenuItem( - value: item, - child: Text(item == current ? '-' : item.name), - ); - }, - ).toList(); + .map((item) { + return DropdownMenuItem( + value: item, + child: Text(item == current ? '-' : item.name), + ); + }) + .toList(); @override Widget build(BuildContext context) { return ValueListenableBuilder( valueListenable: current.diffWith, - builder: (_, diffWith, _) => Row( - children: [ - const Text('Diff with:'), - const SizedBox(width: defaultSpacing), - RoundedDropDownButton( - isDense: true, - value: current.diffWith.value ?? current, - onChanged: (SnapshotDataItem? value) { - late SnapshotDataItem? newDiffWith; - if ((value ?? current) == current) { - ga.select( - gac.memory, - gac.MemoryEvents.diffSnapshotDiffSelectOff.name, - ); - newDiffWith = null; - } else { - ga.select( - gac.memory, - gac.MemoryEvents.diffSnapshotDiffSelect.name, - ); - newDiffWith = value; - } - controller.setDiffing(current, newDiffWith); - }, - items: items(), + builder: + (_, diffWith, _) => Row( + children: [ + const Text('Diff with:'), + const SizedBox(width: defaultSpacing), + RoundedDropDownButton( + isDense: true, + value: current.diffWith.value ?? current, + onChanged: (SnapshotDataItem? value) { + late SnapshotDataItem? newDiffWith; + if ((value ?? current) == current) { + ga.select( + gac.memory, + gac.MemoryEvents.diffSnapshotDiffSelectOff.name, + ); + newDiffWith = null; + } else { + ga.select( + gac.memory, + gac.MemoryEvents.diffSnapshotDiffSelect.name, + ); + newDiffWith = value; + } + controller.setDiffing(current, newDiffWith); + }, + items: items(), + ), + ], ), - ], - ), ); } } @@ -137,7 +129,8 @@ class _SnapshotSizeView extends StatelessWidget { return Text( items.entries .map( - (e) => '${e.key}: ' + (e) => + '${e.key}: ' '${prettyPrintBytes(e.value, includeUnit: true, kbFractionDigits: 0)}', ) // TODO(polina-c): consider using vertical divider instead of text. diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_list.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_list.dart index 0a10a47dcda..52eaf021134 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_list.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_list.dart @@ -39,9 +39,7 @@ class SnapshotList extends StatelessWidget { child: _ListControlPane(controller: controller), ), ), - Expanded( - child: _SnapshotListItems(controller: controller), - ), + Expanded(child: _SnapshotListItems(controller: controller)), ], ); } @@ -63,17 +61,19 @@ class _ListControlPane extends StatelessWidget { if (!context.mounted) return; await showDialog( context: context, - builder: (context) => UnexpectedErrorDialog( - additionalInfo: - 'Encountered an error while taking a heap snapshot:\n${e.runtimeType}\n$e\n$trace', - ), + builder: + (context) => UnexpectedErrorDialog( + additionalInfo: + 'Encountered an error while taking a heap snapshot:\n${e.runtimeType}\n$e\n$trace', + ), ); } } @override Widget build(BuildContext context) { - final showTakeSnapshotButton = controller.loader != null && + final showTakeSnapshotButton = + controller.loader != null && !offlineDataController.showingOfflineData.value; return Row( children: [ @@ -93,15 +93,16 @@ class _ListControlPane extends StatelessWidget { icon: Icons.delete, size: defaultIconSize, tooltip: 'Delete all snapshots', - onPressed: controller.hasSnapshots - ? () { - ga.select( - gac.memory, - gac.MemoryEvents.diffClearSnapshots.name, - ); - controller.clearSnapshots(); - } - : null, + onPressed: + controller.hasSnapshots + ? () { + ga.select( + gac.memory, + gac.MemoryEvents.diffClearSnapshots.name, + ); + controller.clearSnapshots(); + } + : null, ); }, ), @@ -182,29 +183,28 @@ class SnapshotListTitle extends StatelessWidget { ContextMenuButton.defaultWidth + ContextMenuButton.densePadding; trailing.addAll([ if (theItem.totalSize != null) - Text( - prettyPrintBytes(theItem.totalSize, includeUnit: true)!, - ), + Text(prettyPrintBytes(theItem.totalSize, includeUnit: true)!), Padding( padding: const EdgeInsets.only(left: ContextMenuButton.densePadding), - child: selected - ? ContextMenuButton( - menuChildren: [ - MenuItemButton( - onPressed: onEdit, - child: const Text('Rename'), - ), - MenuItemButton( - onPressed: onDelete, - child: const Text('Delete'), - ), - MenuItemButton( - onPressed: onExport, - child: const Text('Export'), - ), - ], - ) - : const SizedBox(width: menuButtonWidth), + child: + selected + ? ContextMenuButton( + menuChildren: [ + MenuItemButton( + onPressed: onEdit, + child: const Text('Rename'), + ), + MenuItemButton( + onPressed: onDelete, + child: const Text('Delete'), + ), + MenuItemButton( + onPressed: onExport, + child: const Text('Export'), + ), + ], + ) + : const SizedBox(width: menuButtonWidth), ), ]); } else { @@ -384,10 +384,7 @@ class _SnapshotListItemsState extends State<_SnapshotListItems> final core = widget.controller.core; return MultiValueListenableBuilder( - listenables: [ - core.snapshots, - core.selectedSnapshotIndex, - ], + listenables: [core.snapshots, core.selectedSnapshotIndex], builder: (_, values, _) { final snapshots = values.first as List; final selectedIndex = values.second as int; @@ -399,9 +396,10 @@ class _SnapshotListItemsState extends State<_SnapshotListItems> final selected = selectedIndex == index; return Container( height: _headerHeight, - color: selected - ? Theme.of(context).colorScheme.selectedRowBackgroundColor - : null, + color: + selected + ? Theme.of(context).colorScheme.selectedRowBackgroundColor + : null, child: InkWell( canRequestFocus: false, onTap: () { diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_view.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_view.dart index 465d13bc8d6..1242bce7abd 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_view.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/snapshot_view.dart @@ -58,12 +58,13 @@ class SnapshotView extends StatelessWidget { final pathTable = ValueListenableBuilder( valueListenable: controller.derived.classData, - builder: (_, classData, _) => HeapClassDetails( - classData: classData, - pathSelection: controller.derived.selectedPath, - isDiff: classes is ClassDataList, - pathController: controller.retainingPathController, - ), + builder: + (_, classData, _) => HeapClassDetails( + classData: classData, + pathSelection: controller.derived.selectedPath, + isDiff: classes is ClassDataList, + pathController: controller.retainingPathController, + ), ); return SplitPane( @@ -71,12 +72,8 @@ class SnapshotView extends StatelessWidget { initialFractions: const [0.4, 0.6], minSizes: const [80, 80], children: [ - OutlineDecoration.onlyBottom( - child: classTable, - ), - OutlineDecoration.onlyTop( - child: pathTable, - ), + OutlineDecoration.onlyBottom(child: classTable), + OutlineDecoration.onlyTop(child: pathTable), ], ); }, 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 4c0338ff97f..11418ab7730 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 @@ -62,14 +62,14 @@ class _StoreAllAsVariableMenu extends StatelessWidget { String title, { required bool subclasses, required bool implementers, - }) => - MenuItemButton( - onPressed: () async => await sampler.allLiveToConsole( + }) => MenuItemButton( + onPressed: + () async => await sampler.allLiveToConsole( includeImplementers: implementers, includeSubclasses: subclasses, ), - child: Text(title), - ); + child: Text(title), + ); return SubmenuButton( menuChildren: [ @@ -95,9 +95,10 @@ class _StoreAsOneVariableMenu extends StatelessWidget { @override Widget build(BuildContext context) { return MenuItemButton( - onPressed: () => unawaited( - sampler.oneLiveToConsole(sourceFeature: MemoryAreas.profile.name), - ), + onPressed: + () => unawaited( + sampler.oneLiveToConsole(sourceFeature: MemoryAreas.profile.name), + ), child: const Text('Store one instance as a console variable'), ); } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/model.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/model.dart index 9689a292875..681ec6a4a10 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/model.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/model.dart @@ -26,10 +26,10 @@ class AdaptedProfile with Serializable { required this.newSpaceGCStats, required this.oldSpaceGCStats, required this.totalGCStats, - }) : filter = ClassFilter.empty(), - _total = total, - _items = items, - _itemsFiltered = items; + }) : filter = ClassFilter.empty(), + _total = total, + _items = items, + _itemsFiltered = items; factory AdaptedProfile.fromAllocationProfile( AllocationProfile profile, @@ -38,10 +38,11 @@ class AdaptedProfile with Serializable { ) { final adaptedProfile = AdaptedProfile._( total: ProfileRecord.total(profile), - items: (profile.members ?? []) - .where((e) => (e.instancesCurrent ?? 0) > 0) - .map((e) => ProfileRecord.fromClassHeapStats(e)) - .toList(), + items: + (profile.members ?? []) + .where((e) => (e.instancesCurrent ?? 0) > 0) + .map((e) => ProfileRecord.fromClassHeapStats(e)) + .toList(), newSpaceGCStats: profile.newSpaceGCStats, oldSpaceGCStats: profile.oldSpaceGCStats, totalGCStats: profile.totalGCStats, @@ -54,9 +55,9 @@ class AdaptedProfile with Serializable { AdaptedProfile profile, this.filter, String? rootPackage, - ) : newSpaceGCStats = profile.newSpaceGCStats, - oldSpaceGCStats = profile.oldSpaceGCStats, - totalGCStats = profile.totalGCStats { + ) : newSpaceGCStats = profile.newSpaceGCStats, + oldSpaceGCStats = profile.oldSpaceGCStats, + totalGCStats = profile.totalGCStats { _items = profile._items; _total = profile._total; @@ -73,9 +74,10 @@ class AdaptedProfile with Serializable { factory AdaptedProfile.fromJson(Map json) { return AdaptedProfile._( total: ProfileRecord.fromJson(json[_ProfileJson.total]), - items: (json[_ProfileJson.items] as List) - .map((e) => ProfileRecord.fromJson(e)) - .toList(), + items: + (json[_ProfileJson.items] as List) + .map((e) => ProfileRecord.fromJson(e)) + .toList(), newSpaceGCStats: GCStats.fromJson(json[_ProfileJson.newGC]), oldSpaceGCStats: GCStats.fromJson(json[_ProfileJson.oldGC]), totalGCStats: GCStats.fromJson(json[_ProfileJson.totalGC]), @@ -160,7 +162,8 @@ class ProfileRecord with PinnableListEntry, Serializable { isTotal: false, heapClass: HeapClassName.fromClassRef(stats.classRef), totalInstances: stats.instancesCurrent ?? 0, - totalSize: stats.bytesCurrent! + + totalSize: + stats.bytesCurrent! + stats.oldSpace.externalSize + stats.newSpace.externalSize, totalDartHeapSize: stats.bytesCurrent!, @@ -178,22 +181,22 @@ class ProfileRecord with PinnableListEntry, Serializable { } ProfileRecord.total(AllocationProfile profile) - : isTotal = true, - heapClass = - HeapClassName.fromPath(className: 'All Classes', library: ''), - totalInstances = null, - totalSize = (profile.memoryUsage?.externalUsage ?? 0) + - (profile.memoryUsage?.heapUsage ?? 0), - totalDartHeapSize = profile.memoryUsage?.heapUsage ?? 0, - totalExternalSize = profile.memoryUsage?.externalUsage ?? 0, - newSpaceInstances = null, - newSpaceSize = null, - newSpaceDartHeapSize = null, - newSpaceExternalSize = null, - oldSpaceInstances = null, - oldSpaceSize = null, - oldSpaceDartHeapSize = null, - oldSpaceExternalSize = null { + : isTotal = true, + heapClass = HeapClassName.fromPath(className: 'All Classes', library: ''), + totalInstances = null, + totalSize = + (profile.memoryUsage?.externalUsage ?? 0) + + (profile.memoryUsage?.heapUsage ?? 0), + totalDartHeapSize = profile.memoryUsage?.heapUsage ?? 0, + totalExternalSize = profile.memoryUsage?.externalUsage ?? 0, + newSpaceInstances = null, + newSpaceSize = null, + newSpaceDartHeapSize = null, + newSpaceExternalSize = null, + oldSpaceInstances = null, + oldSpaceSize = null, + oldSpaceDartHeapSize = null, + oldSpaceExternalSize = null { _verifyIntegrity(); } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 5c1b6ccf08e..d5775e554f0 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -15,17 +15,11 @@ import '../../shared/heap/class_filter.dart'; import 'model.dart'; @visibleForTesting -enum Json { - profile, - rootPackage; -} +enum Json { profile, rootPackage } class ProfilePaneController extends DisposableController with AutoDisposeControllerMixin, Serializable { - ProfilePaneController({ - required this.rootPackage, - AdaptedProfile? profile, - }) { + ProfilePaneController({required this.rootPackage, AdaptedProfile? profile}) { // [profile] should only be non-null when loading offline data. if (profile != null) { _currentAllocationProfile.value = AdaptedProfile.withNewFilter( diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_view.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_view.dart index 715aaf30dc1..78f8c420c7e 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_view.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_view.dart @@ -37,10 +37,7 @@ class _FieldClassNameColumn extends ColumnData ColumnRenderer, ColumnHeaderRenderer { _FieldClassNameColumn(this.classFilterData) - : super( - 'Class', - fixedWidthPx: scaleByFontFactor(200), - ); + : super('Class', fixedWidthPx: scaleByFontFactor(200)); @override String? getValue(ProfileRecord dataObject) => dataObject.heapClass.className; @@ -107,12 +104,12 @@ enum HeapGeneration { class _FieldInstanceCountColumn extends ColumnData implements ColumnRenderer { _FieldInstanceCountColumn({required this.heap}) - : super( - 'Instances', - titleTooltip: 'The number of instances of the class in the heap', - alignment: ColumnAlignment.right, - fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), - ); + : super( + 'Instances', + titleTooltip: 'The number of instances of the class in the heap', + alignment: ColumnAlignment.right, + fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), + ); final HeapGeneration heap; @@ -150,11 +147,11 @@ class _FieldInstanceCountColumn extends ColumnData class _FieldExternalSizeColumn extends _FieldSizeColumn { _FieldExternalSizeColumn({required super.heap}) - : super._( - title: 'External', - titleTooltip: - 'Non-Dart heap allocated memory associated with a Dart object', - ); + : super._( + title: 'External', + titleTooltip: + 'Non-Dart heap allocated memory associated with a Dart object', + ); @override int? getValue(ProfileRecord dataObject) { @@ -171,10 +168,7 @@ class _FieldExternalSizeColumn extends _FieldSizeColumn { class _FieldDartHeapSizeColumn extends _FieldSizeColumn { _FieldDartHeapSizeColumn({required super.heap}) - : super._( - title: 'Dart Heap', - titleTooltip: SizeType.shallow.description, - ); + : super._(title: 'Dart Heap', titleTooltip: SizeType.shallow.description); @override int? getValue(ProfileRecord dataObject) { @@ -193,7 +187,8 @@ class _FieldSizeColumn extends ColumnData { factory _FieldSizeColumn({required HeapGeneration heap}) => _FieldSizeColumn._( title: 'Total Size', - titleTooltip: "The sum of the type's total shallow memory " + titleTooltip: + "The sum of the type's total shallow memory " 'consumption in the Dart heap and associated external (e.g., ' 'non-Dart heap) allocations', heap: heap, @@ -204,11 +199,11 @@ class _FieldSizeColumn extends ColumnData { required String titleTooltip, required this.heap, }) : super( - title, - titleTooltip: titleTooltip, - alignment: ColumnAlignment.right, - fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), - ); + title, + titleTooltip: titleTooltip, + alignment: ColumnAlignment.right, + fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), + ); final HeapGeneration heap; @@ -259,11 +254,7 @@ abstract class _GCHeapStatsColumn extends ColumnData { } class _GCHeapNameColumn extends ColumnData { - _GCHeapNameColumn() - : super( - '', - fixedWidthPx: scaleByFontFactor(200), - ); + _GCHeapNameColumn() : super('', fixedWidthPx: scaleByFontFactor(200)); @override String? getValue(AdaptedProfile dataObject) { @@ -276,12 +267,12 @@ class _GCHeapNameColumn extends ColumnData { class _GCHeapUsageColumn extends _GCHeapStatsColumn { _GCHeapUsageColumn({required super.generation}) - : super( - 'Usage', - titleTooltip: 'The current amount of memory allocated from the heap', - alignment: ColumnAlignment.right, - fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), - ); + : super( + 'Usage', + titleTooltip: 'The current amount of memory allocated from the heap', + alignment: ColumnAlignment.right, + fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), + ); @override int? getValue(AdaptedProfile dataObject) { @@ -299,13 +290,13 @@ class _GCHeapUsageColumn extends _GCHeapStatsColumn { class _GCHeapCapacityColumn extends _GCHeapStatsColumn { _GCHeapCapacityColumn({required super.generation}) - : super( - 'Capacity', - titleTooltip: - 'The current size of the heap, including unallocated memory', - alignment: ColumnAlignment.right, - fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), - ); + : super( + 'Capacity', + titleTooltip: + 'The current size of the heap, including unallocated memory', + alignment: ColumnAlignment.right, + fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), + ); @override int? getValue(AdaptedProfile dataObject) { @@ -323,12 +314,12 @@ class _GCHeapCapacityColumn extends _GCHeapStatsColumn { class _GCCountColumn extends _GCHeapStatsColumn { _GCCountColumn({required super.generation}) - : super( - 'Collections', - titleTooltip: 'The number of garbage collections run on the heap', - alignment: ColumnAlignment.right, - fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), - ); + : super( + 'Collections', + titleTooltip: 'The number of garbage collections run on the heap', + alignment: ColumnAlignment.right, + fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), + ); @override int? getValue(AdaptedProfile dataObject) { @@ -341,13 +332,13 @@ class _GCCountColumn extends _GCHeapStatsColumn { class _GCLatencyColumn extends _GCHeapStatsColumn { _GCLatencyColumn({required super.generation}) - : super( - 'Latency', - titleTooltip: - 'The average time taken to perform a garbage collection on the heap (ms)', - alignment: ColumnAlignment.right, - fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), - ); + : super( + 'Latency', + titleTooltip: + 'The average time taken to perform a garbage collection on the heap (ms)', + alignment: ColumnAlignment.right, + fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), + ); @override double? getValue(AdaptedProfile dataObject) { @@ -361,9 +352,7 @@ class _GCLatencyColumn extends _GCHeapStatsColumn { @override String getDisplayValue(AdaptedProfile dataObject) { return durationText( - Duration( - milliseconds: getValue(dataObject)!.toInt(), - ), + Duration(milliseconds: getValue(dataObject)!.toInt()), fractionDigits: 2, ); } @@ -373,15 +362,10 @@ class _GCLatencyColumn extends _GCHeapStatsColumn { } class _GCStatsTable extends StatelessWidget { - const _GCStatsTable({ - required this.controller, - }); + const _GCStatsTable({required this.controller}); static final _columnGroup = [ - ColumnGroup.fromText( - title: '', - range: const Range(0, 1), - ), + ColumnGroup.fromText(title: '', range: const Range(0, 1)), ColumnGroup.fromText( title: HeapGeneration.total.toString(), range: const Range(1, 5), @@ -405,12 +389,8 @@ class _GCStatsTable extends StatelessWidget { ]) ...[ _GCHeapUsageColumn(generation: generation), _GCHeapCapacityColumn(generation: generation), - _GCCountColumn( - generation: generation, - ), - _GCLatencyColumn( - generation: generation, - ), + _GCCountColumn(generation: generation), + _GCLatencyColumn(generation: generation), ], ]; @@ -475,9 +455,7 @@ class AllocationProfileTableViewState children: [ Padding( padding: const EdgeInsets.all(denseSpacing), - child: _AllocationProfileTableControls( - controller: widget.controller, - ), + child: _AllocationProfileTableControls(controller: widget.controller), ), ValueListenableBuilder( valueListenable: preferences.vmDeveloperModeEnabled, @@ -491,36 +469,25 @@ class AllocationProfileTableViewState // ensure the underlying scrollable area has enough space to not // display a scroll bar. height: defaultRowHeight + defaultHeaderHeight * 2 + 1, - child: _GCStatsTable( - controller: widget.controller, - ), + child: _GCStatsTable(controller: widget.controller), ), const ThickDivider(), ], ); }, ), - Expanded( - child: _AllocationProfileTable( - controller: widget.controller, - ), - ), + Expanded(child: _AllocationProfileTable(controller: widget.controller)), ], ); } } class _AllocationProfileTable extends StatelessWidget { - _AllocationProfileTable({ - required this.controller, - }); + _AllocationProfileTable({required this.controller}); /// List of columns displayed in VM developer mode state. static final _vmModeColumnGroups = [ - ColumnGroup.fromText( - title: '', - range: const Range(0, 1), - ), + ColumnGroup.fromText(title: '', range: const Range(0, 1)), ColumnGroup.fromText( title: HeapGeneration.total.toString(), range: const Range(1, 5), @@ -535,9 +502,7 @@ class _AllocationProfileTable extends StatelessWidget { ), ]; - static final _fieldSizeColumn = _FieldSizeColumn( - heap: HeapGeneration.total, - ); + static final _fieldSizeColumn = _FieldSizeColumn(heap: HeapGeneration.total); late final _columns = >[ _FieldClassNameColumn( @@ -584,9 +549,10 @@ class _AllocationProfileTable extends StatelessWidget { keyFactory: (element) => Key(element.heapClass.fullName), data: profile.records, dataKey: 'allocation-profile', - columnGroups: vmDeveloperModeEnabled - ? _AllocationProfileTable._vmModeColumnGroups - : null, + columnGroups: + vmDeveloperModeEnabled + ? _AllocationProfileTable._vmModeColumnGroups + : null, columns: [ ..._columns, if (vmDeveloperModeEnabled) ..._vmDeveloperModeColumns, @@ -605,9 +571,7 @@ class _AllocationProfileTable extends StatelessWidget { } class _AllocationProfileTableControls extends StatelessWidget { - const _AllocationProfileTableControls({ - required this.controller, - }); + const _AllocationProfileTableControls({required this.controller}); final ProfilePaneController controller; @@ -615,9 +579,7 @@ class _AllocationProfileTableControls extends StatelessWidget { Widget build(BuildContext context) { return Row( children: [ - _ExportAllocationProfileButton( - allocationProfileController: controller, - ), + _ExportAllocationProfileButton(allocationProfileController: controller), if (!offlineDataController.showingOfflineData.value) ...[ const SizedBox(width: denseSpacing), RefreshButton( @@ -626,9 +588,7 @@ class _AllocationProfileTableControls extends StatelessWidget { onPressed: controller.refresh, ), const SizedBox(width: denseSpacing), - _RefreshOnGCToggleButton( - allocationProfileController: controller, - ), + _RefreshOnGCToggleButton(allocationProfileController: controller), ], const SizedBox(width: denseSpacing), const _ProfileHelpLink(), @@ -655,10 +615,12 @@ class _ExportAllocationProfileButton extends StatelessWidget { minScreenWidthForTextBeforeScaling: memoryControlsMinVerboseWidth, tooltip: 'Download allocation profile data in CSV format', label: 'CSV', - onPressed: currentAllocationProfile == null - ? null - : () => allocationProfileController - .downloadMemoryTableCsv(currentAllocationProfile), + onPressed: + currentAllocationProfile == null + ? null + : () => allocationProfileController.downloadMemoryTableCsv( + currentAllocationProfile, + ), ); }, ); @@ -666,9 +628,7 @@ class _ExportAllocationProfileButton extends StatelessWidget { } class _RefreshOnGCToggleButton extends StatelessWidget { - const _RefreshOnGCToggleButton({ - required this.allocationProfileController, - }); + const _RefreshOnGCToggleButton({required this.allocationProfileController}); final ProfilePaneController allocationProfileController; @@ -702,15 +662,17 @@ class _ProfileHelpLink extends StatelessWidget { Widget build(BuildContext context) { return HelpButtonWithDialog( gaScreen: gac.memory, - gaSelection: - gac.topicDocumentationButton(gac.MemoryEvents.profileHelp.name), + gaSelection: gac.topicDocumentationButton( + gac.MemoryEvents.profileHelp.name, + ), dialogTitle: 'Memory Allocation Profile Help', actions: [ MoreInfoLink( url: DocLinks.profile.value, gaScreenName: '', - gaSelectedItemDescription: - gac.topicDocumentationLink(gac.MemoryEvents.profileHelp.name), + gaSelectedItemDescription: gac.topicDocumentationLink( + gac.MemoryEvents.profileHelp.name, + ), ), ], child: const Column( diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart index 194d61be28b..ad724ab1178 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart @@ -23,13 +23,13 @@ const _defaultNumberFieldWidth = 70.0; class _TraceCheckBoxColumn extends ColumnData implements ColumnRenderer { _TraceCheckBoxColumn({required this.controller}) - : super( - 'Trace', - titleTooltip: - 'Enable or disable allocation tracing for a specific type', - fixedWidthPx: scaleByFontFactor(40.0), - alignment: ColumnAlignment.left, - ); + : super( + 'Trace', + titleTooltip: + 'Enable or disable allocation tracing for a specific type', + fixedWidthPx: scaleByFontFactor(40.0), + alignment: ColumnAlignment.left, + ); final TracePaneController controller; @@ -99,12 +99,12 @@ class _ClassNameColumn extends ColumnData class _InstancesColumn extends ColumnData { _InstancesColumn() - : super( - 'Delta', - titleTooltip: - 'Number of instances, allocated after the class was selected for tracing.', - fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), - ); + : super( + 'Delta', + titleTooltip: + 'Number of instances, allocated after the class was selected for tracing.', + fixedWidthPx: scaleByFontFactor(_defaultNumberFieldWidth), + ); @override int getValue(TracedClass dataObject) { @@ -135,8 +135,9 @@ class _AllocationTracingTableState extends State { void initState() { super.initState(); - _classNameColumn = - _ClassNameColumn(rootPackage: widget.controller.rootPackage); + _classNameColumn = _ClassNameColumn( + rootPackage: widget.controller.rootPackage, + ); _checkboxColumn = _TraceCheckBoxColumn(controller: widget.controller); columns = >[ @@ -152,10 +153,7 @@ class _AllocationTracingTableState extends State { void _sendFilterEditGaEvent() { final now = DateTime.now(); if (now.difference(_editFilterGaSent) < _editFilterGaThrottling) return; - ga.select( - gac.memory, - gac.MemoryEvents.tracingClassFilter.name, - ); + ga.select(gac.memory, gac.MemoryEvents.tracingClassFilter.name); _editFilterGaSent = now; } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart index 438e5bfa205..31495ba47c5 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart @@ -16,19 +16,14 @@ import '../../../profiler/cpu_profile_model.dart'; import '../../../profiler/cpu_profile_transformer.dart'; @visibleForTesting -enum TracedClassJson { - clazz, - instances, - allocations, -} +enum TracedClassJson { clazz, instances, allocations } /// A representation of a class and it's allocation tracing state. class TracedClass with PinnableListEntry, Serializable { - TracedClass({ - required this.clazz, - }) : traceAllocations = false, - instances = 0, - name = HeapClassName.fromClassRef(clazz); + TracedClass({required this.clazz}) + : traceAllocations = false, + instances = 0, + name = HeapClassName.fromClassRef(clazz); TracedClass._({ required this.clazz, @@ -39,8 +34,9 @@ class TracedClass with PinnableListEntry, Serializable { factory TracedClass.fromJson(Map json) { return TracedClass._( instances: json[TracedClassJson.instances.name] as int, - clazz: ClassRefEncodeDecode.instance - .decode(json[TracedClassJson.clazz.name]), + clazz: ClassRefEncodeDecode.instance.decode( + json[TracedClassJson.clazz.name], + ), traceAllocations: json[TracedClassJson.allocations.name] as bool, ); } @@ -92,11 +88,7 @@ class TracedClass with PinnableListEntry, Serializable { // TODO(kenz): include the selected class in the toJson and fromJson methods. @visibleForTesting -enum TracingIsolateStateJson { - isolate, - classes, - profiles; -} +enum TracingIsolateStateJson { isolate, classes, profiles } /// Contains allocation tracing state for a single isolate. /// @@ -118,17 +110,19 @@ class TracingIsolateState with Serializable { factory TracingIsolateState.fromJson(Map json) { return TracingIsolateState( - isolate: IsolateRefEncodeDecode.instance - .decode(json[TracingIsolateStateJson.isolate.name]), + isolate: IsolateRefEncodeDecode.instance.decode( + json[TracingIsolateStateJson.isolate.name], + ), profiles: (json[TracingIsolateStateJson.profiles.name] as Map).map( (key, value) => MapEntry( key, deserialize(value, CpuProfileData.fromJson), ), ), - classes: (json[TracingIsolateStateJson.classes.name] as List) - .map((e) => deserialize(e, TracedClass.fromJson)) - .toList(), + classes: + (json[TracingIsolateStateJson.classes.name] as List) + .map((e) => deserialize(e, TracedClass.fromJson)) + .toList(), ); } @@ -207,9 +201,7 @@ class TracingIsolateState with Serializable { (newFilter.caseInsensitiveContains(currentFilter) && !force ? _filteredClassList.value : classes) - .where( - (e) => e.clazz.name!.caseInsensitiveContains(newFilter), - ) + .where((e) => e.clazz.name!.caseInsensitiveContains(newFilter)) .map((e) => classesById[e.clazz.id!]!) .toList(); @@ -254,9 +246,7 @@ class TracingIsolateState with Serializable { // Only update if the tracing state has changed for `clazz`. if (tracedClass.traceAllocations != enabled) { await service.setTraceClassAllocation(isolate.id!, clazz.id!, enabled); - final update = tracedClass.copyWith( - traceAllocations: enabled, - ); + final update = tracedClass.copyWith(traceAllocations: enabled); _updateClassState(tracedClass, update); } } @@ -280,8 +270,13 @@ class TracingIsolateState with Serializable { ); } final service = serviceConnection.serviceManager.service!; - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!; + final isolateId = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!; final clazz = tracedClass.clazz; // Note: we need to provide `timeExtentMicros` to `getAllocationTraces`, 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 50e1d72e219..8ab21627762 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 @@ -15,11 +15,7 @@ import '../../../../shared/globals.dart'; import 'tracing_data.dart'; @visibleForTesting -enum Json { - stateForIsolate, - selection, - rootPackage; -} +enum Json { stateForIsolate, selection, rootPackage } class TracePaneController extends DisposableController with AutoDisposeControllerMixin, Serializable { @@ -29,10 +25,9 @@ class TracePaneController extends DisposableController required this.rootPackage, }) { this.stateForIsolate = stateForIsolate ?? {}; - final isolate = this - .stateForIsolate - .values - .firstWhereOrNull((i) => i.isolate.id == selectedIsolateId); + final isolate = this.stateForIsolate.values.firstWhereOrNull( + (i) => i.isolate.id == selectedIsolateId, + ); if (selectedIsolateId != null && isolate == null) { throw ArgumentError( '$selectedIsolateId must be a key in stateForIsolate', diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_tree.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_tree.dart index 811171916b7..e86d1a39330 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_tree.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_tree.dart @@ -28,10 +28,7 @@ class AllocationTracingTree extends StatefulWidget { static final _bottomUpTab = _buildTab(tabName: 'Bottom Up'); static final _callTreeTab = _buildTab(tabName: 'Call Tree'); - static final tabs = [ - _bottomUpTab, - _callTreeTab, - ]; + static final tabs = [_bottomUpTab, _callTreeTab]; static DevToolsTab _buildTab({Key? key, required String tabName}) { return DevToolsTab.create( @@ -78,7 +75,8 @@ class _AllocationTracingTreeState extends State return const _TracingInstructions(); } else if (!selection.traceAllocations) { return _TracingInstructions( - prefix: 'Allocation tracing is not enabled for class ' + prefix: + 'Allocation tracing is not enabled for class ' '${selection.clazz.name}.', ); } else if (selection.traceAllocations && @@ -124,9 +122,7 @@ class _AllocationTracingTreeState extends State } class _TracingInstructions extends StatelessWidget { - const _TracingInstructions({ - this.prefix, - }); + const _TracingInstructions({this.prefix}); final String? prefix; @@ -138,9 +134,7 @@ class _TracingInstructions extends StatelessWidget { } return Markdown( data: data, - styleSheet: MarkdownStyleSheet( - p: Theme.of(context).regularTextStyle, - ), + styleSheet: MarkdownStyleSheet(p: Theme.of(context).regularTextStyle), ); } } @@ -180,9 +174,7 @@ class _TracingTreeHeader extends StatelessWidget { title: Text.rich( TextSpan( children: [ - const TextSpan( - text: 'Traced allocations for: ', - ), + const TextSpan(text: 'Traced allocations for: '), TextSpan( style: theme.fixedFontStyle, text: controller.selection.value.selectedClass.value?.clazz.name!, @@ -204,25 +196,23 @@ class _TracingTreeHeader extends StatelessWidget { ExpandAllButton( gaScreen: gac.memory, gaSelection: gac.MemoryEvents.tracingTreeExpandAll.name, - onPressed: () => updateTreeStateCallback( - () { - for (final root in _currentDataRoots) { - root.expandCascading(); - } - }, - ), + onPressed: + () => updateTreeStateCallback(() { + for (final root in _currentDataRoots) { + root.expandCascading(); + } + }), ), const SizedBox(width: denseSpacing), CollapseAllButton( gaScreen: gac.memory, gaSelection: gac.MemoryEvents.tracingTreeCollapseAll.name, - onPressed: () => updateTreeStateCallback( - () { - for (final root in _currentDataRoots) { - root.collapseCascading(); - } - }, - ), + onPressed: + () => updateTreeStateCallback(() { + for (final root in _currentDataRoots) { + root.collapseCascading(); + } + }), ), ], ); @@ -238,11 +228,11 @@ class _TracingTreeHeader extends StatelessWidget { class _InclusiveCountColumn extends ColumnData { _InclusiveCountColumn() - : super( - 'Inclusive', - titleTooltip: _tooltip, - fixedWidthPx: scaleByFontFactor(_countColumnWidth), - ); + : super( + 'Inclusive', + titleTooltip: _tooltip, + fixedWidthPx: scaleByFontFactor(_countColumnWidth), + ); static const _tooltip = 'The number of instances allocated by calls made from a stack frame.'; @@ -271,11 +261,11 @@ class _InclusiveCountColumn extends ColumnData { class _ExclusiveCountColumn extends ColumnData { _ExclusiveCountColumn() - : super( - 'Exclusive', - titleTooltip: _tooltip, - fixedWidthPx: scaleByFontFactor(_countColumnWidth), - ); + : super( + 'Exclusive', + titleTooltip: _tooltip, + fixedWidthPx: scaleByFontFactor(_countColumnWidth), + ); static const _tooltip = 'The number of instances allocated directly by a stack frame.'; @@ -304,10 +294,7 @@ class _ExclusiveCountColumn extends ColumnData { /// A table of an allocation profile tree. class TracingTable extends StatelessWidget { - const TracingTable({ - super.key, - required this.dataRoots, - }); + const TracingTable({super.key, required this.dataRoots}); static final treeColumn = MethodAndSourceColumn(); static final startingSortColumn = _InclusiveCountColumn(); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_view.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_view.dart index bcfac97142d..eb72f9dbe92 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_view.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_view.dart @@ -17,10 +17,7 @@ import 'tracing_pane_controller.dart'; import 'tracing_tree.dart'; class TracingPane extends StatefulWidget { - const TracingPane({ - super.key, - required this.controller, - }); + const TracingPane({super.key, required this.controller}); final TracePaneController controller; @@ -49,7 +46,7 @@ class TracingPaneState extends State { Widget build(BuildContext context) { final isProfileMode = serviceConnection.serviceManager.connectedApp?.isProfileBuildNow ?? - false; + false; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -64,14 +61,10 @@ class TracingPaneState extends State { initialFractions: const [0.25, 0.75], children: [ OutlineDecoration.onlyRight( - child: AllocationTracingTable( - controller: widget.controller, - ), + child: AllocationTracingTable(controller: widget.controller), ), OutlineDecoration.onlyLeft( - child: AllocationTracingTree( - controller: widget.controller, - ), + child: AllocationTracingTree(controller: widget.controller), ), ], ), @@ -136,8 +129,9 @@ class _ProfileHelpLink extends StatelessWidget { MoreInfoLink( url: DocLinks.trace.value, gaScreenName: gac.memory, - gaSelectedItemDescription: - gac.topicDocumentationLink(_documentationTopic), + gaSelectedItemDescription: gac.topicDocumentationLink( + _documentationTopic, + ), ), ], child: const Column( diff --git a/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart b/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart index 58fb31466c0..fb67ae19a11 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart @@ -8,11 +8,7 @@ import 'package:flutter/foundation.dart'; import '../../../../shared/memory/class_name.dart'; -enum ClassFilterType { - showAll, - except, - only, -} +enum ClassFilterType { showAll, except, only } class ClassFilterData { ClassFilterData({ @@ -57,29 +53,29 @@ class ClassFilter with Serializable { required this.filterType, required String except, required String? only, - }) : except = _trimByLine(except), - only = only == null ? null : _trimByLine(only); + }) : except = _trimByLine(except), + only = only == null ? null : _trimByLine(only); ClassFilter.theDefault() - : this( - filterType: _defaultFilterType, - except: defaultExceptString, - only: null, - ); + : this( + filterType: _defaultFilterType, + except: defaultExceptString, + only: null, + ); ClassFilter.empty() - : this( - filterType: ClassFilterType.showAll, - except: defaultExceptString, - only: null, - ); + : this( + filterType: ClassFilterType.showAll, + except: defaultExceptString, + only: null, + ); factory ClassFilter.fromJson(Map json) { final type = json[_Json.type] as String?; return ClassFilter( filterType: ClassFilterType.values.lastWhereOrNull((t) => t.name == type) ?? - _defaultFilterType, + _defaultFilterType, except: json[_Json.except] as String? ?? defaultExceptString, only: json[_Json.only] as String?, ); @@ -132,13 +128,14 @@ class ClassFilter with Serializable { int get hashCode => Object.hash(filterType, except, only); Set _filtersAsSet() { - Set stringToSet(String? s) => s == null - ? {} - : s - .split(RegExp(',|\n')) - .map((e) => e.trim()) - .where((e) => e.isNotEmpty) - .toSet(); + Set stringToSet(String? s) => + s == null + ? {} + : s + .split(RegExp(',|\n')) + .map((e) => e.trim()) + .where((e) => e.isNotEmpty) + .toSet(); switch (filterType) { case ClassFilterType.showAll: @@ -240,9 +237,10 @@ class ClassFilter with Serializable { throw StateError('Unexpected task: $task.'); } - final result = dataToFilter - .where((e) => newFilter.apply(extractClass(e), rootPackage)) - .toList(); + final result = + dataToFilter + .where((e) => newFilter.apply(extractClass(e), rootPackage)) + .toList(); return result; } diff --git a/packages/devtools_app/lib/src/screens/memory/shared/heap/sampler.dart b/packages/devtools_app/lib/src/screens/memory/shared/heap/sampler.dart index d8d6229391f..94870ccac44 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/heap/sampler.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/heap/sampler.dart @@ -32,13 +32,10 @@ class _HeapObjects { } class LiveClassSampler { - LiveClassSampler( - this.heapClass, { - ObjectSet? objects, - HeapData? heap, - }) : assert(objects?.indexes.isNotEmpty ?? true), - assert((objects == null) == (heap == null)), - _objects = objects == null ? null : _HeapObjects(objects, heap!); + LiveClassSampler(this.heapClass, {ObjectSet? objects, HeapData? heap}) + : assert(objects?.indexes.isNotEmpty ?? true), + assert((objects == null) == (heap == null)), + _objects = objects == null ? null : _HeapObjects(objects, heap!); final HeapClassName heapClass; final _HeapObjects? _objects; @@ -55,11 +52,10 @@ class LiveClassSampler { final object = (await serviceConnection.serviceManager.service!.getInstances( - isolateId, - theClass.id!, - 1, - )) - .instances?[0]; + isolateId, + theClass.id!, + 1, + )).instances?[0]; if (object is InstanceRef) return object; return null; @@ -109,8 +105,9 @@ class LiveClassSampler { } bool get isEvalEnabled => - heapClass - .classType(serviceConnection.serviceManager.rootInfoNow().package) != + heapClass.classType( + serviceConnection.serviceManager.rootInfoNow().package, + ) != ClassType.runtime; Future allLiveToConsole({ @@ -161,11 +158,8 @@ class LiveClassSampler { } class SnapshotClassSampler extends LiveClassSampler { - SnapshotClassSampler( - super.heapClass, - ObjectSet objects, - HeapData heap, - ) : super(heap: heap, objects: objects); + SnapshotClassSampler(super.heapClass, ObjectSet objects, HeapData heap) + : super(heap: heap, objects: objects); Future oneLiveStaticToConsole({required String sourceFeature}) async { ga.select( @@ -176,11 +170,13 @@ class SnapshotClassSampler extends LiveClassSampler { final heapObjects = _objects!; final instances = (await _liveInstances())?.instances; - final instanceRef = instances?.firstWhereOrNull( - (objRef) => - objRef is InstanceRef && - heapObjects.codes.contains(objRef.identityHashCode), - ) as InstanceRef?; + final instanceRef = + instances?.firstWhereOrNull( + (objRef) => + objRef is InstanceRef && + heapObjects.codes.contains(objRef.identityHashCode), + ) + as InstanceRef?; if (instanceRef == null) { serviceConnection.consoleService.appendStdio( diff --git a/packages/devtools_app/lib/src/screens/memory/shared/primitives/instance_context_menu.dart b/packages/devtools_app/lib/src/screens/memory/shared/primitives/instance_context_menu.dart index 3ff1b0398fb..b6397c635a9 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/primitives/instance_context_menu.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/primitives/instance_context_menu.dart @@ -30,12 +30,7 @@ class InstanceViewWithContextMenu extends StatelessWidget { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, children: [ - Expanded( - child: Text( - nf.format(count), - textAlign: TextAlign.end, - ), - ), + Expanded(child: Text(nf.format(count), textAlign: TextAlign.end)), if (shouldShowMenu) ContextMenuButton( // ignore: avoid_redundant_argument_values, ensures consistency with [SizedBox] below. 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 3b7573ec7b0..0831100124a 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 @@ -16,17 +16,16 @@ class MemoryTimeline with Serializable { factory MemoryTimeline.fromJson(Map json) { return MemoryTimeline( - data: (json[_jsonData] as List) - .map((e) => HeapSample.fromJson(e as Map)) - .toList(), + data: + (json[_jsonData] as List) + .map((e) => HeapSample.fromJson(e as Map)) + .toList(), ); } @override Map toJson() { - return { - _jsonData: data, - }; + return {_jsonData: data}; } static const _jsonData = 'data'; @@ -79,10 +78,8 @@ class MemoryTimeline with Serializable { static bool isCustomEvent(String extensionEvent) => extensionEvent.startsWith(devToolsExtensionEvent); - static String customEventName(String extensionEventKind) => - extensionEventKind.substring( - MemoryTimeline.devToolsExtensionEvent.length, - ); + static String customEventName(String extensionEventKind) => extensionEventKind + .substring(MemoryTimeline.devToolsExtensionEvent.length); void addSample(HeapSample sample) { data.add(sample); @@ -95,9 +92,15 @@ class MemoryTimeline with Serializable { Map json, { String? customEventName, }) { - final extensionEvent = customEventName == null - ? ExtensionEvent(timestamp, eventKind, json) - : ExtensionEvent.custom(timestamp, eventKind, customEventName, json); + final extensionEvent = + customEventName == null + ? ExtensionEvent(timestamp, eventKind, json) + : ExtensionEvent.custom( + timestamp, + eventKind, + customEventName, + json, + ); _extensionEvents.add(extensionEvent); } @@ -119,11 +122,6 @@ class MemoryTimeline with Serializable { void addGCEvent() { final timestamp = DateTime.now().millisecondsSinceEpoch; - _eventSamples.add( - EventSample.gcEvent( - timestamp, - events: extensionEvents, - ), - ); + _eventSamples.add(EventSample.gcEvent(timestamp, events: extensionEvents)); } } diff --git a/packages/devtools_app/lib/src/screens/memory/shared/primitives/painting.dart b/packages/devtools_app/lib/src/screens/memory/shared/primitives/painting.dart index 55181d48acf..842f1e48a8f 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/primitives/painting.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/primitives/painting.dart @@ -10,18 +10,9 @@ const _dashWidth = 5.0; const _spaceBetweenDash = 3.0; Widget createDashWidget(Color color) { - final dash = Container( - width: _dashWidth, - height: _dashHeight, - color: color, - ); - const space = SizedBox( - width: _spaceBetweenDash, - height: _dashHeight, - ); - return Row( - children: [dash, space, dash, space, dash], - ); + final dash = Container(width: _dashWidth, height: _dashHeight, color: color); + const space = SizedBox(width: _spaceBetweenDash, height: _dashHeight); + return Row(children: [dash, space, dash, space, dash]); } Widget createSolidLine(Color color) { @@ -59,9 +50,10 @@ class DashedLine extends CustomPainter { @override void paint(Canvas canvas, Size size) { double startX = 0; - final paint = Paint() - ..color = _color - ..strokeWidth = _dashHeight; + final paint = + Paint() + ..color = _color + ..strokeWidth = _dashHeight; while (_totalWidth >= 0) { canvas.drawLine(Offset(startX, 0), Offset(startX + _dashWidth, 0), paint); diff --git a/packages/devtools_app/lib/src/screens/memory/shared/primitives/simple_elements.dart b/packages/devtools_app/lib/src/screens/memory/shared/primitives/simple_elements.dart index 685288fff49..a91e7013ff2 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/primitives/simple_elements.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/primitives/simple_elements.dart @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -const nonGcableInstancesColumnTooltip = 'Number of instances of the class,\n' +const nonGcableInstancesColumnTooltip = + 'Number of instances of the class,\n' 'that are reachable, i.e. have a retaining path from the root\n' "and therefore can't be garbage collected."; @@ -12,7 +13,8 @@ const memoryControlsMinVerboseWidth = 240.0; enum SizeType { shallow( displayName: 'Shallow', - description: 'The total shallow size of all of the instances.\n' + description: + 'The total shallow size of all of the instances.\n' 'The shallow size of an object is the size of the object\n' 'plus the references it holds to other Dart objects\n' "in its fields (this doesn't include the size of\n" @@ -23,8 +25,7 @@ enum SizeType { description: 'Total shallow Dart size of objects plus shallow Dart size of objects they retain,\n' 'taking into account only the shortest retaining path for the referenced objects.', - ), - ; + ); const SizeType({required this.displayName, required this.description}); diff --git a/packages/devtools_app/lib/src/screens/memory/shared/widgets/class_filter.dart b/packages/devtools_app/lib/src/screens/memory/shared/widgets/class_filter.dart index 9d4325fd635..c35ded8c2ff 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/widgets/class_filter.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/widgets/class_filter.dart @@ -20,7 +20,7 @@ String _adaptRootPackageForFilter(String? rootPackage) { class ClassFilterButton extends StatelessWidget { ClassFilterButton(this.data, {super.key}) - : _rootPackage = _adaptRootPackageForFilter(data.rootPackage); + : _rootPackage = _adaptRootPackageForFilter(data.rootPackage); final ClassFilterData data; final String _rootPackage; @@ -32,19 +32,17 @@ class ClassFilterButton extends StatelessWidget { builder: (context, filter, _) { return DevToolsFilterButton( onPressed: () { - ga.select( - gac.memory, - gac.MemoryEvents.diffSnapshotFilter.name, - ); + ga.select(gac.memory, gac.MemoryEvents.diffSnapshotFilter.name); unawaited( showDialog( context: context, - builder: (context) => ClassFilterDialog( - filter, - onChanged: data.onChanged, - rootPackage: _rootPackage, - ), + builder: + (context) => ClassFilterDialog( + filter, + onChanged: data.onChanged, + rootPackage: _rootPackage, + ), ), ); }, @@ -114,27 +112,24 @@ class _ClassFilterDialogState extends State { ); Widget textField(TextEditingController controller) => Padding( - padding: EdgeInsets.only(left: textFieldLeftPadding), - child: TextField( - style: Theme.of(context).regularTextStyle, - decoration: const InputDecoration( - contentPadding: EdgeInsets.all(denseSpacing), - border: OutlineInputBorder(), - ), - keyboardType: TextInputType.multiline, - maxLines: null, - controller: controller, - ), - ); + padding: EdgeInsets.only(left: textFieldLeftPadding), + child: TextField( + style: Theme.of(context).regularTextStyle, + decoration: const InputDecoration( + contentPadding: EdgeInsets.all(denseSpacing), + border: OutlineInputBorder(), + ), + keyboardType: TextInputType.multiline, + maxLines: null, + controller: controller, + ), + ); return StateUpdateDialog( title: 'Filter Classes and Packages', helpBuilder: _helpBuilder, onResetDefaults: () { - ga.select( - gac.memory, - gac.MemoryEvents.diffSnapshotFilterReset.name, - ); + ga.select(gac.memory, gac.MemoryEvents.diffSnapshotFilterReset.name); setState(() => _loadStateFromFilter(ClassFilter.theDefault())); }, onApply: () { @@ -176,10 +171,7 @@ Widget _helpBuilder(BuildContext context) { (t) => Row( children: [ t.icon, - Text( - ' ${t.alias} - for ${t.aliasDescription}', - style: textStyle, - ), + Text(' ${t.alias} - for ${t.aliasDescription}', style: textStyle), CopyToClipboardControl( dataProvider: () => t.alias, size: tableIconSize, @@ -191,7 +183,8 @@ Widget _helpBuilder(BuildContext context) { ); } -const _helpText = 'Choose and customize the filter.\n' +const _helpText = + 'Choose and customize the filter.\n' 'List full or partial class names separated by new lines. For example:\n\n' ' package:myPackage/src/myFolder/myLibrary.dart/MyClass\n' ' MyClass\n' diff --git a/packages/devtools_app/lib/src/screens/memory/shared/widgets/shared_memory_widgets.dart b/packages/devtools_app/lib/src/screens/memory/shared/widgets/shared_memory_widgets.dart index 5f7549d8da7..f6405c36969 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/widgets/shared_memory_widgets.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/widgets/shared_memory_widgets.dart @@ -73,12 +73,7 @@ class ClassTypeLegend extends StatelessWidget { children: [ const Text('Class type legend:'), ...ClassType.values.map( - (t) => Row( - children: [ - t.icon, - Text(' ${t.aliasDescription}'), - ], - ), + (t) => Row(children: [t.icon, Text(' ${t.aliasDescription}')]), ), ], ); diff --git a/packages/devtools_app/lib/src/screens/network/constants.dart b/packages/devtools_app/lib/src/screens/network/constants.dart index b6e016e6158..d09b0e7a749 100644 --- a/packages/devtools_app/lib/src/screens/network/constants.dart +++ b/packages/devtools_app/lib/src/screens/network/constants.dart @@ -80,9 +80,4 @@ class NetworkEventCustomFieldKeys { static const events = '_events'; } -enum NetworkEventCustomFieldRemappedKeys { - isolateId, - id, - startTime, - events, -} +enum NetworkEventCustomFieldRemappedKeys { isolateId, id, startTime, events } diff --git a/packages/devtools_app/lib/src/screens/network/har_data_entry.dart b/packages/devtools_app/lib/src/screens/network/har_data_entry.dart index be71e04e2d2..4be56ecfb19 100644 --- a/packages/devtools_app/lib/src/screens/network/har_data_entry.dart +++ b/packages/devtools_app/lib/src/screens/network/har_data_entry.dart @@ -28,16 +28,18 @@ class HarDataEntry { final modifiedRequestData = _remapCustomFieldKeys(json); // Retrieving url, method from requestData - final requestData = modifiedRequestData[NetworkEventKeys.request.name] - as Map; + final requestData = + modifiedRequestData[NetworkEventKeys.request.name] + as Map; modifiedRequestData[NetworkEventKeys.uri.name] = requestData[NetworkEventKeys.url.name]; modifiedRequestData[NetworkEventKeys.method.name] = requestData[NetworkEventKeys.method.name]; // Adding missing keys which are mandatory for parsing - final responseData = modifiedRequestData[NetworkEventKeys.response.name] - as Map; + final responseData = + modifiedRequestData[NetworkEventKeys.response.name] + as Map; responseData[NetworkEventKeys.redirects.name] = >[]; final requestPostData = responseData[NetworkEventKeys.postData.name]; final responseContent = responseData[NetworkEventKeys.content.name]; @@ -59,60 +61,65 @@ class HarDataEntry { /// serialization. static Map toJson(DartIOHttpRequestData e) { // Implement the logic to convert DartIOHttpRequestData to HAR entry format - final requestCookies = e.requestCookies.map((cookie) { - return { - NetworkEventKeys.name.name: cookie.name, - NetworkEventKeys.value.name: cookie.value, - NetworkEventKeys.path.name: cookie.path, - NetworkEventKeys.domain.name: cookie.domain, - NetworkEventKeys.expires.name: - cookie.expires?.toUtc().toIso8601String(), - NetworkEventKeys.httpOnly.name: cookie.httpOnly, - NetworkEventKeys.secure.name: cookie.secure, - }; - }).toList(); - - final requestHeaders = e.requestHeaders?.entries.map((header) { - var value = header.value; - if (value is List) { - value = value.first; - } - return { - NetworkEventKeys.name.name: header.key, - NetworkEventKeys.value.name: value, - }; - }).toList(); - - final queryString = Uri.parse(e.uri).queryParameters.entries.map((param) { - return { - NetworkEventKeys.name.name: param.key, - NetworkEventKeys.value.name: param.value, - }; - }).toList(); - - final responseCookies = e.responseCookies.map((cookie) { - return { - NetworkEventKeys.name.name: cookie.name, - NetworkEventKeys.value.name: cookie.value, - NetworkEventKeys.path.name: cookie.path, - NetworkEventKeys.domain.name: cookie.domain, - NetworkEventKeys.expires.name: - cookie.expires?.toUtc().toIso8601String(), - NetworkEventKeys.httpOnly.name: cookie.httpOnly, - NetworkEventKeys.secure.name: cookie.secure, - }; - }).toList(); - - final responseHeaders = e.responseHeaders?.entries.map((header) { - var value = header.value; - if (value is List) { - value = value.first; - } - return { - NetworkEventKeys.name.name: header.key, - NetworkEventKeys.value.name: value, - }; - }).toList(); + final requestCookies = + e.requestCookies.map((cookie) { + return { + NetworkEventKeys.name.name: cookie.name, + NetworkEventKeys.value.name: cookie.value, + NetworkEventKeys.path.name: cookie.path, + NetworkEventKeys.domain.name: cookie.domain, + NetworkEventKeys.expires.name: + cookie.expires?.toUtc().toIso8601String(), + NetworkEventKeys.httpOnly.name: cookie.httpOnly, + NetworkEventKeys.secure.name: cookie.secure, + }; + }).toList(); + + final requestHeaders = + e.requestHeaders?.entries.map((header) { + var value = header.value; + if (value is List) { + value = value.first; + } + return { + NetworkEventKeys.name.name: header.key, + NetworkEventKeys.value.name: value, + }; + }).toList(); + + final queryString = + Uri.parse(e.uri).queryParameters.entries.map((param) { + return { + NetworkEventKeys.name.name: param.key, + NetworkEventKeys.value.name: param.value, + }; + }).toList(); + + final responseCookies = + e.responseCookies.map((cookie) { + return { + NetworkEventKeys.name.name: cookie.name, + NetworkEventKeys.value.name: cookie.value, + NetworkEventKeys.path.name: cookie.path, + NetworkEventKeys.domain.name: cookie.domain, + NetworkEventKeys.expires.name: + cookie.expires?.toUtc().toIso8601String(), + NetworkEventKeys.httpOnly.name: cookie.httpOnly, + NetworkEventKeys.secure.name: cookie.secure, + }; + }).toList(); + + final responseHeaders = + e.responseHeaders?.entries.map((header) { + var value = header.value; + if (value is List) { + value = value.first; + } + return { + NetworkEventKeys.name.name: header.key, + NetworkEventKeys.value.name: value, + }; + }).toList(); return { NetworkEventKeys.startedDateTime.name: @@ -130,8 +137,9 @@ class HarDataEntry { NetworkEventKeys.mimeType.name: e.contentType, NetworkEventKeys.text.name: e.requestBody, }, - NetworkEventKeys.headersSize.name: - _calculateHeadersSize(e.requestHeaders), + NetworkEventKeys.headersSize.name: _calculateHeadersSize( + e.requestHeaders, + ), NetworkEventKeys.bodySize.name: _calculateBodySize(e.requestBody), }, // Response @@ -149,8 +157,9 @@ class HarDataEntry { NetworkEventKeys.text.name: e.responseBody, }, NetworkEventKeys.redirectURL.name: '', - NetworkEventKeys.headersSize.name: - _calculateHeadersSize(e.responseHeaders), + NetworkEventKeys.headersSize.name: _calculateHeadersSize( + e.responseHeaders, + ), NetworkEventKeys.bodySize.name: _calculateBodySize(e.responseBody), }, // Cache @@ -267,15 +276,16 @@ int _calculateHeadersSize(Map? headers) { if (headers == null) return -1; // Combine headers into a single string with CRLF endings - String headersString = headers.entries.map((entry) { - final key = entry.key; - var value = entry.value; - // If the value is a List, join it with a comma - if (value is List) { - value = value.join(', '); - } - return '$key: $value\r\n'; - }).join(); + String headersString = + headers.entries.map((entry) { + final key = entry.key; + var value = entry.value; + // If the value is a List, join it with a comma + if (value is List) { + value = value.join(', '); + } + return '$key: $value\r\n'; + }).join(); // Add final CRLF to indicate end of headers headersString += '\r\n'; 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 60b02ac82d0..5b81bb0d02f 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 @@ -29,15 +29,17 @@ class HarNetworkData with Serializable { /// final harData = HarNetworkData.fromJson(json); /// ``` factory HarNetworkData.fromJson(Map json) { - final entries = ((json[NetworkEventKeys.log.name] - as Map)[NetworkEventKeys.entries.name] - as List) - .map( - (entryJson) => - HarDataEntry.fromJson(entryJson as Map) - .toDartIOHttpRequest(), - ) - .toList(); + final entries = + ((json[NetworkEventKeys.log.name] + as Map)[NetworkEventKeys.entries.name] + as List) + .map( + (entryJson) => + HarDataEntry.fromJson( + entryJson as Map, + ).toDartIOHttpRequest(), + ) + .toList(); return HarNetworkData(entries); } diff --git a/packages/devtools_app/lib/src/screens/network/network_controller.dart b/packages/devtools_app/lib/src/screens/network/network_controller.dart index f6ea6c56822..2d555968d36 100644 --- a/packages/devtools_app/lib/src/screens/network/network_controller.dart +++ b/packages/devtools_app/lib/src/screens/network/network_controller.dart @@ -40,10 +40,7 @@ enum NetworkResponseViewType { } } -enum _NetworkTrafficType { - http, - socket, -} +enum _NetworkTrafficType { http, socket } class NetworkController extends DisposableController with @@ -94,25 +91,25 @@ class NetworkController extends DisposableController @override Map> createQueryFilterArgs() => { - methodFilterId: QueryFilterArgument( - keys: ['method', 'm'], - exampleUsages: ['m:get', '-m:put,patch'], - dataValueProvider: (request) => request.method, - substringMatch: false, - ), - statusFilterId: QueryFilterArgument( - keys: ['status', 's'], - exampleUsages: ['s:200', '-s:404'], - dataValueProvider: (request) => request.status, - substringMatch: false, - ), - typeFilterId: QueryFilterArgument( - keys: ['type', 't'], - exampleUsages: ['t:json', '-t:text'], - dataValueProvider: (request) => request.type, - substringMatch: false, - ), - }; + methodFilterId: QueryFilterArgument( + keys: ['method', 'm'], + exampleUsages: ['m:get', '-m:put,patch'], + dataValueProvider: (request) => request.method, + substringMatch: false, + ), + statusFilterId: QueryFilterArgument( + keys: ['status', 's'], + exampleUsages: ['s:200', '-s:404'], + dataValueProvider: (request) => request.status, + substringMatch: false, + ), + typeFilterId: QueryFilterArgument( + keys: ['type', 't'], + exampleUsages: ['t:json', '-t:text'], + dataValueProvider: (request) => request.type, + substringMatch: false, + ), + }; @override ValueNotifier? get filterTagNotifier => preferences.network.filterTag; @@ -124,8 +121,9 @@ class NetworkController extends DisposableController ValueListenable get currentResponseViewType => _currentResponseViewType; - final _currentResponseViewType = - ValueNotifier(NetworkResponseViewType.auto); + final _currentResponseViewType = ValueNotifier( + NetworkResponseViewType.auto, + ); /// Change current response type set setResponseViewType(NetworkResponseViewType type) => @@ -185,8 +183,9 @@ class NetworkController extends DisposableController // the value. final currentSelectedRequestId = selectedRequest.value?.id; if (currentSelectedRequestId != null) { - selectedRequest.value = - currentRequests.getRequest(currentSelectedRequestId); + selectedRequest.value = currentRequests.getRequest( + currentSelectedRequestId, + ); } } @@ -221,10 +220,12 @@ class NetworkController extends DisposableController Future startRecording() async { await _startRecording( - alreadyRecordingHttp: - await _recordingNetworkTraffic(type: _NetworkTrafficType.http), - alreadyRecordingSocketData: - await _recordingNetworkTraffic(type: _NetworkTrafficType.socket), + alreadyRecordingHttp: await _recordingNetworkTraffic( + type: _NetworkTrafficType.http, + ), + alreadyRecordingSocketData: await _recordingNetworkTraffic( + type: _NetworkTrafficType.socket, + ), ); } @@ -256,8 +257,11 @@ class NetworkController extends DisposableController // fewer flags risks breaking functionality on the timeline view that // assumes that all flags are set. await allowedError( - serviceConnection.serviceManager.service! - .setVMTimelineFlags(['GC', 'Dart', 'Embedder']), + serviceConnection.serviceManager.service!.setVMTimelineFlags([ + 'GC', + 'Dart', + 'Embedder', + ]), ); // TODO(kenz): only call these if http logging and socket profiling are not @@ -299,22 +303,22 @@ class NetworkController extends DisposableController }) async { bool enabled = true; final service = serviceConnection.serviceManager.service!; - await service.forEachIsolate( - (isolate) async { - final future = switch (type) { - _NetworkTrafficType.http => - service.httpEnableTimelineLoggingWrapper(isolate.id!), - _NetworkTrafficType.socket => - service.socketProfilingEnabledWrapper(isolate.id!), - }; - // The above call won't complete immediately if the isolate is paused, - // so give up waiting after 500ms. - final state = await timeout(future, 500); - if (state?.enabled != true) { - enabled = false; - } - }, - ); + await service.forEachIsolate((isolate) async { + final future = switch (type) { + _NetworkTrafficType.http => service.httpEnableTimelineLoggingWrapper( + isolate.id!, + ), + _NetworkTrafficType.socket => service.socketProfilingEnabledWrapper( + isolate.id!, + ), + }; + // The above call won't complete immediately if the isolate is paused, + // so give up waiting after 500ms. + final state = await timeout(future, 500); + if (state?.enabled != true) { + enabled = false; + } + }); return enabled; } @@ -362,7 +366,8 @@ class NetworkController extends DisposableController ..addAll( _currentNetworkRequests.value.where((NetworkRequest r) { final filteredOutByQueryFilterArgument = queryFilter - .filterArguments.values + .filterArguments + .values .any((argument) => !argument.matchesValue(r)); if (filteredOutByQueryFilterArgument) return false; @@ -396,10 +401,10 @@ class NetworkController extends DisposableController } Future _fetchFullDataBeforeExport() => Future.wait( - filteredData.value - .whereType() - .map((item) => item.getFullRequestData()), - ); + filteredData.value.whereType().map( + (item) => item.getFullRequestData(), + ), + ); } /// Class for managing the set of all current sockets, and 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 64e7ba1f4a2..44a12b1d538 100644 --- a/packages/devtools_app/lib/src/screens/network/network_model.dart +++ b/packages/devtools_app/lib/src/screens/network/network_model.dart @@ -36,12 +36,10 @@ abstract class NetworkRequest with ChangeNotifier, SearchableDataMixin { String get durationDisplay { final duration = this.duration; - final text = duration != null - ? durationText( - duration, - unit: DurationDisplayUnit.milliseconds, - ) - : 'Pending'; + final text = + duration != null + ? durationText(duration, unit: DurationDisplayUnit.milliseconds) + : 'Pending'; return 'Duration: $text'; } @@ -72,14 +70,8 @@ abstract class NetworkRequest with ChangeNotifier, SearchableDataMixin { } @override - int get hashCode => Object.hash( - method, - uri, - contentType, - type, - port, - startTimestamp, - ); + int get hashCode => + Object.hash(method, uri, contentType, type, port, startTimestamp); } class Socket extends NetworkRequest { @@ -113,16 +105,16 @@ class Socket extends NetworkRequest { @override DateTime get startTimestamp => DateTime.fromMicrosecondsSinceEpoch( - timelineMicrosecondsSinceEpoch(_socket.startTime), - ); + timelineMicrosecondsSinceEpoch(_socket.startTime), + ); @override DateTime? get endTimestamp { final endTime = _socket.endTime; return endTime != null ? DateTime.fromMicrosecondsSinceEpoch( - timelineMicrosecondsSinceEpoch(endTime), - ) + timelineMicrosecondsSinceEpoch(endTime), + ) : null; } @@ -130,8 +122,8 @@ class Socket extends NetworkRequest { final lastReadTime = _socket.lastReadTime; return lastReadTime != null ? DateTime.fromMicrosecondsSinceEpoch( - timelineMicrosecondsSinceEpoch(lastReadTime), - ) + timelineMicrosecondsSinceEpoch(lastReadTime), + ) : null; } @@ -139,8 +131,8 @@ class Socket extends NetworkRequest { final lastWriteTime = _socket.lastWriteTime; return lastWriteTime != null ? DateTime.fromMicrosecondsSinceEpoch( - timelineMicrosecondsSinceEpoch(lastWriteTime), - ) + timelineMicrosecondsSinceEpoch(lastWriteTime), + ) : null; } diff --git a/packages/devtools_app/lib/src/screens/network/network_request_inspector.dart b/packages/devtools_app/lib/src/screens/network/network_request_inspector.dart index 0278f7fec1f..68d3e939ac7 100644 --- a/packages/devtools_app/lib/src/screens/network/network_request_inspector.dart +++ b/packages/devtools_app/lib/src/screens/network/network_request_inspector.dart @@ -39,23 +39,23 @@ class NetworkRequestInspector extends StatelessWidget { builder: (context, data, _) { return data == null ? RoundedOutlinedBorder( - child: Center( - child: Text( - 'No request selected', - style: Theme.of(context).regularTextStyle, - ), + child: Center( + child: Text( + 'No request selected', + style: Theme.of(context).regularTextStyle, ), - ) + ), + ) : ListenableBuilder( - listenable: data, - builder: (context, _) { - return AnalyticsTabbedView( - analyticsSessionIdentifier: data.id, - tabs: _generateTabs(data), - gaScreen: gac.network, - ); - }, - ); + listenable: data, + builder: (context, _) { + return AnalyticsTabbedView( + analyticsSessionIdentifier: data.id, + tabs: _generateTabs(data), + gaScreen: gac.network, + ); + }, + ); }, ); } @@ -64,58 +64,64 @@ class NetworkRequestInspector extends StatelessWidget { NetworkRequest data, ) => [ - ( - tab: _buildTab(tabName: NetworkRequestInspector._overviewTabTitle), - tabView: NetworkRequestOverviewView(data), - ), - if (data is DartIOHttpRequestData) ...[ - ( - tab: _buildTab(tabName: NetworkRequestInspector._headersTabTitle), - tabView: HttpRequestHeadersView(data), - ), - if (data.requestBody != null) ( tab: _buildTab( - tabName: NetworkRequestInspector._requestTabTitle, - trailing: HttpViewTrailingCopyButton( - data, - (data) => data.requestBody, - ), + tabName: NetworkRequestInspector._overviewTabTitle, ), - tabView: HttpRequestView(data), + tabView: NetworkRequestOverviewView(data), ), - if (data.responseBody != null) - ( - tab: _buildTab( - tabName: NetworkRequestInspector._responseTabTitle, - trailing: Row( - children: [ - HttpResponseTrailingDropDown( + if (data is DartIOHttpRequestData) ...[ + ( + tab: _buildTab( + tabName: NetworkRequestInspector._headersTabTitle, + ), + tabView: HttpRequestHeadersView(data), + ), + if (data.requestBody != null) + ( + tab: _buildTab( + tabName: NetworkRequestInspector._requestTabTitle, + trailing: HttpViewTrailingCopyButton( data, - currentResponseViewType: - controller.currentResponseViewType, - onChanged: (value) => - controller.setResponseViewType = value, + (data) => data.requestBody, ), - HttpViewTrailingCopyButton( - data, - (data) => data.responseBody, + ), + tabView: HttpRequestView(data), + ), + if (data.responseBody != null) + ( + tab: _buildTab( + tabName: NetworkRequestInspector._responseTabTitle, + trailing: Row( + children: [ + HttpResponseTrailingDropDown( + data, + currentResponseViewType: + controller.currentResponseViewType, + onChanged: + (value) => controller.setResponseViewType = value, + ), + HttpViewTrailingCopyButton( + data, + (data) => data.responseBody, + ), + ], ), - ], + ), + tabView: HttpResponseView( + data, + currentResponseViewType: controller.currentResponseViewType, + ), ), - ), - tabView: HttpResponseView( - data, - currentResponseViewType: controller.currentResponseViewType, - ), - ), - if (data.hasCookies) - ( - tab: _buildTab(tabName: NetworkRequestInspector._cookiesTabTitle), - tabView: HttpRequestCookiesView(data), - ), - ], - ] + if (data.hasCookies) + ( + tab: _buildTab( + tabName: NetworkRequestInspector._cookiesTabTitle, + ), + tabView: HttpRequestCookiesView(data), + ), + ], + ] .map( (t) => ( tab: t.tab, diff --git a/packages/devtools_app/lib/src/screens/network/network_request_inspector_views.dart b/packages/devtools_app/lib/src/screens/network/network_request_inspector_views.dart index e2e14c5a033..ae4b8acae4a 100644 --- a/packages/devtools_app/lib/src/screens/network/network_request_inspector_views.dart +++ b/packages/devtools_app/lib/src/screens/network/network_request_inspector_views.dart @@ -24,20 +24,16 @@ const _rowIndentPadding = 30.0; // No padding between the last element and the divider of a expandable tile. const _rowSpacingPadding = 15.0; -const _rowPadding = - EdgeInsets.only(left: _rowIndentPadding, bottom: _rowSpacingPadding); +const _rowPadding = EdgeInsets.only( + left: _rowIndentPadding, + bottom: _rowSpacingPadding, +); /// Helper to build ExpansionTile widgets for inspector views. -ExpansionTile _buildTile( - String title, - List children, { - Key? key, -}) { +ExpansionTile _buildTile(String title, List children, {Key? key}) { return ExpansionTile( key: key, - title: Text( - title, - ), + title: Text(title), initiallyExpanded: true, children: children, ); @@ -67,36 +63,24 @@ class HttpRequestHeadersView extends StatelessWidget { return SelectionArea( child: ListView( children: [ - _buildTile( - 'General', - [ - for (final entry in general.entries) - _Row( - entry: entry, - constraints: constraints, - isErrorValue: data.didFail && entry.key == 'statusCode', - ), - ], - key: generalKey, - ), - _buildTile( - 'Response Headers', - [ - if (responseHeaders != null) - for (final entry in responseHeaders.entries) - _Row(entry: entry, constraints: constraints), - ], - key: responseHeadersKey, - ), - _buildTile( - 'Request Headers', - [ - if (requestHeaders != null) - for (final entry in requestHeaders.entries) - _Row(entry: entry, constraints: constraints), - ], - key: requestHeadersKey, - ), + _buildTile('General', [ + for (final entry in general.entries) + _Row( + entry: entry, + constraints: constraints, + isErrorValue: data.didFail && entry.key == 'statusCode', + ), + ], key: generalKey), + _buildTile('Response Headers', [ + if (responseHeaders != null) + for (final entry in responseHeaders.entries) + _Row(entry: entry, constraints: constraints), + ], key: responseHeadersKey), + _buildTile('Request Headers', [ + if (requestHeaders != null) + for (final entry in requestHeaders.entries) + _Row(entry: entry, constraints: constraints), + ], key: requestHeadersKey), ], ), ); @@ -125,10 +109,7 @@ class _Row extends StatelessWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - '${entry.key}: ', - style: theme.textTheme.titleMedium, - ), + Text('${entry.key}: ', style: theme.textTheme.titleMedium), Expanded( child: Text( style: isErrorValue ? theme.errorTextStyle : null, @@ -156,33 +137,32 @@ class HttpRequestView extends StatelessWidget { final requestContentType = requestHeaders?['content-type'] ?? ''; final isLoading = data.isFetchingFullData; if (isLoading) { - return CenteredCircularProgressIndicator( - size: mediumProgressSize, - ); + return CenteredCircularProgressIndicator(size: mediumProgressSize); } final isJson = switch (requestContentType) { - List() => - requestContentType.any((e) => (e as String).contains('json')), + List() => requestContentType.any( + (e) => (e as String).contains('json'), + ), String() => requestContentType.contains('json'), - _ => throw StateError( + _ => + throw StateError( "Expected 'content-type' to be a List or String, but got: " '$requestContentType', ), }; Widget child; - child = isJson - ? JsonViewer(encodedJson: data.requestBody!) - : TextViewer( - text: data.requestBody!, - style: theme.fixedFontStyle, - ); + child = + isJson + ? JsonViewer(encodedJson: data.requestBody!) + : TextViewer( + text: data.requestBody!, + style: theme.fixedFontStyle, + ); return Padding( padding: const EdgeInsets.all(denseSpacing), - child: SingleChildScrollView( - child: child, - ), + child: SingleChildScrollView(child: child), ); }, ); @@ -211,9 +191,7 @@ class HttpViewTrailingCopyButton extends StatelessWidget { return Align( alignment: Alignment.centerRight, - child: CopyToClipboardControl( - dataProvider: () => dataToCopy, - ), + child: CopyToClipboardControl(dataProvider: () => dataToCopy), ); }, ); @@ -250,7 +228,8 @@ class HttpResponseTrailingDropDown extends StatelessWidget { return ListenableBuilder( listenable: data, builder: (_, _) { - final visible = (data.contentType != null && + final visible = + (data.contentType != null && !data.contentType!.contains('image')) && data.responseBody!.isNotEmpty; @@ -268,14 +247,15 @@ class HttpResponseTrailingDropDown extends StatelessWidget { builder: (_, currentType, _) { return RoundedDropDownButton( value: currentType, - items: availableResponseTypes - .map( - (e) => DropdownMenuItem( - value: e, - child: Text(e.toString()), - ), - ) - .toList(), + items: + availableResponseTypes + .map( + (e) => DropdownMenuItem( + value: e, + child: Text(e.toString()), + ), + ) + .toList(), onChanged: (value) { if (value == null) { return; @@ -315,9 +295,7 @@ class HttpResponseView extends StatelessWidget { final responseBody = data.responseBody!; final isLoading = data.isFetchingFullData; if (isLoading) { - return CenteredCircularProgressIndicator( - size: mediumProgressSize, - ); + return CenteredCircularProgressIndicator(size: mediumProgressSize); } if (contentType != null && contentType.contains('image')) { child = ImageResponseView(data); @@ -372,9 +350,9 @@ class HttpTextResponseViewer extends StatelessWidget { return switch (currentLocalResponseType) { NetworkResponseViewType.json => JsonViewer(encodedJson: responseBody), NetworkResponseViewType.text => TextViewer( - text: responseBody, - style: textStyle, - ), + text: responseBody, + style: textStyle, + ), _ => const SizedBox(), }; }, @@ -394,67 +372,34 @@ class ImageResponseView extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - _buildTile( - 'Image Preview', - [ - Padding( - padding: const EdgeInsets.all( - denseSpacing, - ), - child: Image.memory( - encodedResponse, - ), - ), - ], - ), - _buildTile( - 'Metadata', - [ - _buildRow( - context, - 'Format', - data.type, - ), - _buildRow( - context, - 'Size', - prettyPrintBytes( - encodedResponse.lengthInBytes, - includeUnit: true, - )!, - ), - _buildRow( - context, - 'Dimensions', - '${img.width} x ${img.height}', - ), - ], - ), + _buildTile('Image Preview', [ + Padding( + padding: const EdgeInsets.all(denseSpacing), + child: Image.memory(encodedResponse), + ), + ]), + _buildTile('Metadata', [ + _buildRow(context, 'Format', data.type), + _buildRow( + context, + 'Size', + prettyPrintBytes(encodedResponse.lengthInBytes, includeUnit: true)!, + ), + _buildRow(context, 'Dimensions', '${img.width} x ${img.height}'), + ]), ], ); } - Widget _buildRow( - BuildContext context, - String key, - String value, - ) { + Widget _buildRow(BuildContext context, String key, String value) { return Padding( padding: _rowPadding, child: Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - '$key: ', - style: Theme.of(context).textTheme.titleMedium, - ), - Expanded( - child: Text( - value, - overflow: TextOverflow.ellipsis, - ), - ), + Text('$key: ', style: Theme.of(context).textTheme.titleMedium), + Expanded(child: Text(value, overflow: TextOverflow.ellipsis)), ], ), ); @@ -506,10 +451,7 @@ class HttpRequestCookiesView extends StatelessWidget { bool requestCookies = false, }) { final theme = Theme.of(context); - DataColumn buildColumn( - String title, { - bool numeric = false, - }) { + DataColumn buildColumn(String title, {bool numeric = false}) { return DataColumn( label: Expanded( child: Text( @@ -528,58 +470,50 @@ class HttpRequestCookiesView extends StatelessWidget { ); } - return _buildTile( - title, - [ - // Add a divider between the tile's title and the cookie table headers for - // symmetry. - const Divider( - // Remove extra padding at the top of the divider; the tile's title - // already has bottom padding. - height: 0, - ), - Align( - alignment: Alignment.centerLeft, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: ConstrainedBox( - constraints: requestCookies - ? const BoxConstraints() - : BoxConstraints( - minWidth: constraints.minWidth, - ), - child: DataTable( - key: key, - dataRowMinHeight: defaultRowHeight, - dataRowMaxHeight: defaultRowHeight, - // NOTE: if this list of columns change, _buildRow will need - // to be updated to match. - columns: [ - buildColumn('Name'), - buildColumn('Value'), - if (!requestCookies) ...[ - buildColumn('Domain'), - buildColumn('Path'), - buildColumn('Expires / Max Age'), - buildColumn('Size', numeric: true), - buildColumn('HttpOnly'), - buildColumn('Secure'), - ], - ], - rows: [ - for (int i = 0; i < cookies.length; ++i) - _buildRow( - i, - cookies[i], - requestCookies: requestCookies, - ), + return _buildTile(title, [ + // Add a divider between the tile's title and the cookie table headers for + // symmetry. + const Divider( + // Remove extra padding at the top of the divider; the tile's title + // already has bottom padding. + height: 0, + ), + Align( + alignment: Alignment.centerLeft, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: ConstrainedBox( + constraints: + requestCookies + ? const BoxConstraints() + : BoxConstraints(minWidth: constraints.minWidth), + child: DataTable( + key: key, + dataRowMinHeight: defaultRowHeight, + dataRowMaxHeight: defaultRowHeight, + // NOTE: if this list of columns change, _buildRow will need + // to be updated to match. + columns: [ + buildColumn('Name'), + buildColumn('Value'), + if (!requestCookies) ...[ + buildColumn('Domain'), + buildColumn('Path'), + buildColumn('Expires / Max Age'), + buildColumn('Size', numeric: true), + buildColumn('HttpOnly'), + buildColumn('Secure'), ], - ), + ], + rows: [ + for (int i = 0; i < cookies.length; ++i) + _buildRow(i, cookies[i], requestCookies: requestCookies), + ], ), ), ), - ], - ); + ), + ]); } @override @@ -601,9 +535,7 @@ class HttpRequestCookiesView extends StatelessWidget { // Add padding between the cookie tables if displaying both // response and request cookies. if (responseCookies.isNotEmpty && requestCookies.isNotEmpty) - const Padding( - padding: EdgeInsets.only(bottom: 24.0), - ), + const Padding(padding: EdgeInsets.only(bottom: 24.0)), if (requestCookies.isNotEmpty) _buildCookiesTable( context, @@ -699,9 +631,10 @@ class NetworkRequestOverviewView extends StatelessWidget { _buildRow( context: context, title: 'Timing', - child: data is Socket - ? _buildSocketTimeGraph(context) - : _buildHttpTimeGraph(), + child: + data is Socket + ? _buildSocketTimeGraph(context) + : _buildHttpTimeGraph(), ), const SizedBox(height: denseSpacing), _buildRow( @@ -732,21 +665,14 @@ class NetworkRequestOverviewView extends StatelessWidget { ]; } - Widget _buildTimingRow( - Color color, - String label, - Duration duration, - ) { + Widget _buildTimingRow(Color color, String label, Duration duration) { final flex = (duration.inMicroseconds / data.duration!.inMicroseconds * 100).round(); return Flexible( flex: flex, child: DevToolsTooltip( message: '$label - ${durationText(duration)}', - child: Container( - height: _timingGraphHeight, - color: color, - ), + child: Container(height: _timingGraphHeight, color: color), ), ); } @@ -761,11 +687,7 @@ class NetworkRequestOverviewView extends StatelessWidget { ); } - const colors = [ - searchMatchColor, - mainRasterColor, - mainAsyncColor, - ]; + const colors = [searchMatchColor, mainRasterColor, mainAsyncColor]; var colorIndex = 0; Color nextColor() { @@ -779,21 +701,15 @@ class NetworkRequestOverviewView extends StatelessWidget { final timingWidgets = []; for (final instant in data.instantEvents) { final duration = instant.timeRange!.duration; - timingWidgets.add( - _buildTimingRow(nextColor(), instant.name, duration), - ); + timingWidgets.add(_buildTimingRow(nextColor(), instant.name, duration)); } final duration = Duration( - microseconds: data.endTimestamp!.microsecondsSinceEpoch - + microseconds: + data.endTimestamp!.microsecondsSinceEpoch - data.instantEvents.last.timestamp.microsecondsSinceEpoch, ); - timingWidgets.add( - _buildTimingRow(nextColor(), 'Response', duration), - ); - return Row( - key: httpTimingGraphKey, - children: timingWidgets, - ); + timingWidgets.add(_buildTimingRow(nextColor(), 'Response', duration)); + return Row(key: httpTimingGraphKey, children: timingWidgets); } // TODO(kenz): add a "waterfall" like visualization with the same colors that @@ -877,17 +793,19 @@ class NetworkRequestOverviewView extends StatelessWidget { _buildRow( context: context, title: 'Last read time', - child: lastReadTimestamp != null - ? _valueText(formatDateTime(lastReadTimestamp)) - : _valueText('--'), + child: + lastReadTimestamp != null + ? _valueText(formatDateTime(lastReadTimestamp)) + : _valueText('--'), ), const SizedBox(height: defaultSpacing), _buildRow( context: context, title: 'Last write time', - child: lastWriteTimestamp != null - ? _valueText(formatDateTime(lastWriteTimestamp)) - : _valueText('--'), + child: + lastWriteTimestamp != null + ? _valueText(formatDateTime(lastWriteTimestamp)) + : _valueText('--'), ), ]; } @@ -907,17 +825,12 @@ class NetworkRequestOverviewView extends StatelessWidget { style: Theme.of(context).textTheme.titleMedium, ), ), - Expanded( - child: child, - ), + Expanded(child: child), ], ); } Widget _valueText(String value, [TextStyle? style]) { - return Text( - style: style, - value, - ); + return Text(style: style, value); } } 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 bb63e84e328..ec92270cdc0 100644 --- a/packages/devtools_app/lib/src/screens/network/network_screen.dart +++ b/packages/devtools_app/lib/src/screens/network/network_screen.dart @@ -45,10 +45,7 @@ class NetworkScreen extends Screen { final networkController = Provider.of(context); final color = Theme.of(context).colorScheme.onPrimary; return MultiValueListenableBuilder( - listenables: [ - networkController.requests, - networkController.filteredData, - ], + listenables: [networkController.requests, networkController.filteredData], builder: (context, values, child) { final networkRequests = values.first as List; final filteredRequests = values.second as List; @@ -73,11 +70,12 @@ class NetworkScreen extends Screen { return SizedBox( width: smallProgressSize, height: smallProgressSize, - child: recording - ? SmallCircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(color), - ) - : const SizedBox(), + child: + recording + ? SmallCircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(color), + ) + : const SizedBox(), ); }, ), @@ -135,9 +133,7 @@ class _NetworkScreenBodyState extends State children: [ _NetworkProfilerControls(controller: controller), const SizedBox(height: intermediateSpacing), - Expanded( - child: _NetworkProfilerBody(controller: controller), - ), + Expanded(child: _NetworkProfilerBody(controller: controller)), ], ); } @@ -146,9 +142,7 @@ class _NetworkScreenBodyState extends State /// The row of controls that control the Network profiler (e.g., record, pause, /// clear, search, filter, etc.). class _NetworkProfilerControls extends StatefulWidget { - const _NetworkProfilerControls({ - required this.controller, - }); + const _NetworkProfilerControls({required this.controller}); static const _includeTextWidth = 810.0; @@ -185,11 +179,12 @@ class _NetworkProfilerControlsState extends State<_NetworkProfilerControls> children: [ StartStopRecordingButton( recording: _recording, - onPressed: () async => - await widget.controller.togglePolling(!_recording), - tooltipOverride: _recording - ? 'Stop recording network traffic' - : 'Resume recording network traffic', + onPressed: + () async => await widget.controller.togglePolling(!_recording), + tooltipOverride: + _recording + ? 'Stop recording network traffic' + : 'Resume recording network traffic', minScreenWidthForTextBeforeScaling: double.infinity, gaScreen: gac.network, gaSelection: _recording ? gac.pause : gac.resume, @@ -217,9 +212,10 @@ class _NetworkProfilerControlsState extends State<_NetworkProfilerControls> child: SearchField( searchController: widget.controller, searchFieldEnabled: hasRequests, - searchFieldWidth: screenWidth <= MediaSize.xs - ? defaultSearchFieldWidth - : wideSearchFieldWidth, + searchFieldWidth: + screenWidth <= MediaSize.xs + ? defaultSearchFieldWidth + : wideSearchFieldWidth, ), ), const SizedBox(width: denseSpacing), @@ -325,11 +321,11 @@ class NetworkRequestsTable extends StatelessWidget { class AddressColumn extends ColumnData implements ColumnRenderer { AddressColumn() - : super.wide( - 'Address', - minWidthPx: scaleByFontFactor(isEmbedded() ? 100 : 150.0), - showTooltip: true, - ); + : super.wide( + 'Address', + minWidthPx: scaleByFontFactor(isEmbedded() ? 100 : 150.0), + showTooltip: true, + ); @override String getValue(NetworkRequest dataObject) { @@ -370,11 +366,11 @@ class MethodColumn extends ColumnData { class ActionsColumn extends ColumnData implements ColumnRenderer { ActionsColumn() - : super( - '', - fixedWidthPx: scaleByFontFactor(32), - alignment: ColumnAlignment.right, - ); + : super( + '', + fixedWidthPx: scaleByFontFactor(32), + alignment: ColumnAlignment.right, + ); static const _actionSplashRadius = 16.0; @@ -445,12 +441,12 @@ class ActionsColumn extends ColumnData class StatusColumn extends ColumnData implements ColumnRenderer { StatusColumn() - : super( - 'Status', - alignment: ColumnAlignment.right, - headerAlignment: TextAlign.right, - fixedWidthPx: scaleByFontFactor(50), - ); + : super( + 'Status', + alignment: ColumnAlignment.right, + headerAlignment: TextAlign.right, + fixedWidthPx: scaleByFontFactor(50), + ); @override String? getValue(NetworkRequest dataObject) { @@ -473,21 +469,22 @@ class StatusColumn extends ColumnData final theme = Theme.of(context); return Text( getDisplayValue(data), - style: data.didFail - ? TextStyle(color: theme.colorScheme.error) - : theme.regularTextStyle, + style: + data.didFail + ? TextStyle(color: theme.colorScheme.error) + : theme.regularTextStyle, ); } } class TypeColumn extends ColumnData { TypeColumn() - : super( - 'Type', - alignment: ColumnAlignment.right, - headerAlignment: TextAlign.right, - fixedWidthPx: scaleByFontFactor(50), - ); + : super( + 'Type', + alignment: ColumnAlignment.right, + headerAlignment: TextAlign.right, + fixedWidthPx: scaleByFontFactor(50), + ); @override String getValue(NetworkRequest dataObject) { @@ -502,12 +499,12 @@ class TypeColumn extends ColumnData { class DurationColumn extends ColumnData { DurationColumn() - : super( - 'Duration', - alignment: ColumnAlignment.right, - headerAlignment: TextAlign.right, - fixedWidthPx: scaleByFontFactor(75), - ); + : super( + 'Duration', + alignment: ColumnAlignment.right, + headerAlignment: TextAlign.right, + fixedWidthPx: scaleByFontFactor(75), + ); @override int? getValue(NetworkRequest dataObject) { @@ -519,21 +516,18 @@ class DurationColumn extends ColumnData { final ms = getValue(dataObject); return ms == null ? 'Pending' - : durationText( - Duration(milliseconds: ms), - fractionDigits: 0, - ); + : durationText(Duration(milliseconds: ms), fractionDigits: 0); } } class TimestampColumn extends ColumnData { TimestampColumn() - : super( - 'Timestamp', - alignment: ColumnAlignment.right, - headerAlignment: TextAlign.right, - fixedWidthPx: scaleByFontFactor(115), - ); + : super( + 'Timestamp', + alignment: ColumnAlignment.right, + headerAlignment: TextAlign.right, + fixedWidthPx: scaleByFontFactor(115), + ); @override DateTime? getValue(NetworkRequest dataObject) { diff --git a/packages/devtools_app/lib/src/screens/network/network_service.dart b/packages/devtools_app/lib/src/screens/network/network_service.dart index 5e78a4d6d3e..ae21304456a 100644 --- a/packages/devtools_app/lib/src/screens/network/network_service.dart +++ b/packages/devtools_app/lib/src/screens/network/network_service.dart @@ -42,9 +42,7 @@ class NetworkService { /// would have occurred, so the refresh time is not updated. Otherwise, /// [NetworkController.lastHttpDataRefreshTime] is updated to the current /// time. - void updateLastHttpDataRefreshTime({ - bool alreadyRecordingHttp = false, - }) { + void updateLastHttpDataRefreshTime({bool alreadyRecordingHttp = false}) { if (!alreadyRecordingHttp) { networkController.lastHttpDataRefreshTime = DateTime.now(); } @@ -128,8 +126,8 @@ class NetworkService { if (service == null) return; await service.forEachIsolate((isolate) async { final isolateId = isolate.id!; - final socketProfilingAvailable = - await service.isSocketProfilingAvailableWrapper(isolateId); + final socketProfilingAvailable = await service + .isSocketProfilingAvailableWrapper(isolateId); if (socketProfilingAvailable) { final future = service.clearSocketProfileWrapper(isolateId); // The above call won't complete immediately if the isolate is paused, so @@ -148,8 +146,8 @@ class NetworkService { if (service == null) return; await service.forEachIsolate((isolate) async { final isolateId = isolate.id!; - final socketProfilingAvailable = - await service.isSocketProfilingAvailableWrapper(isolateId); + final socketProfilingAvailable = await service + .isSocketProfilingAvailableWrapper(isolateId); if (socketProfilingAvailable) { final future = service.socketProfilingEnabledWrapper(isolateId, state); // The above call won't complete immediately if the isolate is paused, so diff --git a/packages/devtools_app/lib/src/screens/performance/panes/controls/enhance_tracing/enhance_tracing.dart b/packages/devtools_app/lib/src/screens/performance/panes/controls/enhance_tracing/enhance_tracing.dart index 83478a55e1b..a766875d754 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/controls/enhance_tracing/enhance_tracing.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/controls/enhance_tracing/enhance_tracing.dart @@ -18,10 +18,7 @@ import '../performance_controls.dart'; import 'enhance_tracing_controller.dart'; class EnhanceTracingButton extends StatelessWidget { - const EnhanceTracingButton( - this.enhanceTracingController, { - super.key, - }); + const EnhanceTracingButton(this.enhanceTracingController, {super.key}); static const title = 'Enhance Tracing'; @@ -49,7 +46,8 @@ class EnhanceTracingButton extends StatelessWidget { }, overlayDescription: RichText( text: TextSpan( - text: 'These options can be used to add more detail to the ' + text: + 'These options can be used to add more detail to the ' 'timeline, but be aware that ', style: textStyle, children: [ @@ -57,12 +55,10 @@ class EnhanceTracingButton extends StatelessWidget { text: 'frame times may be negatively affected', style: textStyle.copyWith(color: theme.colorScheme.error), ), + TextSpan(text: '.\n\n', style: textStyle), TextSpan( - text: '.\n\n', - style: textStyle, - ), - TextSpan( - text: 'When toggling on/off a tracing option, you will need ' + text: + 'When toggling on/off a tracing option, you will need ' 'to reproduce activity in your app to see the enhanced ' 'tracing in the timeline.', style: textStyle, @@ -74,10 +70,7 @@ class EnhanceTracingButton extends StatelessWidget { } } -enum TraceWidgetBuildsScope { - all, - userCreated, -} +enum TraceWidgetBuildsScope { all, userCreated } extension TraceWidgetBuildsScopeExtension on TraceWidgetBuildsScope { String get radioDisplay { @@ -153,19 +146,20 @@ class _TraceWidgetBuildsSettingState extends State serviceConnection.serviceManager.serviceExtensionManager .waitForServiceExtensionAvailable(extension.extension) .then((isServiceAvailable) { - if (isServiceAvailable) { - _tracingAvailable.value = true; - - final state = serviceConnection - .serviceManager.serviceExtensionManager - .getServiceExtensionState(extension.extension); - - _updateForServiceExtensionState(state.value, type); - addAutoDisposeListener(state, () { - _updateForServiceExtensionState(state.value, type); - }); - } - }), + if (isServiceAvailable) { + _tracingAvailable.value = true; + + final state = serviceConnection + .serviceManager + .serviceExtensionManager + .getServiceExtensionState(extension.extension); + + _updateForServiceExtensionState(state.value, type); + addAutoDisposeListener(state, () { + _updateForServiceExtensionState(state.value, type); + }); + } + }), ); } } @@ -174,15 +168,17 @@ class _TraceWidgetBuildsSettingState extends State ServiceExtensionState newState, TraceWidgetBuildsScope type, ) async { - final otherState = serviceConnection.serviceManager.serviceExtensionManager - .getServiceExtensionState(type.opposite.extensionForScope.extension) - .value - .enabled; + final otherState = + serviceConnection.serviceManager.serviceExtensionManager + .getServiceExtensionState(type.opposite.extensionForScope.extension) + .value + .enabled; final traceAllWidgets = type == TraceWidgetBuildsScope.all ? newState.enabled : otherState; - final traceUserWidgets = type == TraceWidgetBuildsScope.userCreated - ? newState.enabled - : otherState; + final traceUserWidgets = + type == TraceWidgetBuildsScope.userCreated + ? newState.enabled + : otherState; await _updateTracing( traceAllWidgets: traceAllWidgets, traceUserWidgets: traceUserWidgets, @@ -199,10 +195,10 @@ class _TraceWidgetBuildsSettingState extends State // widgets. Disable the service extension for tracing all widgets. await serviceConnection.serviceManager.serviceExtensionManager .setServiceExtensionState( - extensions.profileWidgetBuilds.extension, - enabled: false, - value: extensions.profileWidgetBuilds.disabledValue, - ); + extensions.profileWidgetBuilds.extension, + enabled: false, + value: extensions.profileWidgetBuilds.disabledValue, + ); traceAllWidgets = false; } @@ -211,9 +207,10 @@ class _TraceWidgetBuildsSettingState extends State // Double nested conditinoal expressions are hard to read. // ignore: prefer-conditional-expression if (_tracingEnabled.value) { - _selectedScope.value = traceUserWidgets - ? TraceWidgetBuildsScope.userCreated - : TraceWidgetBuildsScope.all; + _selectedScope.value = + traceUserWidgets + ? TraceWidgetBuildsScope.userCreated + : TraceWidgetBuildsScope.all; } else { _selectedScope.value = null; } @@ -234,10 +231,7 @@ class _TraceWidgetBuildsSettingState extends State }, ), MultiValueListenableBuilder( - listenables: [ - _tracingEnabled, - _selectedScope, - ], + listenables: [_tracingEnabled, _selectedScope], builder: (context, values, _) { final tracingEnabled = values.first as bool; final selectedScope = values.second as TraceWidgetBuildsScope?; @@ -300,26 +294,27 @@ class TraceWidgetBuildsCheckbox extends StatelessWidget { void _checkboxChanged(bool? value) async { final enabled = value == true; - final tracingExtensions = - TraceWidgetBuildsScope.values.map((scope) => scope.extensionForScope); + final tracingExtensions = TraceWidgetBuildsScope.values.map( + (scope) => scope.extensionForScope, + ); if (enabled) { // Default to tracing only user-created widgets. final extension = extensions.profileUserWidgetBuilds; await serviceConnection.serviceManager.serviceExtensionManager .setServiceExtensionState( - extension.extension, - enabled: true, - value: extension.enabledValue, - ); + extension.extension, + enabled: true, + value: extension.enabledValue, + ); } else { await Future.wait([ for (final extension in tracingExtensions) serviceConnection.serviceManager.serviceExtensionManager .setServiceExtensionState( - extension.extension, - enabled: false, - value: extension.disabledValue, - ), + extension.extension, + enabled: false, + value: extension.disabledValue, + ), ]); } } @@ -347,10 +342,7 @@ class TraceWidgetBuildsScopeSelector extends StatelessWidget { textStyle: textStyle, ), const SizedBox(width: defaultSpacing), - ..._scopeSetting( - TraceWidgetBuildsScope.all, - textStyle: textStyle, - ), + ..._scopeSetting(TraceWidgetBuildsScope.all, textStyle: textStyle), ], ); } @@ -366,10 +358,7 @@ class TraceWidgetBuildsScopeSelector extends StatelessWidget { materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, onChanged: enabled ? _changeScope : null, ), - Text( - type.radioDisplay, - style: textStyle, - ), + Text(type.radioDisplay, style: textStyle), ]; } @@ -377,21 +366,19 @@ class TraceWidgetBuildsScopeSelector extends StatelessWidget { assert(enabled); final extension = type!.extensionForScope; final opposite = type.opposite.extensionForScope; - await Future.wait( - [ - serviceConnection.serviceManager.serviceExtensionManager - .setServiceExtensionState( - opposite.extension, - enabled: false, - value: opposite.disabledValue, - ), - serviceConnection.serviceManager.serviceExtensionManager - .setServiceExtensionState( - extension.extension, - enabled: true, - value: extension.enabledValue, - ), - ], - ); + await Future.wait([ + serviceConnection.serviceManager.serviceExtensionManager + .setServiceExtensionState( + opposite.extension, + enabled: false, + value: opposite.disabledValue, + ), + serviceConnection.serviceManager.serviceExtensionManager + .setServiceExtensionState( + extension.extension, + enabled: true, + value: extension.enabledValue, + ), + ]); } } diff --git a/packages/devtools_app/lib/src/screens/performance/panes/controls/enhance_tracing/enhance_tracing_controller.dart b/packages/devtools_app/lib/src/screens/performance/panes/controls/enhance_tracing/enhance_tracing_controller.dart index 6ab917b4867..e5d0e572dd1 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/controls/enhance_tracing/enhance_tracing_controller.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/controls/enhance_tracing/enhance_tracing_controller.dart @@ -53,20 +53,21 @@ class EnhanceTracingController extends DisposableController /// This method assigns [_firstLiveFrameId] when the first 'Flutter.Frame' /// event is received, and then cancels the stream subscription. void _listenForFirstLiveFrame() { - _firstFrameEventSubscription = - serviceConnection.serviceManager.service!.onExtensionEvent.listen( - (event) { - if (event.extensionKind == 'Flutter.Frame' && - _firstLiveFrameId == null) { - _firstLiveFrameId = - FlutterFrame.fromJson(event.extensionData!.data).id; - // See https://github.com/dart-lang/linter/issues/3801 - // ignore: discarded_futures - unawaited(_firstFrameEventSubscription!.cancel()); - _firstFrameEventSubscription = null; - } - }, - ); + _firstFrameEventSubscription = serviceConnection + .serviceManager + .service! + .onExtensionEvent + .listen((event) { + if (event.extensionKind == 'Flutter.Frame' && + _firstLiveFrameId == null) { + _firstLiveFrameId = + FlutterFrame.fromJson(event.extensionData!.data).id; + // See https://github.com/dart-lang/linter/issues/3801 + // ignore: discarded_futures + unawaited(_firstFrameEventSubscription!.cancel()); + _firstFrameEventSubscription = null; + } + }); } void init() { @@ -92,7 +93,8 @@ class EnhanceTracingController extends DisposableController } void _updateTracingState() { - final builds = _extensionStates[extensions.profileWidgetBuilds]! || + final builds = + _extensionStates[extensions.profileWidgetBuilds]! || _extensionStates[extensions.profileUserWidgetBuilds]!; final layouts = _extensionStates[extensions.profileRenderObjectLayouts]!; final paints = _extensionStates[extensions.profileRenderObjectPaints]!; diff --git a/packages/devtools_app/lib/src/screens/performance/panes/controls/more_debugging_options.dart b/packages/devtools_app/lib/src/screens/performance/panes/controls/more_debugging_options.dart index c4df18096c6..630bc007aca 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/controls/more_debugging_options.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/controls/more_debugging_options.dart @@ -42,15 +42,18 @@ class MoreDebuggingOptionsButton extends StatelessWidget { style: theme.subtleTextStyle, ), if (serviceConnection - .serviceManager.connectedApp!.isProfileBuildNow!) ...[ + .serviceManager + .connectedApp! + .isProfileBuildNow!) ...[ const SizedBox(height: denseSpacing), RichText( text: TextSpan( text: "These debugging options aren't available in profile mode. " 'To use them, run your app in debug mode.', - style: theme.subtleTextStyle - .copyWith(color: theme.colorScheme.error), + style: theme.subtleTextStyle.copyWith( + color: theme.colorScheme.error, + ), ), ), ], diff --git a/packages/devtools_app/lib/src/screens/performance/panes/controls/performance_controls.dart b/packages/devtools_app/lib/src/screens/performance/panes/controls/performance_controls.dart index ef31f168af1..dcc334e2129 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/controls/performance_controls.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/controls/performance_controls.dart @@ -89,7 +89,9 @@ class _PrimaryControls extends StatelessWidget { return Row( children: [ if (serviceConnection - .serviceManager.connectedApp!.isFlutterAppNow!) ...[ + .serviceManager + .connectedApp! + .isFlutterAppNow!) ...[ VisibilityButton( show: preferences.performance.showFlutterFramesChart, gaScreen: gac.performance, @@ -123,9 +125,7 @@ class _PrimaryControls extends StatelessWidget { } class _SecondaryPerformanceControls extends StatelessWidget { - const _SecondaryPerformanceControls({ - required this.controller, - }); + const _SecondaryPerformanceControls({required this.controller}); final PerformanceController controller; @@ -140,9 +140,7 @@ class _SecondaryPerformanceControls extends StatelessWidget { ServiceExtensionButtonGroup( minScreenWidthForTextBeforeScaling: PerformanceControls.minScreenWidthForTextBeforeScaling, - extensions: [ - extensions.performanceOverlay, - ], + extensions: [extensions.performanceOverlay], ), const SizedBox(width: denseSpacing), EnhanceTracingButton(controller.enhanceTracingController), diff --git a/packages/devtools_app/lib/src/screens/performance/panes/controls/performance_settings.dart b/packages/devtools_app/lib/src/screens/performance/panes/controls/performance_settings.dart index 2ec00c39a86..31f9901bea4 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/controls/performance_settings.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/controls/performance_settings.dart @@ -32,9 +32,7 @@ class PerformanceSettingsDialog extends StatelessWidget { ), ], ), - actions: const [ - DialogCloseButton(), - ], + actions: const [DialogCloseButton()], ); } } @@ -50,8 +48,9 @@ class FlutterSettings extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ CheckboxSetting( - notifier: flutterFramesController.badgeTabForJankyFrames - as ValueNotifier, + notifier: + flutterFramesController.badgeTabForJankyFrames + as ValueNotifier, title: 'Badge Performance tab when Flutter UI jank is detected', ), ], 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 bc4443b1764..896735b140c 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 @@ -27,9 +27,10 @@ class FlutterFrame { final timeStart = Duration(microseconds: json[startTimeKey]! as int); final timeEnd = timeStart + Duration(microseconds: json[elapsedKey]! as int); - final frameTime = TimeRange() - ..start = timeStart - ..end = timeEnd; + final frameTime = + TimeRange() + ..start = timeStart + ..end = timeEnd; return FlutterFrame._( id: json[numberKey]! as int, timeFromFrameTiming: frameTime, @@ -107,8 +108,10 @@ class FlutterFrame { if (timelineEventData.rasterEvent == null) return Duration.zero; final shaderEvents = timelineEventData.rasterEvent! .shallowNodesWithCondition((event) => event.isShaderEvent); - final duration = - shaderEvents.fold(Duration.zero, (previous, event) { + final duration = shaderEvents.fold(Duration.zero, ( + previous, + event, + ) { return previous + event.time.duration; }); return _shaderTime = duration; @@ -147,13 +150,13 @@ class FlutterFrame { } Map get json => { - numberKey: id, - startTimeKey: timeFromFrameTiming.start!.inMicroseconds, - elapsedKey: timeFromFrameTiming.duration.inMicroseconds, - buildKey: buildTime.inMicroseconds, - rasterKey: rasterTime.inMicroseconds, - vsyncOverheadKey: vsyncOverheadTime.inMicroseconds, - }; + numberKey: id, + startTimeKey: timeFromFrameTiming.start!.inMicroseconds, + elapsedKey: timeFromFrameTiming.duration.inMicroseconds, + buildKey: buildTime.inMicroseconds, + rasterKey: rasterTime.inMicroseconds, + vsyncOverheadKey: vsyncOverheadTime.inMicroseconds, + }; @override String toString() { diff --git a/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frames_chart.dart b/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frames_chart.dart index cb3b5732b38..0d8209aaa1b 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frames_chart.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frames_chart.dart @@ -113,9 +113,10 @@ class _FlutterFramesChartState extends State<_FlutterFramesChart> { } void _maybeShowShaderJankMessage() { - final shaderJankFrames = widget.frames - .where((frame) => frame.hasShaderJank(widget.displayRefreshRate)) - .toList(); + final shaderJankFrames = + widget.frames + .where((frame) => frame.hasShaderJank(widget.displayRefreshRate)) + .toList(); if (shaderJankFrames.isNotEmpty) { final Duration shaderJankDuration = shaderJankFrames.fold( Duration.zero, @@ -145,7 +146,8 @@ class _FlutterFramesChartState extends State<_FlutterFramesChart> { right: denseSpacing, bottom: denseSpacing, ), - height: defaultChartHeight + + height: + defaultChartHeight + _FlutterFramesChart.frameNumberSectionHeight + _FlutterFramesChart.frameChartScrollbarOffset, child: Row( @@ -299,17 +301,18 @@ class _FramesChartState extends State with AutoDisposeMixin { scrollDirection: Axis.horizontal, itemCount: widget.frames.length, itemExtent: _defaultFrameWidthWithPadding, - itemBuilder: (context, index) => FlutterFramesChartItem( - framesController: widget.framesController, - index: index, - frame: widget.frames[index], - selected: widget.frames[index] == _selectedFrame, - msPerPx: _msPerPx, - availableChartHeight: - defaultChartHeight - 2 * _outlineBorderWidth, - displayRefreshRate: widget.displayRefreshRate, - onSelected: (index) => _selectedFrameIndex = index, - ), + itemBuilder: + (context, index) => FlutterFramesChartItem( + framesController: widget.framesController, + index: index, + frame: widget.frames[index], + selected: widget.frames[index] == _selectedFrame, + msPerPx: _msPerPx, + availableChartHeight: + defaultChartHeight - 2 * _outlineBorderWidth, + displayRefreshRate: widget.displayRefreshRate, + onSelected: (index) => _selectedFrameIndex = index, + ), ), ), ), @@ -321,7 +324,8 @@ class _FramesChartState extends State with AutoDisposeMixin { displayRefreshRate: widget.displayRefreshRate, msPerPx: _msPerPx, themeData: themeData, - bottomMargin: _FlutterFramesChart.frameChartScrollbarOffset + + bottomMargin: + _FlutterFramesChart.frameChartScrollbarOffset + _FlutterFramesChart.frameNumberSectionHeight, ), ); @@ -332,17 +336,15 @@ class _FramesChartState extends State with AutoDisposeMixin { displayRefreshRate: widget.displayRefreshRate, msPerPx: _msPerPx, themeData: themeData, - bottomMargin: _FlutterFramesChart.frameChartScrollbarOffset + + bottomMargin: + _FlutterFramesChart.frameChartScrollbarOffset + _FlutterFramesChart.frameNumberSectionHeight, ), ); return Stack( children: [ chartAxisPainter, - Padding( - padding: EdgeInsets.only(left: _yAxisUnitsSpace), - child: chart, - ), + Padding(padding: EdgeInsets.only(left: _yAxisUnitsSpace), child: chart), fpsLinePainter, Positioned( right: denseSpacing, @@ -409,18 +411,12 @@ class FramesChartControls extends StatelessWidget { Legend( dense: true, entries: [ - LegendEntry( - terse ? 'UI' : 'Frame Time (UI)', - mainUiColor, - ), + LegendEntry(terse ? 'UI' : 'Frame Time (UI)', mainUiColor), LegendEntry( terse ? 'Raster' : 'Frame Time (Raster)', mainRasterColor, ), - LegendEntry( - terse ? 'Jank' : 'Jank (slow frame)', - uiJankColor, - ), + LegendEntry(terse ? 'Jank' : 'Jank (slow frame)', uiJankColor), if (!impellerEnabled) LegendEntry( 'Shader Compilation', @@ -465,8 +461,9 @@ class FlutterFramesChartItem extends StatelessWidget { static const selectedIndicatorHeight = 8.0; - static const selectedFrameIndicatorKey = - Key('flutter frames chart - selected frame indicator'); + static const selectedFrameIndicatorKey = Key( + 'flutter frames chart - selected frame indicator', + ); final FlutterFramesController framesController; @@ -512,8 +509,10 @@ class FlutterFramesChartItem extends StatelessWidget { final ui = Container( key: Key('frame ${frame.id} - ui'), width: defaultFrameWidth / 2, - height: (frame.buildTime.inMilliseconds / msPerPx) - .clamp(0.0, availableChartHeight), + height: (frame.buildTime.inMilliseconds / msPerPx).clamp( + 0.0, + availableChartHeight, + ), color: uiColor, ); @@ -534,8 +533,10 @@ class FlutterFramesChartItem extends StatelessWidget { Container( key: Key('frame ${frame.id} - shaders'), width: defaultFrameWidth / 2, - height: (shaderDuration / msPerPx) - .clamp(0.0, availableChartHeight * shaderToRasterRatio), + height: (shaderDuration / msPerPx).clamp( + 0.0, + availableChartHeight * shaderToRasterRatio, + ), color: shaderColor, ), ], @@ -563,10 +564,7 @@ class FlutterFramesChartItem extends StatelessWidget { const Expanded(child: SizedBox()), Row( crossAxisAlignment: CrossAxisAlignment.end, - children: [ - ui, - raster, - ], + children: [ui, raster], ), ], ), @@ -591,19 +589,16 @@ class FlutterFramesChartItem extends StatelessWidget { ); return index % 2 == 0 ? Stack( - children: [ - content, - Container( - margin: EdgeInsets.only(top: defaultChartHeight), - height: _FlutterFramesChart.frameNumberSectionHeight, - alignment: AlignmentDirectional.center, - child: Text( - '${frame.id}', - style: themeData.subtleChartTextStyle, - ), - ), - ], - ) + children: [ + content, + Container( + margin: EdgeInsets.only(top: defaultChartHeight), + height: _FlutterFramesChart.frameNumberSectionHeight, + alignment: AlignmentDirectional.center, + child: Text('${frame.id}', style: themeData.subtleChartTextStyle), + ), + ], + ) : content; } @@ -616,11 +611,12 @@ class FlutterFramesChartItem extends StatelessWidget { ga.select( gac.performance, gac.PerformanceEvents.selectFlutterFrame.name, - screenMetricsProvider: () => PerformanceScreenMetrics( - uiDuration: frame.buildTime, - rasterDuration: frame.rasterTime, - shaderCompilationDuration: frame.shaderDuration, - ), + screenMetricsProvider: + () => PerformanceScreenMetrics( + uiDuration: frame.buildTime, + rasterDuration: frame.rasterTime, + shaderCompilationDuration: frame.shaderDuration, + ), ); } framesController.handleSelectedFrame(frame); @@ -657,29 +653,21 @@ class FlutterFrameTooltip extends StatelessWidget { } HoverCardData _buildCardData(TextStyle textStyle) { - final uiText = 'UI: ${durationText( - frame.buildTime, - unit: DurationDisplayUnit.milliseconds, - allowRoundingToZero: false, - )}'; - final rasterText = 'Raster: ${durationText( - frame.rasterTime, - unit: DurationDisplayUnit.milliseconds, - allowRoundingToZero: false, - )}'; - final shaderText = hasShaderJank - ? 'Shader Compilation: ${durationText( - frame.shaderDuration, - unit: DurationDisplayUnit.milliseconds, - allowRoundingToZero: false, - )} -' - : ''; + final uiText = + 'UI: ${durationText(frame.buildTime, unit: DurationDisplayUnit.milliseconds, allowRoundingToZero: false)}'; + final rasterText = + 'Raster: ${durationText(frame.rasterTime, unit: DurationDisplayUnit.milliseconds, allowRoundingToZero: false)}'; + final shaderText = + hasShaderJank + ? 'Shader Compilation: ${durationText(frame.shaderDuration, unit: DurationDisplayUnit.milliseconds, allowRoundingToZero: false)} -' + : ''; return HoverCardData( position: HoverCardPosition.element, - width: _calculateTooltipWidth( - [uiText, rasterText, shaderText], - textStyle, - ), + width: _calculateTooltipWidth([ + uiText, + rasterText, + shaderText, + ], textStyle), contents: Material( child: DefaultTextStyle( style: textStyle, @@ -701,8 +689,11 @@ class FlutterFrameTooltip extends StatelessWidget { MoreInfoLink( url: preCompileShadersDocsUrl, gaScreenName: gac.performance, - gaSelectedItemDescription: gac.PerformanceDocs - .shaderCompilationDocsTooltipLink.name, + gaSelectedItemDescription: + gac + .PerformanceDocs + .shaderCompilationDocsTooltipLink + .name, ), ], ), @@ -716,8 +707,9 @@ class FlutterFrameTooltip extends StatelessWidget { double _calculateTooltipWidth(List lines, TextStyle style) { var maxWidth = 0.0; for (final line in lines) { - final lineWidth = - calculateTextSpanWidth(TextSpan(text: line, style: style)); + final lineWidth = calculateTextSpanWidth( + TextSpan(text: line, style: style), + ); maxWidth = math.max(maxWidth, lineWidth); } // Add (2 * denseSpacing) for the card padding, and add @@ -830,10 +822,7 @@ class ChartAxisPainter extends CustomPainter { _paintYAxisLabels(canvas, chartArea); } - void _paintYAxisLabels( - Canvas canvas, - Rect chartArea, - ) { + void _paintYAxisLabels(Canvas canvas, Rect chartArea) { const yAxisLabelCount = 5; final totalMs = msPerPx * constraints.maxHeight; @@ -849,14 +838,18 @@ class ChartAxisPainter extends CustomPainter { // Y axis time units centered around [targetMsPerFrameRounded]. final yAxisTimes = [ 0, - for (int timeMs = targetMsPerFrameRounded - timeUnitMs; - timeMs > 0; - timeMs -= timeUnitMs) + for ( + int timeMs = targetMsPerFrameRounded - timeUnitMs; + timeMs > 0; + timeMs -= timeUnitMs + ) timeMs, targetMsPerFrameRounded, - for (int timeMs = targetMsPerFrameRounded + timeUnitMs; - timeMs < totalMs; - timeMs += timeUnitMs) + for ( + int timeMs = targetMsPerFrameRounded + timeUnitMs; + timeMs < totalMs; + timeMs += timeUnitMs + ) timeMs, ]; @@ -865,11 +858,7 @@ class ChartAxisPainter extends CustomPainter { } } - void _paintYAxisLabel( - Canvas canvas, - Rect chartArea, { - required int timeMs, - }) { + void _paintYAxisLabel(Canvas canvas, Rect chartArea, {required int timeMs}) { final labelText = durationText( Duration(milliseconds: timeMs), unit: DurationDisplayUnit.milliseconds, @@ -893,10 +882,7 @@ class ChartAxisPainter extends CustomPainter { // Paint the axis label. final textPainter = TextPainter( - text: TextSpan( - text: labelText, - style: themeData.subtleChartTextStyle, - ), + text: TextSpan(text: labelText, style: themeData.subtleChartTextStyle), textAlign: TextAlign.end, textDirection: TextDirection.ltr, )..layout(); @@ -979,10 +965,7 @@ class FPSLinePainter extends CustomPainter { textPainter.paint( canvas, - Offset( - chartArea.right - fpsTextSpace, - targetLineY + borderPadding, - ), + Offset(chartArea.right - fpsTextSpace, targetLineY + borderPadding), ); } 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 24da9f37d4d..ae594538ada 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 @@ -75,9 +75,10 @@ class FlutterFramesController extends PerformanceFeatureController { // Default to true for profile builds only. _badgeTabForJankyFrames.value = await connectedApp.isProfileBuild; - final refreshRate = connectedApp.isFlutterAppNow! - ? await serviceConnection.queryDisplayRefreshRate - : defaultRefreshRate; + final refreshRate = + connectedApp.isFlutterAppNow! + ? await serviceConnection.queryDisplayRefreshRate + : defaultRefreshRate; _displayRefreshRate.value = refreshRate ?? defaultRefreshRate; } @@ -143,8 +144,9 @@ class FlutterFramesController extends PerformanceFeatureController { void _maybeBadgeTabForJankyFrame(FlutterFrame frame) { if (_badgeTabForJankyFrames.value) { if (frame.isJanky(_displayRefreshRate.value)) { - serviceConnection.errorBadgeManager - .incrementBadgeCount(PerformanceScreen.id); + serviceConnection.errorBadgeManager.incrementBadgeCount( + PerformanceScreen.id, + ); } } } diff --git a/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_analysis.dart b/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_analysis.dart index 9a03afeae71..45648c45f92 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_analysis.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_analysis.dart @@ -55,8 +55,9 @@ class FlutterFrameAnalysisView extends StatelessWidget { ), TextSpan( text: '${frame.id}', - style: theme.fixedFontStyle - .copyWith(color: theme.colorScheme.primary), + style: theme.fixedFontStyle.copyWith( + color: theme.colorScheme.primary, + ), ), ], ), @@ -94,10 +95,11 @@ class FlutterFrameAnalysisView extends StatelessWidget { const PaddedDivider.noPadding(), ValueListenableBuilder( valueListenable: serviceConnection - .serviceManager.serviceExtensionManager + .serviceManager + .serviceExtensionManager .getServiceExtensionState( - extensions.countWidgetBuilds.extension, - ), + extensions.countWidgetBuilds.extension, + ), builder: (context, extensionState, _) { if (!extensionState.enabled) { return Row( @@ -119,9 +121,7 @@ class FlutterFrameAnalysisView extends StatelessWidget { ), ], if (rebuilds == null) - const Text( - 'Rebuild information not available for this frame.', - ) + const Text('Rebuild information not available for this frame.') else if (rebuilds.isEmpty) const Text( 'No widget rebuilds occurred for widgets that were directly ' 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 c3bc842475c..4b7fe9ec29b 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 @@ -63,12 +63,12 @@ class FrameAnalysis { final buildChildren = layoutEvent.shallowNodesWithCondition( (event) => FramePhaseType.build.isMatchForEventName(event.name), ); - final buildDuration = buildChildren.fold( - Duration.zero, - (previous, FlutterTimelineEvent event) { - return previous + event.time.duration; - }, - ); + final buildDuration = buildChildren.fold(Duration.zero, ( + previous, + FlutterTimelineEvent event, + ) { + return previous + event.time.duration; + }); return FramePhase.layout( events: [layoutEvent], @@ -109,11 +109,13 @@ class FrameAnalysis { late FramePhase longestUiPhase = _calculateLongestFramePhase(); - bool get hasUiData => _hasUiData ??= [ - ...buildPhase.events, - ...layoutPhase.events, - ...paintPhase.events, - ].isNotEmpty; + bool get hasUiData => + _hasUiData ??= + [ + ...buildPhase.events, + ...layoutPhase.events, + ...paintPhase.events, + ].isNotEmpty; bool? _hasUiData; @@ -272,15 +274,13 @@ enum FramePhaseType { } class FramePhase { - FramePhase._({ - required this.type, - required this.events, - Duration? duration, - }) : title = type.display, - duration = duration ?? - events.fold(Duration.zero, (previous, event) { - return previous + event.time.duration; - }); + FramePhase._({required this.type, required this.events, Duration? duration}) + : title = type.display, + duration = + duration ?? + events.fold(Duration.zero, (previous, event) { + return previous + event.time.duration; + }); factory FramePhase.build({ required List events, diff --git a/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_hints.dart b/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_hints.dart index 5be006420d7..b0de47b74be 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_hints.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_hints.dart @@ -44,32 +44,34 @@ class FrameHints extends StatelessWidget { final theme = Theme.of(context); final saveLayerCount = frameAnalysis.saveLayerCount; final intrinsicOperationsCount = frameAnalysis.intrinsicOperationsCount; - final uiHints = showUiJankHints - ? [ - Text('UI Jank Detected', style: theme.errorTextStyle), - const SizedBox(height: denseSpacing), - EnhanceTracingHint( - longestPhase: frameAnalysis.longestUiPhase, - enhanceTracingState: frameAnalysis.frame.enhanceTracingState, - enhanceTracingController: enhanceTracingController, - ), - const SizedBox(height: densePadding), - if (intrinsicOperationsCount > 0) - IntrinsicOperationsHint(intrinsicOperationsCount), - ] - : []; - final rasterHints = showRasterJankHints - ? [ - Text('Raster Jank Detected', style: theme.errorTextStyle), - const SizedBox(height: denseSpacing), - if (saveLayerCount > 0) CanvasSaveLayerHint(saveLayerCount), - const SizedBox(height: denseSpacing), - if (frame.hasShaderTime) - ShaderCompilationHint(shaderTime: frame.shaderDuration), - const SizedBox(height: denseSpacing), - const GeneralRasterJankHint(), - ] - : []; + final uiHints = + showUiJankHints + ? [ + Text('UI Jank Detected', style: theme.errorTextStyle), + const SizedBox(height: denseSpacing), + EnhanceTracingHint( + longestPhase: frameAnalysis.longestUiPhase, + enhanceTracingState: frameAnalysis.frame.enhanceTracingState, + enhanceTracingController: enhanceTracingController, + ), + const SizedBox(height: densePadding), + if (intrinsicOperationsCount > 0) + IntrinsicOperationsHint(intrinsicOperationsCount), + ] + : []; + final rasterHints = + showRasterJankHints + ? [ + Text('Raster Jank Detected', style: theme.errorTextStyle), + const SizedBox(height: denseSpacing), + if (saveLayerCount > 0) CanvasSaveLayerHint(saveLayerCount), + const SizedBox(height: denseSpacing), + if (frame.hasShaderTime) + ShaderCompilationHint(shaderTime: frame.shaderDuration), + const SizedBox(height: denseSpacing), + const GeneralRasterJankHint(), + ] + : []; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -92,10 +94,7 @@ class _Hint extends StatelessWidget { Widget build(BuildContext context) { return Row( children: [ - Icon( - Icons.lightbulb_outline, - size: defaultIconSize, - ), + Icon(Icons.lightbulb_outline, size: defaultIconSize), const SizedBox(width: denseSpacing), Expanded(child: message), ], @@ -130,10 +129,7 @@ class EnhanceTracingHint extends StatelessWidget { text: TextSpan( text: '', children: [ - TextSpan( - text: longestPhase.title, - style: theme.fixedFontStyle, - ), + TextSpan(text: longestPhase.title, style: theme.fixedFontStyle), TextSpan( text: ' was the longest UI phase in this frame. ', style: theme.regularTextStyle, @@ -145,10 +141,7 @@ class EnhanceTracingHint extends StatelessWidget { ); } - List _hintForPhase( - FramePhase phase, - ThemeData theme, - ) { + List _hintForPhase(FramePhase phase, ThemeData theme) { final phaseType = phase.type; // TODO(kenz): when [enhanceTracingState] is not available, use heuristics // to detect whether tracing was enhanced for a frame (e.g. the depth or @@ -191,7 +184,8 @@ class EnhanceTracingHint extends StatelessWidget { if (tracingEnhanced) { return [ TextSpan( - text: 'Since "$settingTitle" was enabled while this frame was drawn, ' + text: + 'Since "$settingTitle" was enabled while this frame was drawn, ' 'you should be able to see timeline events for each ' '$eventDescription.', style: theme.regularTextStyle, @@ -244,10 +238,7 @@ class SmallEnhanceTracingButton extends StatelessWidget { @visibleForTesting class IntrinsicOperationsHint extends StatelessWidget { - const IntrinsicOperationsHint( - this.intrinsicOperationsCount, { - super.key, - }); + const IntrinsicOperationsHint(this.intrinsicOperationsCount, {super.key}); static const _intrinsicOperationsDocs = 'https://flutter.dev/to/minimize-layout-passes'; @@ -265,12 +256,10 @@ class IntrinsicOperationsHint extends StatelessWidget { gac.PerformanceDocs.intrinsicOperationsDocs.name, message: TextSpan( children: [ + TextSpan(text: 'Intrinsic', style: theme.fixedFontStyle), TextSpan( - text: 'Intrinsic', - style: theme.fixedFontStyle, - ), - TextSpan( - text: ' passes were performed $intrinsicOperationsCount ' + text: + ' passes were performed $intrinsicOperationsCount ' '${pluralize('time', intrinsicOperationsCount)} during this ' 'frame.', style: theme.regularTextStyle, @@ -288,10 +277,7 @@ class IntrinsicOperationsHint extends StatelessWidget { // args, display it in the hint. @visibleForTesting class CanvasSaveLayerHint extends StatelessWidget { - const CanvasSaveLayerHint( - this.saveLayerCount, { - super.key, - }); + const CanvasSaveLayerHint(this.saveLayerCount, {super.key}); static const _saveLayerDocs = 'https://flutter.dev/to/save-layer-perf'; @@ -307,12 +293,10 @@ class CanvasSaveLayerHint extends StatelessWidget { gaSelectedItemDescription: gac.PerformanceDocs.canvasSaveLayerDocs.name, message: TextSpan( children: [ + TextSpan(text: 'Canvas.saveLayer()', style: theme.fixedFontStyle), TextSpan( - text: 'Canvas.saveLayer()', - style: theme.fixedFontStyle, - ), - TextSpan( - text: ' was called $saveLayerCount ' + text: + ' was called $saveLayerCount ' '${pluralize('time', saveLayerCount)} during this frame.', style: theme.regularTextStyle, ), @@ -325,10 +309,7 @@ class CanvasSaveLayerHint extends StatelessWidget { @visibleForTesting class ShaderCompilationHint extends StatelessWidget { - const ShaderCompilationHint({ - super.key, - required this.shaderTime, - }); + const ShaderCompilationHint({super.key, required this.shaderTime}); final Duration shaderTime; @@ -356,30 +337,28 @@ class ShaderCompilationHint extends StatelessWidget { ), ], ), - childrenSpans: serviceConnection.serviceManager.connectedApp!.isIosApp - ? [ - TextSpan( - text: - ' Note: pre-compiling shaders is a legacy solution with many ' - 'pitfalls. Try ', - style: theme.regularTextStyle, - ), - GaLinkTextSpan( - link: GaLink( - display: 'Impeller', - url: impellerDocsUrl, - gaScreenName: gac.performance, - gaSelectedItemDescription: - gac.PerformanceDocs.impellerDocsLink.name, + childrenSpans: + serviceConnection.serviceManager.connectedApp!.isIosApp + ? [ + TextSpan( + text: + ' Note: pre-compiling shaders is a legacy solution with many ' + 'pitfalls. Try ', + style: theme.regularTextStyle, ), - context: context, - ), - TextSpan( - text: ' instead!', - style: theme.regularTextStyle, - ), - ] - : [], + GaLinkTextSpan( + link: GaLink( + display: 'Impeller', + url: impellerDocsUrl, + gaScreenName: gac.performance, + gaSelectedItemDescription: + gac.PerformanceDocs.impellerDocsLink.name, + ), + context: context, + ), + TextSpan(text: ' instead!', style: theme.regularTextStyle), + ] + : [], ), ); } @@ -397,7 +376,8 @@ class GeneralRasterJankHint extends StatelessWidget { text: TextSpan( children: [ TextSpan( - text: 'To learn about rendering performance in Flutter, check ' + text: + 'To learn about rendering performance in Flutter, check ' 'out the Flutter documentation on ', style: theme.regularTextStyle, ), @@ -411,10 +391,7 @@ class GeneralRasterJankHint extends StatelessWidget { ), context: context, ), - TextSpan( - text: '.', - style: theme.regularTextStyle, - ), + TextSpan(text: '.', style: theme.regularTextStyle), ], ), ), @@ -444,10 +421,7 @@ class _ExpensiveOperationHint extends StatelessWidget { text: TextSpan( children: [ message, - TextSpan( - text: ' This may ', - style: theme.regularTextStyle, - ), + TextSpan(text: ' This may ', style: theme.regularTextStyle), GaLinkTextSpan( context: context, link: GaLink( @@ -458,10 +432,7 @@ class _ExpensiveOperationHint extends StatelessWidget { 'frameAnalysis_$gaSelectedItemDescription', ), ), - TextSpan( - text: '.', - style: theme.regularTextStyle, - ), + TextSpan(text: '.', style: theme.regularTextStyle), ...childrenSpans, ], ), diff --git a/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_time_visualizer.dart b/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_time_visualizer.dart index 4515f570c55..a47b8141204 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_time_visualizer.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_time_visualizer.dart @@ -13,10 +13,7 @@ import '../../../../shared/ui/utils.dart'; import 'frame_analysis_model.dart'; class FrameTimeVisualizer extends StatefulWidget { - const FrameTimeVisualizer({ - super.key, - required this.frameAnalysis, - }); + const FrameTimeVisualizer({super.key, required this.frameAnalysis}); final FrameAnalysis frameAnalysis; @@ -154,12 +151,16 @@ class _FrameBlockGroup extends StatelessWidget { Widget build(BuildContext context) { Widget content; if (hasData) { - final totalFlex = - data.fold(0, (current, block) => current + block.flex); + final totalFlex = data.fold( + 0, + (current, block) => current + block.flex, + ); content = LayoutBuilder( builder: (context, constraints) { - final adjustedBlockWidths = - adjustedWidthsForBlocks(constraints, totalFlex); + final adjustedBlockWidths = adjustedWidthsForBlocks( + constraints, + totalFlex, + ); return Row( children: [ for (var i = 0; i < data.length; i++) @@ -177,11 +178,7 @@ class _FrameBlockGroup extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(title), - const SizedBox(height: denseSpacing), - content, - ], + children: [Text(title), const SizedBox(height: denseSpacing), content], ); } @@ -194,11 +191,12 @@ class _FrameBlockGroup extends StatelessWidget { BoxConstraints constraints, int totalFlex, ) { - final unadjustedBlockWidths = data - .map( - (blockData) => constraints.maxWidth * blockData.flex / totalFlex, - ) - .toList(); + final unadjustedBlockWidths = + data + .map( + (blockData) => constraints.maxWidth * blockData.flex / totalFlex, + ) + .toList(); var adjustment = 0.0; var widestBlockIndex = 0; @@ -213,11 +211,13 @@ class _FrameBlockGroup extends StatelessWidget { } } - final adjustedBlockWidths = unadjustedBlockWidths - .map( - (blockWidth) => math.max(blockWidth, _FramePhaseBlock.minBlockWidth), - ) - .toList(); + final adjustedBlockWidths = + unadjustedBlockWidths + .map( + (blockWidth) => + math.max(blockWidth, _FramePhaseBlock.minBlockWidth), + ) + .toList(); final widest = adjustedBlockWidths[widestBlockIndex]; adjustedBlockWidths[widestBlockIndex] = math.max( widest - adjustment, @@ -229,10 +229,7 @@ class _FrameBlockGroup extends StatelessWidget { } class _FramePhaseBlock extends StatelessWidget { - const _FramePhaseBlock({ - required this.blockData, - required this.width, - }); + const _FramePhaseBlock({required this.blockData, required this.width}); static const _height = 24.0; @@ -263,7 +260,8 @@ class _FramePhaseBlock extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: densePadding), child: LayoutBuilder( builder: (context, constraints) { - final minWidthForText = defaultIconSize + + final minWidthForText = + defaultIconSize + densePadding * 2 + denseSpacing + calculateTextSpanWidth(TextSpan(text: blockData.display)); @@ -274,16 +272,10 @@ class _FramePhaseBlock extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - blockData.icon, - size: defaultIconSize, - ), + Icon(blockData.icon, size: defaultIconSize), if (includeText) ...[ const SizedBox(width: denseSpacing), - Text( - blockData.display, - overflow: TextOverflow.ellipsis, - ), + Text(blockData.display, overflow: TextOverflow.ellipsis), ], ], ); @@ -311,13 +303,14 @@ class _FramePhaseBlockData { final IconData icon; String get display { - final text = duration != Duration.zero - ? durationText( - duration, - unit: DurationDisplayUnit.milliseconds, - allowRoundingToZero: false, - ) - : '--'; + final text = + duration != Duration.zero + ? durationText( + duration, + unit: DurationDisplayUnit.milliseconds, + allowRoundingToZero: false, + ) + : '--'; return '$title - $text'; } } diff --git a/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats.dart b/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats.dart index 146f3268d92..53a319a1e86 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats.dart @@ -107,8 +107,9 @@ class _RebuildStatsViewState extends State ), Expanded( child: Padding( - padding: - const EdgeInsets.symmetric(horizontal: denseSpacing), + padding: const EdgeInsets.symmetric( + horizontal: denseSpacing, + ), child: ServiceExtensionCheckbox( serviceExtension: extensions.countWidgetBuilds, ), @@ -121,10 +122,11 @@ class _RebuildStatsViewState extends State Expanded( child: ValueListenableBuilder( valueListenable: serviceConnection - .serviceManager.serviceExtensionManager + .serviceManager + .serviceExtensionManager .getServiceExtensionState( - extensions.countWidgetBuilds.extension, - ), + extensions.countWidgetBuilds.extension, + ), builder: (context, state, _) { if (metrics.isEmpty && !state.enabled) { return const Center( @@ -135,9 +137,7 @@ class _RebuildStatsViewState extends State } if (metrics.isEmpty) { return const Center( - child: Text( - 'Interact with the app to trigger rebuilds.', - ), + child: Text('Interact with the app to trigger rebuilds.'), ); // No data to display but there should be data soon. } return RebuildTable( @@ -196,8 +196,11 @@ class _RebuildTableState extends State { static final _widgetColumn = _WidgetColumn(); static final _locationColumn = _LocationColumn(); - List> get _columns => - [_widgetColumn, ..._metricsColumns, _locationColumn]; + List> get _columns => [ + _widgetColumn, + ..._metricsColumns, + _locationColumn, + ]; @override Widget build(BuildContext context) { @@ -205,8 +208,9 @@ class _RebuildTableState extends State { dataKey: 'RebuildMetricsTable', columns: _columns, data: widget.metrics, - keyFactory: (RebuildLocationStats location) => - ValueKey('${location.location.id}'), + keyFactory: + (RebuildLocationStats location) => + ValueKey('${location.location.id}'), defaultSortColumn: _metricsColumns.first, defaultSortDirection: sortDirection, onItemSelected: (item) async { @@ -226,11 +230,7 @@ class _RebuildTableState extends State { } class _WidgetColumn extends ColumnData { - _WidgetColumn() - : super( - 'Widget', - fixedWidthPx: scaleByFontFactor(200), - ); + _WidgetColumn() : super('Widget', fixedWidthPx: scaleByFontFactor(200)); @override String getValue(RebuildLocationStats dataObject) { @@ -263,9 +263,7 @@ class _LocationColumn extends ColumnData { class _RebuildCountColumn extends ColumnData { _RebuildCountColumn(super.name, this.metricIndex) - : super( - fixedWidthPx: scaleByFontFactor(130), - ); + : super(fixedWidthPx: scaleByFontFactor(130)); final int metricIndex; 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 74c1f23fbbe..66cecadc4a2 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 @@ -307,7 +307,7 @@ class RebuildLocation { /// the last route change. class RebuildLocationStats { RebuildLocationStats(this.location, {required int numStats}) - : buildCounts = List.filled(numStats, 0); + : buildCounts = List.filled(numStats, 0); final Location location; final List buildCounts; } @@ -321,14 +321,12 @@ List combineStats( final statsForIndex = rebuildStats[i]; for (final entry in statsForIndex) { output - .putIfAbsent( - entry.location, - () => RebuildLocationStats( - entry.location, - numStats: numStats, - ), - ) - .buildCounts[i] = entry.buildCount; + .putIfAbsent( + entry.location, + () => RebuildLocationStats(entry.location, numStats: numStats), + ) + .buildCounts[i] = + entry.buildCount; } } return output.values.toList(growable: false); 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 01dab9bdf76..a857e2a25eb 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 @@ -123,8 +123,9 @@ class PerfettoControllerImpl extends PerfettoController { origin: window.location.origin, path: window.location.pathname, ); - final indexFilePath = ui_web.assetManager - .getAssetUrl(devToolsEnvironmentParameters.perfettoIndexLocation); + final indexFilePath = ui_web.assetManager.getAssetUrl( + devToolsEnvironmentParameters.perfettoIndexLocation, + ); final baseUrl = '$basePath/$indexFilePath'; return '$baseUrl$_embeddedModeQuery'; } @@ -164,11 +165,12 @@ class PerfettoControllerImpl extends PerfettoController { ); _initialized = true; - _perfettoIFrame = HTMLIFrameElement() - // This url is safe because we built it ourselves and it does not include - // any user input. - ..src = perfettoUrl - ..allow = 'usb'; + _perfettoIFrame = + HTMLIFrameElement() + // This url is safe because we built it ourselves and it does not include + // any user input. + ..src = perfettoUrl + ..allow = 'usb'; _perfettoIFrame.style ..border = 'none' ..height = '100%' 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 175990a7c8c..41deb693757 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,10 +7,7 @@ import 'package:flutter/material.dart'; import 'perfetto_controller.dart'; class Perfetto extends StatelessWidget { - const Perfetto({ - super.key, - required this.perfettoController, - }); + const Perfetto({super.key, required this.perfettoController}); final PerfettoController perfettoController; diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_web.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_web.dart index 9d60603b9d2..31e660eec71 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_web.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_web.dart @@ -26,10 +26,7 @@ import 'perfetto_controller.dart'; final _log = Logger('PerfettoWeb'); class Perfetto extends StatefulWidget { - const Perfetto({ - super.key, - required this.perfettoController, - }); + const Perfetto({super.key, required this.perfettoController}); final PerfettoController perfettoController; @@ -83,9 +80,7 @@ class _PerfettoState extends State with AutoDisposeMixin { Widget build(BuildContext context) { return Container( color: Theme.of(context).scaffoldBackgroundColor, - child: HtmlElementView( - viewType: _perfettoController.viewId, - ), + child: HtmlElementView(viewType: _perfettoController.viewId), ); } @@ -237,9 +232,7 @@ class _PerfettoViewController extends DisposableController _postMessageWithId( EmbeddedPerfettoEvent.devtoolsThemeChange.event, perfettoIgnore: true, - args: { - 'theme': darkMode ? 'dark' : 'light', - }, + args: {'theme': darkMode ? 'dark' : 'light'}, ); } @@ -309,12 +302,14 @@ class _PerfettoViewController extends DisposableController Future _pingPerfettoUntilReady() async { if (!_perfettoHandlerReady.isCompleted) { - _pollForPerfettoHandlerReady = - Timer.periodic(const Duration(milliseconds: 200), (_) { - // Once the Perfetto UI is ready, Perfetto will receive this 'PING' - // message and return a 'PONG' message, handled in [_handleMessage]. - _postMessage(EmbeddedPerfettoEvent.ping.event); - }); + _pollForPerfettoHandlerReady = Timer.periodic( + const Duration(milliseconds: 200), + (_) { + // Once the Perfetto UI is ready, Perfetto will receive this 'PING' + // message and return a 'PONG' message, handled in [_handleMessage]. + _postMessage(EmbeddedPerfettoEvent.ping.event); + }, + ); await _perfettoHandlerReady.future.timeout( _pollUntilReadyTimeout, @@ -326,16 +321,18 @@ class _PerfettoViewController extends DisposableController Future _pingDevToolsThemeHandlerUntilReady() async { if (!_devtoolsThemeHandlerReady.isCompleted) { - _pollForThemeHandlerReady = - Timer.periodic(const Duration(milliseconds: 200), (_) { - // Once [devtools_theme_handler.js] is ready, it will receive this - // 'PING-DEVTOOLS-THEME' message and return a 'PONG-DEVTOOLS-THEME' - // message, handled in [_handleMessage]. - _postMessageWithId( - EmbeddedPerfettoEvent.devtoolsThemePing.event, - perfettoIgnore: true, - ); - }); + _pollForThemeHandlerReady = Timer.periodic( + const Duration(milliseconds: 200), + (_) { + // Once [devtools_theme_handler.js] is ready, it will receive this + // 'PING-DEVTOOLS-THEME' message and return a 'PONG-DEVTOOLS-THEME' + // message, handled in [_handleMessage]. + _postMessageWithId( + EmbeddedPerfettoEvent.devtoolsThemePing.event, + perfettoIgnore: true, + ); + }, + ); await _devtoolsThemeHandlerReady.future.timeout( _pollUntilReadyTimeout, diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto.dart index c1789811d9a..b3400f57c3f 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto.dart @@ -17,9 +17,7 @@ class EmbeddedPerfetto extends StatelessWidget { @override Widget build(BuildContext context) { - return Perfetto( - perfettoController: perfettoController, - ); + return Perfetto(perfettoController: perfettoController); } } 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 60ae5eec428..8b71bda297e 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 @@ -38,9 +38,10 @@ class PerfettoTrackDescriptorEvent extends _PerfettoTracePacket { final TrackDescriptor trackDescriptor; - String get name => trackDescriptor.name.isNotEmpty - ? trackDescriptor.name - : trackDescriptor.thread.threadName; + String get name => + trackDescriptor.name.isNotEmpty + ? trackDescriptor.name + : trackDescriptor.thread.threadName; Int64 get id => trackDescriptor.uuid; diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_event_processor.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_event_processor.dart index 786dad69d88..c53e438912f 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_event_processor.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_event_processor.dart @@ -133,7 +133,8 @@ class FlutterTimelineEventProcessor { TimelineEventType _inferTrackType(PerfettoTrackEvent event) { // Whether the UI and Raster events are expected to come on a single track. // This is expected when DevTools is connected to a flutter-tester device. - final singleTrackType = uiTrackId != null && + final singleTrackType = + uiTrackId != null && rasterTrackId != null && uiTrackId == rasterTrackId; 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 0638b8b2a09..9050d50bc6a 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 @@ -30,11 +30,7 @@ import 'perfetto/tracing/model.dart'; final _log = Logger('timeline_events_controller'); -enum EventsControllerStatus { - empty, - refreshing, - ready, -} +enum EventsControllerStatus { empty, refreshing, ready } class TimelineEventsController extends PerformanceFeatureController with AutoDisposeControllerMixin { @@ -110,8 +106,9 @@ class TimelineEventsController extends PerformanceFeatureController /// Whether the recorded timeline data is currently being processed. ValueListenable get status => _status; - final _status = - ValueNotifier(EventsControllerStatus.empty); + final _status = ValueNotifier( + EventsControllerStatus.empty, + ); final _refreshWorkTracker = FutureWorkTracker(); @@ -184,40 +181,33 @@ class TimelineEventsController extends PerformanceFeatureController late PerfettoTimeline rawPerfettoTimeline; if (preferences.performance.includeCpuSamplesInTimeline.value) { - await debugTimeAsync( - () async { - await ga.timeAsync( - gac.performance, - gac.PerformanceEvents.getPerfettoVMTimelineWithCpuSamplesTime.name, - asyncOperation: () async { - rawPerfettoTimeline = - await service.getPerfettoVMTimelineWithCpuSamplesWrapper( - timeOriginMicros: _nextPollStartMicros, - timeExtentMicros: - currentVmTime.timestamp! - _nextPollStartMicros, - ); - }, - ); - }, - debugName: 'VmService.getPerfettoVMTimelineWithCpuSamples', - ); + await debugTimeAsync(() async { + await ga.timeAsync( + gac.performance, + gac.PerformanceEvents.getPerfettoVMTimelineWithCpuSamplesTime.name, + asyncOperation: () async { + rawPerfettoTimeline = await service + .getPerfettoVMTimelineWithCpuSamplesWrapper( + timeOriginMicros: _nextPollStartMicros, + timeExtentMicros: + currentVmTime.timestamp! - _nextPollStartMicros, + ); + }, + ); + }, debugName: 'VmService.getPerfettoVMTimelineWithCpuSamples'); } else { - await debugTimeAsync( - () async { - await ga.timeAsync( - gac.performance, - gac.PerformanceEvents.getPerfettoVMTimelineTime.name, - asyncOperation: () async { - rawPerfettoTimeline = await service.getPerfettoVMTimeline( - timeOriginMicros: _nextPollStartMicros, - timeExtentMicros: - currentVmTime.timestamp! - _nextPollStartMicros, - ); - }, - ); - }, - debugName: 'VmService.getPerfettoVMTimeline', - ); + await debugTimeAsync(() async { + await ga.timeAsync( + gac.performance, + gac.PerformanceEvents.getPerfettoVMTimelineTime.name, + asyncOperation: () async { + rawPerfettoTimeline = await service.getPerfettoVMTimeline( + timeOriginMicros: _nextPollStartMicros, + timeExtentMicros: currentVmTime.timestamp! - _nextPollStartMicros, + ); + }, + ); + }, debugName: 'VmService.getPerfettoVMTimeline'); } _nextPollStartMicros = currentVmTime.timestamp! + 1; @@ -241,8 +231,9 @@ class TimelineEventsController extends PerformanceFeatureController }) { if (!_isFlutterAppHelper()) { debugTraceCallback( - () => _log - .info('[_prepareTraceForProcessing] not a flutter app, returning.'), + () => _log.info( + '[_prepareTraceForProcessing] not a flutter app, returning.', + ), ); return; } @@ -251,8 +242,9 @@ class TimelineEventsController extends PerformanceFeatureController final newTrackDescriptors = []; for (final packet in trace.packet) { if (packet.hasTrackDescriptor()) { - final trackDescriptor = - PerfettoTrackDescriptorEvent(packet.trackDescriptor); + final trackDescriptor = PerfettoTrackDescriptorEvent( + packet.trackDescriptor, + ); final added = _trackDescriptors.add(trackDescriptor); if (added) { newTrackDescriptors.add(trackDescriptor); @@ -367,10 +359,12 @@ class TimelineEventsController extends PerformanceFeatureController ga.timeSync( gac.performance, gac.PerformanceEvents.perfettoModeTraceEventProcessingTime.nameOverride!, - syncOperation: () => perfettoController.processor - .processTrackEvents(_unprocessedTrackEvents), - screenMetricsProvider: () => - PerformanceScreenMetrics(traceEventCount: eventCount), + syncOperation: + () => perfettoController.processor.processTrackEvents( + _unprocessedTrackEvents, + ), + screenMetricsProvider: + () => PerformanceScreenMetrics(traceEventCount: eventCount), ); _unprocessedTrackEvents.clear(); } @@ -388,11 +382,11 @@ class TimelineEventsController extends PerformanceFeatureController void processMoreEventsOrExitHelper({ required FutureOr Function() onProcessMore, }) async { - final hasProcessedTimelineEventsForFrame = - perfettoController.processor.hasProcessedEventsForFrame(frame.id); + final hasProcessedTimelineEventsForFrame = perfettoController.processor + .hasProcessedEventsForFrame(frame.id); if (!hasProcessedTimelineEventsForFrame) { - final timelineEventsUnavailable = - perfettoController.processor.frameIsBeforeTimelineData(frame.id); + final timelineEventsUnavailable = perfettoController.processor + .frameIsBeforeTimelineData(frame.id); if (timelineEventsUnavailable) { _maybePushNoTimelineEventsWarning(); return; @@ -429,8 +423,9 @@ class TimelineEventsController extends PerformanceFeatureController ); await forceRefresh(); - final hasProcessedTimelineEventsForFrame = - perfettoController.processor.hasProcessedEventsForFrame(frame.id); + final hasProcessedTimelineEventsForFrame = perfettoController + .processor + .hasProcessedEventsForFrame(frame.id); if (!hasProcessedTimelineEventsForFrame) { // At this point, we still have not processed any timeline events // for this Flutter frame, which means we will never have access to @@ -465,11 +460,8 @@ class TimelineEventsController extends PerformanceFeatureController event, ); } else { - final unassignedEventsForFrame = - _unassignedFlutterTimelineEvents.putIfAbsent( - frameNumber, - () => FrameTimelineEventData(), - ); + final unassignedEventsForFrame = _unassignedFlutterTimelineEvents + .putIfAbsent(frameNumber, () => FrameTimelineEventData()); unassignedEventsForFrame.setEventFlow(event: event, setTimeData: false); } } @@ -516,8 +508,9 @@ class TimelineEventsController extends PerformanceFeatureController await loadPerfettoTrace(); if (offlineData.selectedFrame != null) { - perfettoController - .scrollToTimeRange(offlineData.selectedFrame!.timeFromFrameTiming); + perfettoController.scrollToTimeRange( + offlineData.selectedFrame!.timeFromFrameTiming, + ); } } diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_events_view.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_events_view.dart index 8a79bef198a..9cb0c1c6b84 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_events_view.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_events_view.dart @@ -191,9 +191,10 @@ class RefreshTimelineEventsButton extends StatelessWidget { return RefreshButton( iconOnly: true, outlined: false, - onPressed: status == EventsControllerStatus.refreshing - ? null - : controller.forceRefresh, + onPressed: + status == EventsControllerStatus.refreshing + ? null + : controller.forceRefresh, tooltip: 'Refresh timeline events', gaScreen: gac.performance, gaSelection: gac.PerformanceEvents.refreshTimelineEvents.name, @@ -251,9 +252,7 @@ class _TimelineSettingsDialogState extends State ], ), ), - actions: const [ - DialogCloseButton(), - ], + actions: const [DialogCloseButton()], ); } @@ -267,12 +266,7 @@ class _TimelineSettingsDialogState extends State ), const SizedBox(height: defaultSpacing), ...dialogSubHeader(theme, 'Trace categories'), - RichText( - text: TextSpan( - text: 'Default', - style: theme.subtleTextStyle, - ), - ), + RichText(text: TextSpan(text: 'Default', style: theme.subtleTextStyle)), ..._timelineStreams(advanced: false), // Special case "Network Traffic" because it is not implemented as a // Timeline recorded stream in the VM. The user does not need to be aware of @@ -281,46 +275,41 @@ class _TimelineSettingsDialogState extends State title: 'Network', description: 'Http traffic', notifier: _httpLogging, - onChanged: (value) => unawaited( - http_service.toggleHttpRequestLogging(value ?? false), - ), + onChanged: + (value) => unawaited( + http_service.toggleHttpRequestLogging(value ?? false), + ), ), ]; } List _advancedStreams(ThemeData theme) { return [ - RichText( - text: TextSpan( - text: 'Advanced', - style: theme.subtleTextStyle, - ), - ), + RichText(text: TextSpan(text: 'Advanced', style: theme.subtleTextStyle)), ..._timelineStreams(advanced: true), ]; } - List _timelineStreams({ - required bool advanced, - }) { - final streams = advanced - ? serviceConnection.timelineStreamManager.advancedStreams - : serviceConnection.timelineStreamManager.basicStreams; - final settings = streams - .map( - (stream) => CheckboxSetting( - title: stream.name, - description: stream.description, - notifier: stream.recorded as ValueNotifier, - onChanged: (newValue) => unawaited( - serviceConnection.timelineStreamManager.updateTimelineStream( - stream, - newValue ?? false, + List _timelineStreams({required bool advanced}) { + final streams = + advanced + ? serviceConnection.timelineStreamManager.advancedStreams + : serviceConnection.timelineStreamManager.basicStreams; + final settings = + streams + .map( + (stream) => CheckboxSetting( + title: stream.name, + description: stream.description, + notifier: stream.recorded as ValueNotifier, + onChanged: + (newValue) => unawaited( + serviceConnection.timelineStreamManager + .updateTimelineStream(stream, newValue ?? false), + ), ), - ), - ), - ) - .toList(); + ) + .toList(); return settings; } } diff --git a/packages/devtools_app/lib/src/screens/performance/performance_controller.dart b/packages/devtools_app/lib/src/screens/performance/performance_controller.dart index c2935f55229..87154b6a886 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_controller.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_controller.dart @@ -106,9 +106,7 @@ class PerformanceController extends DisposableController if (serviceConnection.serviceManager.connectedApp?.isFlutterAppNow ?? false) { final impellerEnabledResponse = await serviceConnection.serviceManager - .callServiceExtensionOnMainIsolate( - registrations.isImpellerEnabled, - ); + .callServiceExtensionOnMainIsolate(registrations.isImpellerEnabled); _impellerEnabled = impellerEnabledResponse.json?['enabled'] == true; } else { _impellerEnabled = false; @@ -120,27 +118,31 @@ class PerformanceController extends DisposableController // Listen for Flutter.RebuiltWidgets events. autoDisposeStreamSubscription( serviceConnection - .serviceManager.service!.onExtensionEventWithHistorySafe + .serviceManager + .service! + .onExtensionEventWithHistorySafe .listen((event) { - if (event.extensionKind == FlutterEvent.frame) { - final frame = FlutterFrame.fromJson(event.extensionData!.data); - enhanceTracingController.assignStateForFrame(frame); - flutterFramesController.addFrame(frame); - } else if (event.extensionKind == FlutterEvent.rebuiltWidgets && - FeatureFlags.widgetRebuildStats) { - if (_currentRebuildWidgetsIsolate != event.isolate) { - rebuildCountModel.clearFromRestart(); - } - _currentRebuildWidgetsIsolate = event.isolate; - // TODO(jacobr): need to make sure we don't get events from before - // the last hot restart. Their data would be bogus. - rebuildCountModel.processRebuildEvent(event.extensionData!.data); - if (!rebuildCountModel.locationMap.locationsResolved.value && - !_fetchMissingLocationsStarted) { - _fetchMissingRebuildLocations(); - } - } - }), + if (event.extensionKind == FlutterEvent.frame) { + final frame = FlutterFrame.fromJson(event.extensionData!.data); + enhanceTracingController.assignStateForFrame(frame); + flutterFramesController.addFrame(frame); + } else if (event.extensionKind == FlutterEvent.rebuiltWidgets && + FeatureFlags.widgetRebuildStats) { + if (_currentRebuildWidgetsIsolate != event.isolate) { + rebuildCountModel.clearFromRestart(); + } + _currentRebuildWidgetsIsolate = event.isolate; + // TODO(jacobr): need to make sure we don't get events from before + // the last hot restart. Their data would be bogus. + rebuildCountModel.processRebuildEvent( + event.extensionData!.data, + ); + if (!rebuildCountModel.locationMap.locationsResolved.value && + !_fetchMissingLocationsStarted) { + _fetchMissingRebuildLocations(); + } + } + }), ); } else { await maybeLoadOfflineData( @@ -245,15 +247,16 @@ class PerformanceController extends DisposableController @override OfflineScreenData prepareOfflineScreenData() => OfflineScreenData( - screenId: PerformanceScreen.id, - data: OfflinePerformanceData( + screenId: PerformanceScreen.id, + data: + OfflinePerformanceData( perfettoTraceBinary: timelineEventsController.fullPerfettoTrace, frames: flutterFramesController.flutterFrames.value, selectedFrame: flutterFramesController.selectedFrame.value, rebuildCountModel: rebuildCountModel, displayRefreshRate: flutterFramesController.displayRefreshRate.value, ).toJson(), - ); + ); } abstract class PerformanceFeatureController extends DisposableController { 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 80747e09943..8747db62a3b 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_model.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_model.dart @@ -26,8 +26,9 @@ class OfflinePerformanceData { final selectedFrameId = json.selectedFrameId; final frames = json.frames; - final selectedFrame = - frames.firstWhereOrNull((frame) => frame.id == selectedFrameId); + final selectedFrame = frames.firstWhereOrNull( + (frame) => frame.id == selectedFrameId, + ); return OfflinePerformanceData( perfettoTraceBinary: json.traceBinary, @@ -58,12 +59,12 @@ class OfflinePerformanceData { bool get isEmpty => perfettoTraceBinary == null; Map toJson() => { - traceBinaryKey: perfettoTraceBinary, - flutterFramesKey: frames.map((frame) => frame.json).toList(), - selectedFrameIdKey: selectedFrame?.id, - displayRefreshRateKey: displayRefreshRate, - rebuildCountModelKey: rebuildCountModel?.toJson(), - }; + traceBinaryKey: perfettoTraceBinary, + flutterFramesKey: frames.map((frame) => frame.json).toList(), + selectedFrameIdKey: selectedFrame?.id, + displayRefreshRateKey: displayRefreshRate, + rebuildCountModelKey: rebuildCountModel?.toJson(), + }; } extension type _PerformanceDataJson(Map json) { @@ -98,8 +99,8 @@ extension type _PerformanceDataJson(Map json) { class FlutterTimelineEvent extends TreeNode { FlutterTimelineEvent(PerfettoTrackEvent firstTrackEvent) - : trackEvents = [firstTrackEvent], - type = firstTrackEvent.timelineEventType { + : trackEvents = [firstTrackEvent], + type = firstTrackEvent.timelineEventType { time.start = Duration(microseconds: firstTrackEvent.timestampMicros); } @@ -137,9 +138,10 @@ class FlutterTimelineEvent extends TreeNode { } copy ..type = type - ..time = (TimeRange() - ..start = time.start - ..end = time.end); + ..time = + (TimeRange() + ..start = time.start + ..end = time.end); return copy; } @@ -180,8 +182,4 @@ class FlutterTimelineEvent extends TreeNode { } } -enum TimelineEventType { - ui, - raster, - other, -} +enum TimelineEventType { ui, raster, other } diff --git a/packages/devtools_app/lib/src/screens/performance/performance_screen.dart b/packages/devtools_app/lib/src/screens/performance/performance_screen.dart index 056f823732c..86db29f3af1 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_screen.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_screen.dart @@ -94,7 +94,8 @@ class PerformanceScreenBodyState extends State final showingOfflineData = offlineDataController.showingOfflineData.value; - final isOfflineFlutterApp = showingOfflineData && + final isOfflineFlutterApp = + showingOfflineData && controller.offlinePerformanceData != null && controller.offlinePerformanceData!.frames.isNotEmpty; return Column( @@ -107,7 +108,9 @@ class PerformanceScreenBodyState extends State if (isOfflineFlutterApp || (!showingOfflineData && serviceConnection - .serviceManager.connectedApp!.isFlutterAppNow!)) + .serviceManager + .connectedApp! + .isFlutterAppNow!)) FlutterFramesChart( controller.flutterFramesController, showingOfflineData: showingOfflineData, @@ -128,7 +131,7 @@ class WebPerformanceScreenBody extends StatelessWidget { Widget build(BuildContext context) { final isFlutterWebApp = serviceConnection.serviceManager.connectedApp?.isFlutterWebAppNow ?? - false; + false; return Markdown( data: isFlutterWebApp ? flutterWebInstructionsMd : dartWebInstructionsMd, onTapLink: (_, url, _) { @@ -155,8 +158,10 @@ class DisconnectedPerformanceScreenBody extends StatelessWidget { gaSelectionImport: gac.PerformanceEvents.openDataFile.name, gaSelectionAction: gac.PerformanceEvents.loadDataFromFile.name, onAction: (jsonFile) { - Provider.of(context, listen: false) - .importData(jsonFile, expectedScreenId: PerformanceScreen.id); + Provider.of( + context, + listen: false, + ).importData(jsonFile, expectedScreenId: PerformanceScreen.id); }, ); } diff --git a/packages/devtools_app/lib/src/screens/performance/tabbed_performance_view.dart b/packages/devtools_app/lib/src/screens/performance/tabbed_performance_view.dart index 6adb48ab683..c241626c189 100644 --- a/packages/devtools_app/lib/src/screens/performance/tabbed_performance_view.dart +++ b/packages/devtools_app/lib/src/screens/performance/tabbed_performance_view.dart @@ -68,7 +68,8 @@ class _TabbedPerformanceViewState extends State final hasOfflineData = offlineData != null; showFrameAnalysis = showFrameAnalysis && hasOfflineData && offlineData.frames.isNotEmpty; - showRebuildStats = showRebuildStats && + showRebuildStats = + showRebuildStats && hasOfflineData && offlineData.rebuildCountModel != null; } @@ -77,9 +78,10 @@ class _TabbedPerformanceViewState extends State showFrameAnalysis: showFrameAnalysis, showRebuildStats: showRebuildStats, ); - final tabs = tabsAndControllers - .map((t) => (tab: t.tab, tabView: t.tabView)) - .toList(); + final tabs = + tabsAndControllers + .map((t) => (tab: t.tab, tabView: t.tabView)) + .toList(); final featureControllers = tabsAndControllers.map((t) => t.featureController).toList(); @@ -110,11 +112,13 @@ class _TabbedPerformanceViewState extends State } List< - ({ - DevToolsTab tab, - Widget tabView, - PerformanceFeatureController? featureController, - })> _generateTabs({ + ({ + DevToolsTab tab, + Widget tabView, + PerformanceFeatureController? featureController, + }) + > + _generateTabs({ required bool showFrameAnalysis, required bool showRebuildStats, }) { @@ -126,18 +130,19 @@ class _TabbedPerformanceViewState extends State ( tab: _buildTab(tabName: 'Frame Analysis'), tabView: KeepAliveWrapper( - child: _selectedFlutterFrame != null - ? FlutterFrameAnalysisView( - frame: _selectedFlutterFrame!, - enhanceTracingController: - controller.enhanceTracingController, - rebuildCountModel: controller.rebuildCountModel, - displayRefreshRateNotifier: - controller.flutterFramesController.displayRefreshRate, - ) - : const CenteredMessage( - message: 'Select a frame above to view analysis data.', - ), + child: + _selectedFlutterFrame != null + ? FlutterFrameAnalysisView( + frame: _selectedFlutterFrame!, + enhanceTracingController: + controller.enhanceTracingController, + rebuildCountModel: controller.rebuildCountModel, + displayRefreshRateNotifier: + controller.flutterFramesController.displayRefreshRate, + ) + : const CenteredMessage( + message: 'Select a frame above to view analysis data.', + ), ), featureController: null, ), 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 7c4b3b5d04f..eedc9da016f 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 @@ -53,8 +53,10 @@ class CpuProfilePair { CpuProfilePair original, bool Function(CpuStackFrame) callback, ) { - final function = - CpuProfileData.filterFrom(original.functionProfile, callback); + final function = CpuProfileData.filterFrom( + original.functionProfile, + callback, + ); CpuProfileData? code; if (original.codeProfile != null) { code = CpuProfileData.filterFrom(original.codeProfile!, callback); @@ -70,8 +72,10 @@ class CpuProfilePair { CpuProfilePair original, TimeRange subTimeRange, ) { - final function = - CpuProfileData.subProfile(original.functionProfile, subTimeRange); + final function = CpuProfileData.subProfile( + original.functionProfile, + subTimeRange, + ); CpuProfileData? code; if (original.codeProfile != null) { code = CpuProfileData.subProfile(original.codeProfile!, subTimeRange); @@ -90,10 +94,7 @@ class CpuProfilePair { final codeProfile = original.codeProfile; CpuProfileData? code; if (codeProfile != null) { - code = CpuProfileData.withTagRoots( - codeProfile, - tagType, - ); + code = CpuProfileData.withTagRoots(codeProfile, tagType); } return CpuProfilePair(functionProfile: function, codeProfile: code); } @@ -173,13 +174,14 @@ class CpuProfileData with Serializable { sampleCount: json.sampleCount ?? 0, samplePeriod: json.samplePeriod ?? 0, stackDepth: json.stackDepth ?? 0, - time: (json.timeOriginMicros != null && json.timeExtentMicros != null) - ? (TimeRange() - ..start = Duration(microseconds: json.timeOriginMicros!) - ..end = Duration( - microseconds: json.timeOriginMicros! + json.timeExtentMicros!, - )) - : null, + time: + (json.timeOriginMicros != null && json.timeExtentMicros != null) + ? (TimeRange() + ..start = Duration(microseconds: json.timeOriginMicros!) + ..end = Duration( + microseconds: json.timeOriginMicros! + json.timeExtentMicros!, + )) + : null, ); // Initialize all stack frames. @@ -226,12 +228,14 @@ class CpuProfileData with Serializable { ) { // Each sample in [subSamples] will have the leaf stack // frame id for a cpu sample within [subTimeRange]. - final subSamples = superProfile.cpuSamples - .where( - (sample) => subTimeRange - .contains(Duration(microseconds: sample.timestampMicros!)), - ) - .toList(); + final subSamples = + superProfile.cpuSamples + .where( + (sample) => subTimeRange.contains( + Duration(microseconds: sample.timestampMicros!), + ), + ) + .toList(); final subStackFrames = {}; for (final sample in subSamples) { @@ -306,9 +310,7 @@ class CpuProfileData with Serializable { profileMetaData: metaData, isTag: true, ); - final idMapping = { - rootId: tagId, - }; + final idMapping = {rootId: tagId}; tagProfile.stackFrames.forEach((k, v) { idMapping.putIfAbsent(k, () => '$isolateId-${nextId++}'); @@ -333,9 +335,10 @@ class CpuProfileData with Serializable { profileMetaData: metaData, parentId: parentId, ); - final parentStackFrameJson = parentId != null - ? originalData.stackFrames[currentStackFrame.parentId] - : null; + final parentStackFrameJson = + parentId != null + ? originalData.stackFrames[currentStackFrame.parentId] + : null; updatedId = parentId; currentStackFrame = parentStackFrameJson; } @@ -368,9 +371,12 @@ class CpuProfileData with Serializable { return CpuProfileData.empty(); } - final samplesWithTag = originalData.cpuSamples - .where((sample) => (useUserTag ? sample.userTag : sample.vmTag) == tag) - .toList(); + final samplesWithTag = + originalData.cpuSamples + .where( + (sample) => (useUserTag ? sample.userTag : sample.vmTag) == tag, + ) + .toList(); assert(samplesWithTag.isNotEmpty); final originalTime = originalData.profileMetaData.time!.duration; @@ -383,13 +389,15 @@ class CpuProfileData with Serializable { // for this profile data, and the samples included in this data could be // sparse over the original profile's time range, so true start and end // times wouldn't be helpful. - time: TimeRange() - ..start = const Duration() - ..end = Duration( - microseconds: microsPerSample.isInfinite - ? 0 - : (newSampleCount * microsPerSample).round(), - ), + time: + TimeRange() + ..start = const Duration() + ..end = Duration( + microseconds: + microsPerSample.isInfinite + ? 0 + : (newSampleCount * microsPerSample).round(), + ), ); final stackFramesWithTag = {}; @@ -487,13 +495,15 @@ class CpuProfileData with Serializable { // for this profile data, and the samples included in this data could be // sparse over the original profile's time range, so true start and end // times wouldn't be helpful. - time: TimeRange() - ..start = const Duration() - ..end = Duration( - microseconds: microsPerSample.isInfinite || microsPerSample.isNaN - ? 0 - : (filteredCpuSamples.length * microsPerSample).round(), - ), + time: + TimeRange() + ..start = const Duration() + ..end = Duration( + microseconds: + microsPerSample.isInfinite || microsPerSample.isNaN + ? 0 + : (filteredCpuSamples.length * microsPerSample).round(), + ), ); void walkAndFilter(CpuStackFrame stackFrame) { @@ -734,17 +744,17 @@ class CpuProfileData with Serializable { @override Map toJson() => { - 'type': '_CpuProfileTimeline', - _samplePeriodKey: profileMetaData.samplePeriod, - _sampleCountKey: profileMetaData.sampleCount, - _stackDepthKey: profileMetaData.stackDepth, - if (profileMetaData.time?.start != null) - _timeOriginKey: profileMetaData.time!.start!.inMicroseconds, - if (profileMetaData.time?.duration != null) - _timeExtentKey: profileMetaData.time!.duration.inMicroseconds, - _stackFramesKey: stackFramesJson, - _traceEventsKey: cpuSamples.map((sample) => sample.toJson).toList(), - }; + 'type': '_CpuProfileTimeline', + _samplePeriodKey: profileMetaData.samplePeriod, + _sampleCountKey: profileMetaData.sampleCount, + _stackDepthKey: profileMetaData.stackDepth, + if (profileMetaData.time?.start != null) + _timeOriginKey: profileMetaData.time!.start!.inMicroseconds, + if (profileMetaData.time?.duration != null) + _timeExtentKey: profileMetaData.time!.duration.inMicroseconds, + _stackFramesKey: stackFramesJson, + _traceEventsKey: cpuSamples.map((sample) => sample.toJson).toList(), + }; bool get isEmpty => profileMetaData.sampleCount == 0; @@ -939,21 +949,25 @@ class CpuStackFrame extends TreeNode /// samples are being grouped by tag. final bool isTag; - bool get isNative => _isNative ??= id != CpuProfileData.rootId && - packageUri.isEmpty && - !name.startsWith(PackagePrefixes.flutterEngine) && - !isTag; + bool get isNative => + _isNative ??= + id != CpuProfileData.rootId && + packageUri.isEmpty && + !name.startsWith(PackagePrefixes.flutterEngine) && + !isTag; bool? _isNative; bool get isDartCore => - _isDartCore ??= packageUri.startsWith(PackagePrefixes.dart) && + _isDartCore ??= + packageUri.startsWith(PackagePrefixes.dart) && !packageUri.startsWith(PackagePrefixes.dartUi); bool? _isDartCore; - bool get isFlutterCore => _isFlutterCore ??= - packageUri.startsWith(PackagePrefixes.flutterPackage) || + bool get isFlutterCore => + _isFlutterCore ??= + packageUri.startsWith(PackagePrefixes.flutterPackage) || name.startsWith(PackagePrefixes.flutterEngine) || packageUri.startsWith(PackagePrefixes.dartUi); @@ -1052,15 +1066,15 @@ class CpuStackFrame extends TreeNode } Map get toJson => { - id: { - CpuProfileData.nameKey: verboseName, - CpuProfileData.categoryKey: category, - CpuProfileData.resolvedUrlKey: rawUrl, - CpuProfileData.resolvedPackageUriKey: packageUri, - CpuProfileData.sourceLineKey: sourceLine, - if (parentId != null) CpuProfileData.parentIdKey: parentId, - }, - }; + id: { + CpuProfileData.nameKey: verboseName, + CpuProfileData.categoryKey: category, + CpuProfileData.resolvedUrlKey: rawUrl, + CpuProfileData.resolvedPackageUriKey: packageUri, + CpuProfileData.sourceLineKey: sourceLine, + if (parentId != null) CpuProfileData.parentIdKey: parentId, + }, + }; @override String toString() { @@ -1105,10 +1119,7 @@ class CpuProfileStore { /// generated, cached in [_profilesByTime] and then returned. This method will /// return null if no profiles are cached for [time] or if a sub profile /// cannot be generated for [time]. - CpuProfilePair? lookupProfile({ - String? label, - TimeRange? time, - }) { + CpuProfilePair? lookupProfile({String? label, TimeRange? time}) { assert((label == null) != (time == null)); if (label != null) { @@ -1124,11 +1135,7 @@ class CpuProfileStore { return _profilesByTime[time]; } - void storeProfile( - CpuProfilePair profile, { - String? label, - TimeRange? time, - }) { + void storeProfile(CpuProfilePair profile, {String? label, TimeRange? time}) { assert((label == null) != (time == null)); if (label != null) { _profilesByLabel[label] = profile; @@ -1244,13 +1251,17 @@ class _CpuProfileTimelineTree { return null; } - String? get resolvedUrl => isCodeTree && _function is vm_service.FuncRef? - ? - // TODO(bkonyi): not sure if this is a resolved URL or not, but it's not - // critical since this is only displayed when VM developer mode is - // enabled. - (_function as vm_service.FuncRef?)?.location?.script?.uri - : samples.functions![index].resolvedUrl; + String? get resolvedUrl => + isCodeTree && _function is vm_service.FuncRef? + ? + // TODO(bkonyi): not sure if this is a resolved URL or not, but it's not + // critical since this is only displayed when VM developer mode is + // enabled. + (_function as vm_service.FuncRef?) + ?.location + ?.script + ?.uri + : samples.functions![index].resolvedUrl; int? get sourceLine { final function = _function; @@ -1269,8 +1280,7 @@ class _CpuProfileTimelineTree { static _CpuProfileTimelineTree? getTreeFromSample( vm_service.CpuSample sample, - ) => - _timelineTreeExpando[sample]; + ) => _timelineTreeExpando[sample]; _CpuProfileTimelineTree _getChild(int index) { final length = children.length; @@ -1285,8 +1295,11 @@ class _CpuProfileTimelineTree { break; } } - final child = - _CpuProfileTimelineTree._fromIndex(samples, index, isCodeTree); + final child = _CpuProfileTimelineTree._fromIndex( + samples, + index, + isCodeTree, + ); if (i < length) { children.insert(i, child); } else { diff --git a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_service.dart b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_service.dart index 994323d493f..bbfed58d2f5 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_service.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_service.dart @@ -18,14 +18,15 @@ extension CpuProfilerExtension on VmService { // Grab the value of this flag before doing asynchronous work. final vmDeveloperModeEnabled = preferences.vmDeveloperModeEnabled.value; - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!; - final cpuSamples = - await serviceConnection.serviceManager.service!.getCpuSamples( - isolateId, - startMicros, - extentMicros, - ); + final isolateId = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!; + final cpuSamples = await serviceConnection.serviceManager.service! + .getCpuSamples(isolateId, startMicros, extentMicros); // If VM developer mode is enabled, getCpuSamples will also include code // profile details automatically (e.g., code stacks and a list of code @@ -75,17 +76,25 @@ extension CpuProfilerExtension on VmService { Future clearSamples() { return serviceConnection.serviceManager.service!.clearCpuSamples( serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!, + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!, ); } Future setProfilePeriod(String value) { - return serviceConnection.serviceManager.service! - .setFlag(vm_flags.profilePeriod, value); + return serviceConnection.serviceManager.service!.setFlag( + vm_flags.profilePeriod, + value, + ); } Future enableCpuProfiler() async { - return await serviceConnection.serviceManager.service! - .setFlag(vm_flags.profiler, 'true'); + return await serviceConnection.serviceManager.service!.setFlag( + vm_flags.profiler, + 'true', + ); } } diff --git a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_transformer.dart b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_transformer.dart index 826b3290216..466f70fddc1 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_transformer.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_transformer.dart @@ -64,9 +64,11 @@ class CpuProfileTransformer { // Check to see if there are any empty tag roots as a result of filtering // and remove them. final nodeIndicesToRemove = []; - for (int i = cpuProfileData.cpuProfileRoot.children.length - 1; - i >= 0; - --i) { + for ( + int i = cpuProfileData.cpuProfileRoot.children.length - 1; + i >= 0; + --i + ) { final root = cpuProfileData.cpuProfileRoot.children[i]; if (root.isTag && root.children.isEmpty) { nodeIndicesToRemove.add(i); @@ -97,8 +99,10 @@ class CpuProfileTransformer { CpuProfileData cpuProfileData, { required String processId, }) { - final batchEnd = - math.min(_stackFramesProcessed + batchSize, _stackFramesCount); + final batchEnd = math.min( + _stackFramesProcessed + batchSize, + _stackFramesCount, + ); for (int i = _stackFramesProcessed; i < batchEnd; i++) { if (processId != _activeProcessId) { throw ProcessCancelledException(); diff --git a/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart b/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart index 9e0c901fc94..b80bc17b5ba 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart @@ -35,14 +35,14 @@ class CpuProfiler extends StatefulWidget { required this.data, required this.controller, List? searchableTabKeys, - }) : callTreeRoots = data.callTreeRoots, - bottomUpRoots = data.bottomUpRoots, - tabs = [ - _buildTab(ProfilerTab.bottomUp), - _buildTab(ProfilerTab.callTree), - _buildTab(ProfilerTab.methodTable), - _buildTab(ProfilerTab.cpuFlameChart), - ]; + }) : callTreeRoots = data.callTreeRoots, + bottomUpRoots = data.bottomUpRoots, + tabs = [ + _buildTab(ProfilerTab.bottomUp), + _buildTab(ProfilerTab.callTree), + _buildTab(ProfilerTab.methodTable), + _buildTab(ProfilerTab.cpuFlameChart), + ]; static DevToolsTab _buildTab(ProfilerTab profilerTab) { return DevToolsTab.create( @@ -113,10 +113,7 @@ class _CpuProfilerState extends State _tabController.removeListener(_onTabChanged); _tabController.dispose(); } - _tabController = TabController( - length: widget.tabs.length, - vsync: this, - ); + _tabController = TabController(length: widget.tabs.length, vsync: this); _tabControllerInitialized = true; if (widget.controller.selectedProfilerTabIndex >= _tabController.length) { @@ -286,24 +283,21 @@ class _CpuProfilerState extends State unawaited( showDialog( context: context, - builder: (context) => FilterDialog( - controller: widget.controller, - filteredItem: 'stack frame', - ), + builder: + (context) => FilterDialog( + controller: widget.controller, + filteredItem: 'stack frame', + ), ), ); } List _buildProfilerViews() { final bottomUp = KeepAliveWrapper( - child: CpuBottomUpTable( - bottomUpRoots: widget.bottomUpRoots, - ), + child: CpuBottomUpTable(bottomUpRoots: widget.bottomUpRoots), ); final callTree = KeepAliveWrapper( - child: CpuCallTreeTable( - dataRoots: widget.callTreeRoots, - ), + child: CpuCallTreeTable(dataRoots: widget.callTreeRoots), ); final methodTable = KeepAliveWrapper( child: CpuMethodTable( @@ -325,21 +319,17 @@ class _CpuProfilerState extends State }, ), ); - return [ - bottomUp, - callTree, - methodTable, - cpuFlameChart, - ]; + return [bottomUp, callTree, methodTable, cpuFlameChart]; } void _performOnDataRoots( void Function(CpuStackFrame root) callback, Tab currentTab, ) { - final roots = currentTab.key == ProfilerTab.callTree.key - ? widget.callTreeRoots - : widget.bottomUpRoots; + final roots = + currentTab.key == ProfilerTab.callTree.key + ? widget.callTreeRoots + : widget.bottomUpRoots; setState(() { roots.forEach(callback); }); @@ -360,15 +350,14 @@ class CpuProfileStats extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); final samplePeriodValid = metadata.samplePeriod > 0; - final samplingPeriodDisplay = samplePeriodValid - ? const Duration(seconds: 1).inMicroseconds ~/ metadata.samplePeriod - : '--'; + final samplingPeriodDisplay = + samplePeriodValid + ? const Duration(seconds: 1).inMicroseconds ~/ metadata.samplePeriod + : '--'; return RoundedOutlinedBorder.onlyBottom( child: Container( height: _statsRowHeight, - padding: const EdgeInsets.symmetric( - horizontal: defaultSpacing, - ), + padding: const EdgeInsets.symmetric(horizontal: defaultSpacing), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ 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 7374bd783ea..f214a53987e 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 @@ -32,10 +32,7 @@ enum CpuProfilerViewType { } } -enum CpuProfilerTagType { - user, - vm, -} +enum CpuProfilerTagType { user, vm } enum CpuProfilerBusyStatus { fetching, @@ -94,7 +91,11 @@ class CpuProfilerController extends DisposableController CpuProfileStore get cpuProfileStore => _cpuProfileStoreByIsolateId.putIfAbsent( serviceConnection - .serviceManager.isolateManager.selectedIsolate.value?.id ?? + .serviceManager + .isolateManager + .selectedIsolate + .value + ?.id ?? '', () => CpuProfileStore(), ); @@ -102,8 +103,9 @@ class CpuProfilerController extends DisposableController /// Store of cached CPU profiles for each isolate. final _cpuProfileStoreByIsolateId = {}; - late final methodTableController = - MethodTableController(dataNotifier: dataNotifier); + late final methodTableController = MethodTableController( + dataNotifier: dataNotifier, + ); /// Notifies that new cpu profile data is available. ValueListenable get dataNotifier => _dataNotifier; @@ -112,8 +114,9 @@ class CpuProfilerController extends DisposableController /// The current busy state of the cpu profiler. ValueListenable get profilerBusyStatus => _profilerBusyStatus; - final _profilerBusyStatus = - ValueNotifier(CpuProfilerBusyStatus.none); + final _profilerBusyStatus = ValueNotifier( + CpuProfilerBusyStatus.none, + ); /// Notifies that a cpu stack frame was selected. ValueListenable get selectedCpuStackFrameNotifier => @@ -126,16 +129,15 @@ class CpuProfilerController extends DisposableController Iterable get userTags => cpuProfileStore - .lookupProfile( - label: userTagNone, - ) + .lookupProfile(label: userTagNone) ?.functionProfile .userTags ?? const []; ValueListenable get viewType => _viewType; - final _viewType = - ValueNotifier(CpuProfilerViewType.function); + final _viewType = ValueNotifier( + CpuProfilerViewType.function, + ); static const _nativeFilterId = 'native'; static const _coreDartFilterId = 'core-dart'; @@ -145,40 +147,39 @@ class CpuProfilerController extends DisposableController /// The toggle filters available for the CPU profiler. @override SettingFilters createSettingFilters() => [ - ToggleFilter( - id: _nativeFilterId, - name: 'Hide Native code', - includeCallback: (stackFrame) => !stackFrame.isNative, - defaultValue: true, - ), - ToggleFilter( - id: _coreDartFilterId, - name: 'Hide core Dart libraries', - includeCallback: (stackFrame) => !stackFrame.isDartCore, - defaultValue: false, - ), - if (serviceConnection.serviceManager.connectedApp?.isFlutterAppNow ?? - true) - ToggleFilter( - id: _coreFlutterFilterId, - name: 'Hide core Flutter libraries', - includeCallback: (stackFrame) => !stackFrame.isFlutterCore, - defaultValue: false, - ), - ]; + ToggleFilter( + id: _nativeFilterId, + name: 'Hide Native code', + includeCallback: (stackFrame) => !stackFrame.isNative, + defaultValue: true, + ), + ToggleFilter( + id: _coreDartFilterId, + name: 'Hide core Dart libraries', + includeCallback: (stackFrame) => !stackFrame.isDartCore, + defaultValue: false, + ), + if (serviceConnection.serviceManager.connectedApp?.isFlutterAppNow ?? true) + ToggleFilter( + id: _coreFlutterFilterId, + name: 'Hide core Flutter libraries', + includeCallback: (stackFrame) => !stackFrame.isFlutterCore, + defaultValue: false, + ), + ]; @override Map> createQueryFilterArgs() => { - _uriQueryFilterId: QueryFilterArgument( - keys: ['uri', 'u'], - exampleUsages: [ - 'uri:my_dart_package/some_lib.dart', - '-u:some_lib_to_hide', - ], - dataValueProvider: (stackFrame) => stackFrame.packageUri, - substringMatch: true, - ), - }; + _uriQueryFilterId: QueryFilterArgument( + keys: ['uri', 'u'], + exampleUsages: [ + 'uri:my_dart_package/some_lib.dart', + '-u:some_lib_to_hide', + ], + dataValueProvider: (stackFrame) => stackFrame.packageUri, + substringMatch: true, + ), + }; @override ValueNotifier? get filterTagNotifier => @@ -226,9 +227,10 @@ class CpuProfilerController extends DisposableController /// Clients interested in the current value of [profilerFlagNotifier] should /// use this getter. Otherwise, clients subscribing to change notifications, /// should listen to [profilerFlagNotifier]. - bool get profilerEnabled => offlineDataController.showingOfflineData.value - ? true - : profilerFlagNotifier?.value.valueAsString == 'true'; + bool get profilerEnabled => + offlineDataController.showingOfflineData.value + ? true + : profilerFlagNotifier?.value.valueAsString == 'true'; Future enableCpuProfiler() { return serviceConnection.serviceManager.service!.enableCpuProfiler(); @@ -254,11 +256,8 @@ class CpuProfilerController extends DisposableController // TODO(kenz): add a cancel button to the processing UI in case pulling a // large payload from the vm service takes a long time. _profilerBusyStatus.value = CpuProfilerBusyStatus.fetching; - cpuProfiles = - await serviceConnection.serviceManager.service!.getCpuProfile( - startMicros: startMicros, - extentMicros: extentMicros, - ); + cpuProfiles = await serviceConnection.serviceManager.service! + .getCpuProfile(startMicros: startMicros, extentMicros: extentMicros); await processAndSetData( cpuProfiles, processId: processId, @@ -275,10 +274,11 @@ class CpuProfilerController extends DisposableController gac.cpuProfiler, gac.CpuProfilerEvents.cpuProfileProcessingTime.name, asyncOperation: pullAndProcessHelper, - screenMetricsProvider: () => ProfilerScreenMetrics( - cpuSampleCount: cpuProfiles.profileMetaData.sampleCount, - cpuStackDepth: cpuProfiles.profileMetaData.stackDepth, - ), + screenMetricsProvider: + () => ProfilerScreenMetrics( + cpuSampleCount: cpuProfiles.profileMetaData.sampleCount, + cpuStackDepth: cpuProfiles.profileMetaData.stackDepth, + ), ); } on ProcessCancelledException catch (_) { // Do nothing for instances of [ProcessCancelledException]. @@ -293,10 +293,7 @@ class CpuProfilerController extends DisposableController }) async { assert(_profilerBusyStatus.value == CpuProfilerBusyStatus.processing); if (storeAsUserTagNone) { - cpuProfileStore.storeProfile( - cpuProfiles, - label: userTagNone, - ); + cpuProfileStore.storeProfile(cpuProfiles, label: userTagNone); cpuProfileStore.storeProfile( cpuProfiles, time: cpuProfiles.profileMetaData.time, @@ -307,10 +304,7 @@ class CpuProfilerController extends DisposableController cpuProfiles = _filterData(cpuProfiles); } - await cpuProfiles.process( - transformer: transformer, - processId: processId, - ); + await cpuProfiles.process(transformer: transformer, processId: processId); if (storeAsUserTagNone && shouldApplyFilters) { cpuProfileStore.storeProfile( cpuProfiles, @@ -439,28 +433,26 @@ class CpuProfilerController extends DisposableController _dataNotifier.value = null; if (appStartUpProfileWithFilters != null) { - _dataNotifier.value = - appStartUpProfileWithFilters.getActive(viewType.value); + _dataNotifier.value = appStartUpProfileWithFilters.getActive( + viewType.value, + ); refreshSearchMatches(); return; } if (appStartUpProfile == null) { - final cpuProfile = - await serviceConnection.serviceManager.service!.getCpuProfile( - startMicros: 0, - // Using [maxJsInt] as [extentMicros] for the getCpuProfile requests will - // give us all cpu samples we have available. - extentMicros: maxJsInt, - ); + final cpuProfile = await serviceConnection.serviceManager.service! + .getCpuProfile( + startMicros: 0, + // Using [maxJsInt] as [extentMicros] for the getCpuProfile requests will + // give us all cpu samples we have available. + extentMicros: maxJsInt, + ); appStartUpProfile = CpuProfilePair.fromUserTag( cpuProfile, appStartUpUserTag, ); - cpuProfileStore.storeProfile( - appStartUpProfile, - label: userTagNone, - ); + cpuProfileStore.storeProfile(appStartUpProfile, label: userTagNone); cpuProfileStore.storeProfile( appStartUpProfile, label: appStartUpUserTag, @@ -514,10 +506,7 @@ class CpuProfilerController extends DisposableController assert(data.processed); _dataNotifier.value = data.getActive(viewType.value); if (storeAsUserTagNone) { - cpuProfileStore.storeProfile( - data, - label: userTagNone, - ); + cpuProfileStore.storeProfile(data, label: userTagNone); } } @@ -528,9 +517,9 @@ class CpuProfilerController extends DisposableController _profilerBusyStatus.value = CpuProfilerBusyStatus.processing; try { - _dataNotifier.value = await processDataForTag(tag).then( - (e) => e.getActive(viewType.value), - ); + _dataNotifier.value = await processDataForTag( + tag, + ).then((e) => e.getActive(viewType.value)); } catch (e, stackTrace) { // In the event of an error, reset the data to the original CPU profile. final filteredOriginalData = await lookupProfileAndProcess( @@ -557,15 +546,14 @@ class CpuProfilerController extends DisposableController label: tag, createIfAbsent: () { final fullData = cpuProfileStore.lookupProfile(label: userTagNone)!; - final tagType = tag == groupByUserTag - ? CpuProfilerTagType.user - : CpuProfilerTagType.vm; - final data = tag == groupByUserTag || tag == groupByVmTag - ? CpuProfilePair.withTagRoots( - fullData, - tagType, - ) - : CpuProfilePair.fromUserTag(fullData, tag); + final tagType = + tag == groupByUserTag + ? CpuProfilerTagType.user + : CpuProfilerTagType.vm; + final data = + tag == groupByUserTag || tag == groupByVmTag + ? CpuProfilePair.withTagRoots(fullData, tagType) + : CpuProfilePair.fromUserTag(fullData, tag); cpuProfileStore.storeProfile(data, label: tag); return data; }, @@ -577,9 +565,7 @@ class CpuProfilerController extends DisposableController void updateViewForType(CpuProfilerViewType type) { _viewType.value = type; _dataNotifier.value = cpuProfileStore - .lookupProfile( - label: _wrapWithFilterTag(_userTagFilter.value), - ) + .lookupProfile(label: _wrapWithFilterTag(_userTagFilter.value)) ?.getActive(type); } @@ -642,9 +628,7 @@ class CpuProfilerController extends DisposableController } else { // Lookup the cpu profile from the cached [cpuProfileStore] if present. final dataLabel = _wrapWithFilterTag(_userTagFilter.value); - filteredData = cpuProfileStore.lookupProfile( - label: dataLabel, - ); + filteredData = cpuProfileStore.lookupProfile(label: dataLabel); if (filteredData == null) { // TODO(https://github.com/flutter/devtools/issues/5203): optimize @@ -668,10 +652,7 @@ class CpuProfilerController extends DisposableController final filterFrom = dataForCurrentTag; filteredData = _filterData(filterFrom, filter: filter); - cpuProfileStore.storeProfile( - filteredData, - label: dataLabel, - ); + cpuProfileStore.storeProfile(filteredData, label: dataLabel); } } unawaited( @@ -701,7 +682,8 @@ class CpuProfilerController extends DisposableController final queryFilter = filter.queryFilter; if (!queryFilter.isEmpty) { final filteredOutByQueryFilterArgument = queryFilter - .filterArguments.values + .filterArguments + .values .any((argument) => !argument.matchesValue(stackFrame)); if (filteredOutByQueryFilterArgument) return false; diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/bottom_up.dart b/packages/devtools_app/lib/src/screens/profiler/panes/bottom_up.dart index 52989b36240..4ae941b8338 100644 --- a/packages/devtools_app/lib/src/screens/profiler/panes/bottom_up.dart +++ b/packages/devtools_app/lib/src/screens/profiler/panes/bottom_up.dart @@ -13,21 +13,20 @@ import 'cpu_profile_columns.dart'; /// A table of the bottom up tree for a CPU profile. class CpuBottomUpTable extends StatelessWidget { - const CpuBottomUpTable({ - required this.bottomUpRoots, - super.key, - }); + const CpuBottomUpTable({required this.bottomUpRoots, super.key}); static final methodColumn = MethodAndSourceColumn(); static final selfTimeColumn = SelfTimeColumn( titleTooltip: selfTimeTooltip, - dataTooltipProvider: (stackFrame, context) => - _bottomUpTimeTooltipBuilder(_TimeType.self, stackFrame, context), + dataTooltipProvider: + (stackFrame, context) => + _bottomUpTimeTooltipBuilder(_TimeType.self, stackFrame, context), ); static final totalTimeColumn = TotalTimeColumn( titleTooltip: totalTimeTooltip, - dataTooltipProvider: (stackFrame, context) => - _bottomUpTimeTooltipBuilder(_TimeType.total, stackFrame, context), + dataTooltipProvider: + (stackFrame, context) => + _bottomUpTimeTooltipBuilder(_TimeType.total, stackFrame, context), ); static final columns = List>.unmodifiable([ totalTimeColumn, @@ -64,12 +63,10 @@ the top-level method (the callee) when called through the child method (the call return TextSpan( children: [ const TextSpan(text: 'Time that '), - TextSpan( - text: '[${stackFrame.name}]', - style: fixedStyle, - ), + TextSpan(text: '[${stackFrame.name}]', style: fixedStyle), const TextSpan( - text: ' spent executing its own code,\nas well as the code for' + text: + ' spent executing its own code,\nas well as the code for' ' any methods that it called.', ), ], @@ -78,10 +75,7 @@ the top-level method (the callee) when called through the child method (the call return TextSpan( children: [ const TextSpan(text: 'Time that '), - TextSpan( - text: '[${stackFrame.name}]', - style: fixedStyle, - ), + TextSpan(text: '[${stackFrame.name}]', style: fixedStyle), const TextSpan(text: ' spent executing its own code.'), ], ); @@ -90,15 +84,9 @@ the top-level method (the callee) when called through the child method (the call return TextSpan( children: [ TextSpan(text: '$type time for root '), - TextSpan( - text: '[${stackFrame.root.name}]', - style: fixedStyle, - ), + TextSpan(text: '[${stackFrame.root.name}]', style: fixedStyle), const TextSpan(text: '\nwhen called through '), - TextSpan( - text: '[${stackFrame.name}]', - style: fixedStyle, - ), + TextSpan(text: '[${stackFrame.name}]', style: fixedStyle), ], ); } diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/call_tree.dart b/packages/devtools_app/lib/src/screens/profiler/panes/call_tree.dart index 28c3f377ba1..91949d5675e 100644 --- a/packages/devtools_app/lib/src/screens/profiler/panes/call_tree.dart +++ b/packages/devtools_app/lib/src/screens/profiler/panes/call_tree.dart @@ -12,17 +12,15 @@ import 'cpu_profile_columns.dart'; /// A table of the CPU's top-down call tree. class CpuCallTreeTable extends StatelessWidget { - const CpuCallTreeTable({ - required this.dataRoots, - super.key, - }); + const CpuCallTreeTable({required this.dataRoots, super.key}); static final methodColumn = MethodAndSourceColumn(); static final selfTimeColumn = SelfTimeColumn(titleTooltip: selfTimeTooltip); - static final totalTimeColumn = - TotalTimeColumn(titleTooltip: totalTimeTooltip); + static final totalTimeColumn = TotalTimeColumn( + titleTooltip: totalTimeTooltip, + ); static final columns = List>.unmodifiable([ totalTimeColumn, diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/controls/cpu_profiler_controls.dart b/packages/devtools_app/lib/src/screens/profiler/panes/controls/cpu_profiler_controls.dart index 3c2e01a5d44..5d0c63ae5a1 100644 --- a/packages/devtools_app/lib/src/screens/profiler/panes/controls/cpu_profiler_controls.dart +++ b/packages/devtools_app/lib/src/screens/profiler/panes/controls/cpu_profiler_controls.dart @@ -25,9 +25,10 @@ class UserTagDropdown extends StatelessWidget { valueListenable: controller.userTagFilter, builder: (context, userTag, _) { final userTags = controller.userTags; - final tooltip = userTags.isNotEmpty - ? 'Filter the CPU profile by the given UserTag' - : 'No UserTags found for this CPU profile'; + final tooltip = + userTags.isNotEmpty + ? 'Filter the CPU profile by the given UserTag' + : 'No UserTags found for this CPU profile'; return SizedBox( height: defaultButtonHeight, child: DevToolsTooltip( @@ -65,11 +66,12 @@ class UserTagDropdown extends StatelessWidget { value: CpuProfilerController.groupByVmTag, ), ], - onChanged: userTags.isEmpty || - (userTags.length == 1 && - userTags.first == UserTag.defaultTag.label) - ? null - : (String? tag) => _onUserTagChanged(tag!), + onChanged: + userTags.isEmpty || + (userTags.length == 1 && + userTags.first == UserTag.defaultTag.label) + ? null + : (String? tag) => _onUserTagChanged(tag!), ); }, ), @@ -83,10 +85,7 @@ class UserTagDropdown extends StatelessWidget { required String display, required String value, }) { - return DropdownMenuItem( - value: value, - child: Text(display), - ); + return DropdownMenuItem(value: value, child: Text(display)); } void _onUserTagChanged(String newTag) async { @@ -111,12 +110,13 @@ class ModeDropdown extends StatelessWidget { return ValueListenableBuilder( valueListenable: controller.viewType, builder: (context, viewType, _) { - final tooltip = viewType == CpuProfilerViewType.function - ? 'Display the profile in terms of the Dart call stack ' - '(i.e., inlined frames are expanded)' - : 'Display the profile in terms of native stack frames ' - '(i.e., inlined frames are not expanded, display code objects ' - 'rather than individual functions)'; + final tooltip = + viewType == CpuProfilerViewType.function + ? 'Display the profile in terms of the Dart call stack ' + '(i.e., inlined frames are expanded)' + : 'Display the profile in terms of native stack frames ' + '(i.e., inlined frames are not expanded, display code objects ' + 'rather than individual functions)'; return SizedBox( height: defaultButtonHeight, child: DevToolsTooltip( 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 6a2d3deeb14..dfe5eab81d4 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 @@ -42,10 +42,7 @@ class ProfilerScreenControls extends StatelessWidget { child: ExitOfflineButton(gaScreen: gac.cpuProfiler), ) else ...[ - _PrimaryControls( - controller: controller, - recording: recording, - ), + _PrimaryControls(controller: controller, recording: recording), const SizedBox(width: defaultSpacing), _SecondaryControls( controller: controller, @@ -58,10 +55,7 @@ class ProfilerScreenControls extends StatelessWidget { } class _PrimaryControls extends StatelessWidget { - const _PrimaryControls({ - required this.controller, - required this.recording, - }); + const _PrimaryControls({required this.controller, required this.recording}); static const _primaryControlsMinIncludeTextWidth = 1170.0; @@ -113,20 +107,24 @@ class _SecondaryControls extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.end, children: [ if (serviceConnection - .serviceManager.connectedApp!.isFlutterNativeAppNow) + .serviceManager + .connectedApp! + .isFlutterNativeAppNow) GaDevToolsButton( icon: Icons.timer, label: 'Profile app start up', - tooltip: 'Load all Dart CPU samples that occurred before \n' + tooltip: + 'Load all Dart CPU samples that occurred before \n' 'the first Flutter frame was drawn (if available)', tooltipPadding: const EdgeInsets.all(denseSpacing), gaScreen: gac.cpuProfiler, gaSelection: gac.CpuProfilerEvents.profileAppStartUp.name, minScreenWidthForTextBeforeScaling: _profilingControlsMinScreenWidthForText, - onPressed: !profilerBusy - ? controller.cpuProfilerController.loadAppStartUpProfile - : null, + onPressed: + !profilerBusy + ? controller.cpuProfilerController.loadAppStartUpProfile + : null, ), const SizedBox(width: denseSpacing), RefreshButton( @@ -136,9 +134,10 @@ class _SecondaryControls extends StatelessWidget { gaSelection: gac.CpuProfilerEvents.loadAllCpuSamples.name, minScreenWidthForTextBeforeScaling: _profilingControlsMinScreenWidthForText, - onPressed: !profilerBusy - ? controller.cpuProfilerController.loadAllSamples - : null, + onPressed: + !profilerBusy + ? controller.cpuProfilerController.loadAllSamples + : null, ), const SizedBox(width: denseSpacing), CpuSamplingRateDropdown( @@ -149,11 +148,12 @@ class _SecondaryControls extends StatelessWidget { const SizedBox(width: denseSpacing), OpenSaveButtonGroup( screenId: ScreenMetaData.cpuProfiler.id, - onSave: !profilerBusy && - controller.cpuProfileData != null && - controller.cpuProfileData?.isEmpty == false - ? _exportPerformance - : null, + onSave: + !profilerBusy && + controller.cpuProfileData != null && + controller.cpuProfileData?.isEmpty == false + ? _exportPerformance + : null, ), ], ); diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/cpu_flame_chart.dart b/packages/devtools_app/lib/src/screens/profiler/panes/cpu_flame_chart.dart index cff8fbf421b..1f459ff3a5c 100644 --- a/packages/devtools_app/lib/src/screens/profiler/panes/cpu_flame_chart.dart +++ b/packages/devtools_app/lib/src/screens/profiler/panes/cpu_flame_chart.dart @@ -21,17 +21,17 @@ class CpuProfileFlameChart extends FlameChart { required ValueListenable activeSearchMatchNotifier, required void Function(CpuStackFrame? stackFrame) onDataSelected, }) : super( - data, - time: data.profileMetaData.time!, - containerWidth: width, - containerHeight: height, - startInset: sideInsetSmall, - endInset: sideInsetSmall, - selectionNotifier: selectionNotifier, - searchMatchesNotifier: searchMatchesNotifier, - activeSearchMatchNotifier: activeSearchMatchNotifier, - onDataSelected: onDataSelected, - ); + data, + time: data.profileMetaData.time!, + containerWidth: width, + containerHeight: height, + startInset: sideInsetSmall, + endInset: sideInsetSmall, + selectionNotifier: selectionNotifier, + searchMatchesNotifier: searchMatchesNotifier, + activeSearchMatchNotifier: activeSearchMatchNotifier, + onDataSelected: onDataSelected, + ); @override State createState() => _CpuProfileFlameChartState(); @@ -53,7 +53,8 @@ class _CpuProfileFlameChartState ); void createChartNodes(CpuStackFrame stackFrame, int row) { - final width = widget.startingContentWidth * stackFrame.totalTimeRatio - + final width = + widget.startingContentWidth * stackFrame.totalTimeRatio - stackFramePadding; final left = startingLeftForStackFrame(stackFrame); final colorPair = _colorPairForStackFrame(stackFrame); @@ -144,7 +145,8 @@ class _CpuProfileFlameChartState // [stackFrame] is not the first child of its parent. [left] should // equal the right value of its previous sibling. final previous = parent.children[stackFrameIndex - 1]; - left = stackFrameLefts[previous.id]! + + left = + stackFrameLefts[previous.id]! + (widget.startingContentWidth * previous.totalTimeRatio); } } diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/cpu_profile_columns.dart b/packages/devtools_app/lib/src/screens/profiler/panes/cpu_profile_columns.dart index 90440589ead..cde9c313bdf 100644 --- a/packages/devtools_app/lib/src/screens/profiler/panes/cpu_profile_columns.dart +++ b/packages/devtools_app/lib/src/screens/profiler/panes/cpu_profile_columns.dart @@ -14,12 +14,12 @@ class SelfTimeColumn extends TimeAndPercentageColumn { super.titleTooltip, RichTooltipBuilder? dataTooltipProvider, }) : super( - title: 'Self Time', - timeProvider: (stackFrame) => stackFrame.selfTime, - percentAsDoubleProvider: (stackFrame) => stackFrame.selfTimeRatio, - richTooltipProvider: dataTooltipProvider, - secondaryCompare: (stackFrame) => stackFrame.name, - ); + title: 'Self Time', + timeProvider: (stackFrame) => stackFrame.selfTime, + percentAsDoubleProvider: (stackFrame) => stackFrame.selfTimeRatio, + richTooltipProvider: dataTooltipProvider, + secondaryCompare: (stackFrame) => stackFrame.name, + ); } class TotalTimeColumn extends TimeAndPercentageColumn { @@ -27,12 +27,12 @@ class TotalTimeColumn extends TimeAndPercentageColumn { super.titleTooltip, RichTooltipBuilder? dataTooltipProvider, }) : super( - title: 'Total Time', - timeProvider: (stackFrame) => stackFrame.totalTime, - percentAsDoubleProvider: (stackFrame) => stackFrame.totalTimeRatio, - richTooltipProvider: dataTooltipProvider, - secondaryCompare: (stackFrame) => stackFrame.name, - ); + title: 'Total Time', + timeProvider: (stackFrame) => stackFrame.totalTime, + percentAsDoubleProvider: (stackFrame) => stackFrame.totalTimeRatio, + richTooltipProvider: dataTooltipProvider, + secondaryCompare: (stackFrame) => stackFrame.name, + ); } class MethodAndSourceColumn extends TreeColumnData diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table.dart b/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table.dart index 6b938b14d89..b50eedf36a5 100644 --- a/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table.dart +++ b/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table.dart @@ -114,9 +114,10 @@ class _MethodGraphState extends State<_MethodGraph> with AutoDisposeMixin { _callers = []; _callees = []; } else { - _callers = _selectedGraphNode!.predecessors - .cast() - .toList(); + _callers = + _selectedGraphNode!.predecessors + .cast() + .toList(); _callees = _selectedGraphNode!.successors.cast().toList(); } @@ -139,10 +140,7 @@ class _MethodGraphState extends State<_MethodGraph> with AutoDisposeMixin { children: [ Flexible( child: OutlineDecoration.onlyBottom( - child: _CallersTable( - widget.methodTableController, - _callers, - ), + child: _CallersTable(widget.methodTableController, _callers), ), ), DevToolsTooltip( @@ -162,10 +160,7 @@ class _MethodGraphState extends State<_MethodGraph> with AutoDisposeMixin { ), Flexible( child: OutlineDecoration.onlyTop( - child: _CalleesTable( - widget.methodTableController, - _callees, - ), + child: _CalleesTable(widget.methodTableController, _callees), ), ), ], @@ -177,8 +172,9 @@ class _MethodGraphState extends State<_MethodGraph> with AutoDisposeMixin { /// A table of predecessors (callers) for a single method in a method table. class _CallersTable extends StatelessWidget { _CallersTable(this._methodTableController, this._callers) { - _callerTimeColumn = - _CallerTimeColumn(methodTableController: _methodTableController); + _callerTimeColumn = _CallerTimeColumn( + methodTableController: _methodTableController, + ); columns = List>.unmodifiable([ _callerTimeColumn, methodColumn, @@ -213,8 +209,9 @@ class _CallersTable extends StatelessWidget { /// A table of successors (callees) for a single method in a method table. class _CalleesTable extends StatelessWidget { _CalleesTable(this._methodTableController, this._callees) { - _calleeTimeColumn = - _CalleeTimeColumn(methodTableController: _methodTableController); + _calleeTimeColumn = _CalleeTimeColumn( + methodTableController: _methodTableController, + ); _columns = List>.unmodifiable([ _calleeTimeColumn, _methodColumn, @@ -248,11 +245,7 @@ class _CalleesTable extends StatelessWidget { class _MethodColumn extends ColumnData implements ColumnRenderer { - _MethodColumn() - : super.wide( - 'Method', - minWidthPx: _methodColumnMinWidth, - ); + _MethodColumn() : super.wide('Method', minWidthPx: _methodColumnMinWidth); @override String getValue(MethodTableGraphNode dataObject) => dataObject.name; @@ -284,50 +277,48 @@ const _callGraphColumnWidth = 70.0; class _SelfTimeColumn extends TimeAndPercentageColumn { _SelfTimeColumn() - : super( - title: 'Self %', - percentageOnly: true, - timeProvider: (node) => node.selfTime, - percentAsDoubleProvider: (node) => node.selfTimeRatio, - secondaryCompare: (node) => node.name, - columnWidth: _totalAndSelfColumnWidth, - ); + : super( + title: 'Self %', + percentageOnly: true, + timeProvider: (node) => node.selfTime, + percentAsDoubleProvider: (node) => node.selfTimeRatio, + secondaryCompare: (node) => node.name, + columnWidth: _totalAndSelfColumnWidth, + ); } class _TotalTimeColumn extends TimeAndPercentageColumn { _TotalTimeColumn() - : super( - title: 'Total %', - percentageOnly: true, - timeProvider: (node) => node.totalTime, - percentAsDoubleProvider: (node) => node.totalTimeRatio, - secondaryCompare: (node) => node.name, - columnWidth: _totalAndSelfColumnWidth, - ); + : super( + title: 'Total %', + percentageOnly: true, + timeProvider: (node) => node.totalTime, + percentAsDoubleProvider: (node) => node.totalTimeRatio, + secondaryCompare: (node) => node.name, + columnWidth: _totalAndSelfColumnWidth, + ); } class _CallerTimeColumn extends TimeAndPercentageColumn { - _CallerTimeColumn({ - required MethodTableController methodTableController, - }) : super( - title: 'Caller %', - percentageOnly: true, - percentAsDoubleProvider: (node) => - methodTableController.callerPercentageFor(node), - secondaryCompare: (node) => node.name, - columnWidth: _callGraphColumnWidth, - ); + _CallerTimeColumn({required MethodTableController methodTableController}) + : super( + title: 'Caller %', + percentageOnly: true, + percentAsDoubleProvider: + (node) => methodTableController.callerPercentageFor(node), + secondaryCompare: (node) => node.name, + columnWidth: _callGraphColumnWidth, + ); } class _CalleeTimeColumn extends TimeAndPercentageColumn { - _CalleeTimeColumn({ - required MethodTableController methodTableController, - }) : super( - title: 'Callee %', - percentageOnly: true, - percentAsDoubleProvider: (node) => - methodTableController.calleePercentageFor(node), - secondaryCompare: (node) => node.name, - columnWidth: _callGraphColumnWidth, - ); + _CalleeTimeColumn({required MethodTableController methodTableController}) + : super( + title: 'Callee %', + percentageOnly: true, + percentAsDoubleProvider: + (node) => methodTableController.calleePercentageFor(node), + secondaryCompare: (node) => node.name, + columnWidth: _callGraphColumnWidth, + ); } diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table_controller.dart b/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table_controller.dart index 5d0df6375d5..90f77de224e 100644 --- a/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table_controller.dart +++ b/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table_controller.dart @@ -65,13 +65,14 @@ class MethodTableController extends DisposableController depthFirstTraversal( root, action: (CpuStackFrame frame) { - final parentNode = frame.parent != null && - frame.parentId != CpuProfileData.rootId && - !frame.parent!.isTag - // Since we are performing a DFS, the parent should always be in - // the map. - ? methodMap[frame.parent!.methodTableId]! - : null; + final parentNode = + frame.parent != null && + frame.parentId != CpuProfileData.rootId && + !frame.parent!.isTag + // Since we are performing a DFS, the parent should always be in + // the map. + ? methodMap[frame.parent!.methodTableId]! + : null; var graphNode = MethodTableGraphNode.fromStackFrame(frame); final existingNode = methodMap[frame.methodTableId]; 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 484c4eaecba..39752c76596 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 @@ -20,9 +20,9 @@ class MethodTableGraphNode extends GraphNode with SearchableDataMixin { required int selfCount, required this.profileMetaData, required this.stackFrameIds, - }) : _totalCount = totalCount, - _selfCount = selfCount, - _sourceUri = uriWithSourceLine(packageUri, sourceLine); + }) : _totalCount = totalCount, + _selfCount = selfCount, + _sourceUri = uriWithSourceLine(packageUri, sourceLine); factory MethodTableGraphNode.fromStackFrame(CpuStackFrame frame) { return MethodTableGraphNode( @@ -67,19 +67,18 @@ class MethodTableGraphNode extends GraphNode with SearchableDataMixin { safeDivide(selfCount, profileMetaData.sampleCount); Duration get selfTime => Duration( - microseconds: - (selfTimeRatio * profileMetaData.time!.duration.inMicroseconds) - .round(), - ); + microseconds: + (selfTimeRatio * profileMetaData.time!.duration.inMicroseconds).round(), + ); double get totalTimeRatio => safeDivide(totalCount, profileMetaData.sampleCount); Duration get totalTime => Duration( - microseconds: - (totalTimeRatio * profileMetaData.time!.duration.inMicroseconds) - .round(), - ); + microseconds: + (totalTimeRatio * profileMetaData.time!.duration.inMicroseconds) + .round(), + ); void merge(MethodTableGraphNode other, {required bool mergeTotalTime}) { if (!shallowEquals(other)) return; @@ -113,9 +112,7 @@ class MethodTableGraphNode extends GraphNode with SearchableDataMixin { .cast() // Sort in descending order. .sorted((a, b) => percentCallback(b).compareTo(percentCallback(a))) - .map( - (node) => '${node.display} - ${percent(percentCallback(node))}', - ) + .map((node) => '${node.display} - ${percent(percentCallback(node))}') .join(newLineAndIndent); } 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 33834302ca1..af5013d1671 100644 --- a/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart +++ b/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart @@ -129,11 +129,12 @@ class _ProfilerScreenBodyState extends State child: const CenteredCircularProgressIndicator(), ); } - final status = recording || profilerBusy - ? (recording - ? const RecordingStatus() - : ProfilerBusyStatus(status: profilerBusyStatus)) - : null; + final status = + recording || profilerBusy + ? (recording + ? const RecordingStatus() + : ProfilerBusyStatus(status: profilerBusyStatus)) + : null; return Column( children: [ ProfilerScreenControls( @@ -144,7 +145,8 @@ class _ProfilerScreenBodyState extends State ), const SizedBox(height: intermediateSpacing), Expanded( - child: status ?? + child: + status ?? ValueListenableBuilder( valueListenable: controller.cpuProfilerController.dataNotifier, @@ -191,8 +193,10 @@ class DisconnectedCpuProfilerScreenBody extends StatelessWidget { gaSelectionImport: gac.CpuProfilerEvents.openDataFile.name, gaSelectionAction: gac.CpuProfilerEvents.loadDataFromFile.name, onAction: (jsonFile) { - Provider.of(context, listen: false) - .importData(jsonFile, expectedScreenId: ProfilerScreen.id); + Provider.of( + context, + listen: false, + ).importData(jsonFile, expectedScreenId: ProfilerScreen.id); }, ); } diff --git a/packages/devtools_app/lib/src/screens/profiler/profiler_screen_controller.dart b/packages/devtools_app/lib/src/screens/profiler/profiler_screen_controller.dart index 625287b4d3f..4139e822165 100644 --- a/packages/devtools_app/lib/src/screens/profiler/profiler_screen_controller.dart +++ b/packages/devtools_app/lib/src/screens/profiler/profiler_screen_controller.dart @@ -38,8 +38,9 @@ class ProfilerScreenController extends DisposableController Future _initHelper() async { if (!offlineDataController.showingOfflineData.value) { await allowedError( - serviceConnection.serviceManager.service! - .setProfilePeriod(mediumProfilePeriod), + serviceConnection.serviceManager.service!.setProfilePeriod( + mediumProfilePeriod, + ), logError: false, ); @@ -48,8 +49,12 @@ class ProfilerScreenController extends DisposableController addAutoDisposeListener( serviceConnection.serviceManager.isolateManager.selectedIsolate, () { - final selectedIsolate = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value; + final selectedIsolate = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value; if (selectedIsolate != null) { switchToIsolate(selectedIsolate); } @@ -68,8 +73,9 @@ class ProfilerScreenController extends DisposableController // need to default to the basic view of the profile. final userTagFilter = cpuProfilerController.userTagFilter.value; if (userTagFilter == CpuProfilerController.groupByVmTag) { - await cpuProfilerController - .loadDataWithTag(CpuProfilerController.userTagNone); + await cpuProfilerController.loadDataWithTag( + CpuProfilerController.userTagNone, + ); } } // Always reset to the function view when the VM developer mode state @@ -93,10 +99,7 @@ class ProfilerScreenController extends DisposableController processId: 'offline data processing', ); cpuProfilerController.loadProcessedData( - CpuProfilePair( - functionProfile: data, - codeProfile: null, - ), + CpuProfilePair(functionProfile: data, codeProfile: null), storeAsUserTagNone: true, ); } @@ -151,9 +154,9 @@ class ProfilerScreenController extends DisposableController @override OfflineScreenData prepareOfflineScreenData() => OfflineScreenData( - screenId: ProfilerScreen.id, - data: cpuProfileData!.toJson(), - ); + screenId: ProfilerScreen.id, + data: cpuProfileData!.toJson(), + ); Future clear() async { await cpuProfilerController.clear(); diff --git a/packages/devtools_app/lib/src/screens/profiler/profiler_status.dart b/packages/devtools_app/lib/src/screens/profiler/profiler_status.dart index beb8ee8a6d0..e5ef464aa98 100644 --- a/packages/devtools_app/lib/src/screens/profiler/profiler_status.dart +++ b/packages/devtools_app/lib/src/screens/profiler/profiler_status.dart @@ -109,8 +109,8 @@ class ProfileRecordingInstructions extends StatelessWidget { class ProfilerBusyStatus extends _Status { ProfilerBusyStatus({required CpuProfilerBusyStatus status}) - : assert(status != CpuProfilerBusyStatus.none), - super(statusVerb: status.display); + : assert(status != CpuProfilerBusyStatus.none), + super(statusVerb: status.display); } class RecordingStatus extends _Status { 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 30162a6ea83..b26f4e38da0 100644 --- a/packages/devtools_app/lib/src/screens/provider/provider_screen.dart +++ b/packages/devtools_app/lib/src/screens/provider/provider_screen.dart @@ -18,7 +18,8 @@ class ProviderScreen extends Screen { return CenteredMessage( richMessage: [ const TextSpan( - text: 'The Provider screen is now shipped as a DevTools extension.\n' + text: + 'The Provider screen is now shipped as a DevTools extension.\n' 'If you want to use this tool, please upgrade your ', ), TextSpan( diff --git a/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view.dart b/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view.dart index 430e3fbc005..a6c8f84837b 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view.dart @@ -24,10 +24,7 @@ import 'isolate_statistics_view_controller.dart'; /// isolate. class IsolateStatisticsView extends VMDeveloperView { const IsolateStatisticsView() - : super( - title: 'Isolates', - icon: Icons.bar_chart, - ); + : super(title: 'Isolates', icon: Icons.bar_chart); @override bool get showIsolateSelector => true; @@ -58,14 +55,8 @@ class IsolateStatisticsViewBody extends StatelessWidget { Flexible( child: Column( children: [ - Flexible( - child: _buildTopRow(), - ), - Flexible( - child: IsolatePortsWidget( - controller: controller, - ), - ), + Flexible(child: _buildTopRow()), + Flexible(child: IsolatePortsWidget(controller: controller)), ], ), ), @@ -82,28 +73,16 @@ class IsolateStatisticsViewBody extends StatelessWidget { child: Column( children: [ Expanded( - child: GeneralIsolateStatisticsWidget( - controller: controller, - ), + child: GeneralIsolateStatisticsWidget(controller: controller), ), Expanded( - child: IsolateMemoryStatisticsWidget( - controller: controller, - ), + child: IsolateMemoryStatisticsWidget(controller: controller), ), ], ), ), - Flexible( - child: TagStatisticsWidget( - controller: controller, - ), - ), - Flexible( - child: ServiceExtensionsWidget( - controller: controller, - ), - ), + Flexible(child: TagStatisticsWidget(controller: controller)), + Flexible(child: ServiceExtensionsWidget(controller: controller)), ], ); } @@ -125,9 +104,7 @@ class GeneralIsolateStatisticsWidget extends StatelessWidget { } final startedAtFormatter = DateFormat.yMMMMd().add_jms(); return startedAtFormatter.format( - DateTime.fromMillisecondsSinceEpoch( - isolate.startTime!, - ).toLocal(), + DateTime.fromMillisecondsSinceEpoch(isolate.startTime!).toLocal(), ); } @@ -138,9 +115,7 @@ class GeneralIsolateStatisticsWidget extends StatelessWidget { final uptimeFormatter = DateFormat.Hms(); return uptimeFormatter.format( DateTime.now() - .subtract( - Duration(milliseconds: isolate.startTime!), - ) + .subtract(Duration(milliseconds: isolate.startTime!)) .toUtc(), ); } @@ -201,10 +176,7 @@ class IsolateMemoryStatisticsWidget extends StatelessWidget { ), selectableTextBuilderMapEntry( 'New Space', - _buildMemoryString( - isolate?.newSpaceUsage, - isolate?.newSpaceUsage, - ), + _buildMemoryString(isolate?.newSpaceUsage, isolate?.newSpaceUsage), ), selectableTextBuilderMapEntry( 'Old Space', @@ -238,18 +210,17 @@ class TagStatisticsWidget extends StatelessWidget { title: 'Execution Time', roundedTopBorder: false, table: Flexible( - child: controller.cpuProfilerController.profilerEnabled - ? FlatTable( - keyFactory: (VMTag tag) => ValueKey(tag.name), - data: controller.tags, - dataKey: 'tag-statistics', - columns: _columns, - defaultSortColumn: _percentage, - defaultSortDirection: SortDirection.descending, - ) - : CpuProfilerDisabled( - controller.cpuProfilerController, - ), + child: + controller.cpuProfilerController.profilerEnabled + ? FlatTable( + keyFactory: (VMTag tag) => ValueKey(tag.name), + data: controller.tags, + dataKey: 'tag-statistics', + columns: _columns, + defaultSortColumn: _percentage, + defaultSortDirection: SortDirection.descending, + ) + : CpuProfilerDisabled(controller.cpuProfilerController), ), ), ); @@ -265,7 +236,7 @@ class _TagColumn extends ColumnData { class _PercentageColumn extends ColumnData { _PercentageColumn() - : super.wide('Percentage', alignment: ColumnAlignment.right); + : super.wide('Percentage', alignment: ColumnAlignment.right); @override double getValue(VMTag dataObject) => dataObject.percentage; @@ -313,10 +284,7 @@ class _StackTraceViewerFrameColumn extends ColumnData { // TODO(bkonyi): merge with debugger stack trace viewer. /// A simple table to display a stack trace, sorted by frame number. class StackTraceViewerWidget extends StatelessWidget { - const StackTraceViewerWidget({ - super.key, - required this.stackTrace, - }); + const StackTraceViewerWidget({super.key, required this.stackTrace}); static final frame = _StackTraceViewerFrameColumn(); @@ -327,29 +295,29 @@ class StackTraceViewerWidget extends StatelessWidget { return ValueListenableBuilder( valueListenable: stackTrace, builder: (context, stackTrace, _) { - final lines = stackTrace?.allocationLocation?.valueAsString - ?.split('\n') - .where((e) => e.isNotEmpty) - .toList(); + final lines = + stackTrace?.allocationLocation?.valueAsString + ?.split('\n') + .where((e) => e.isNotEmpty) + .toList(); return VMInfoList( title: 'Allocation Location', roundedTopBorder: false, - table: lines == null - ? const Expanded( - child: Center( - child: Text('No port selected'), - ), - ) - : Flexible( - child: FlatTable( - keyFactory: (String s) => ValueKey(s), - data: lines, - dataKey: 'stack-trace-viewer', - columns: [frame], - defaultSortColumn: frame, - defaultSortDirection: SortDirection.ascending, + table: + lines == null + ? const Expanded( + child: Center(child: Text('No port selected')), + ) + : Flexible( + child: FlatTable( + keyFactory: (String s) => ValueKey(s), + data: lines, + dataKey: 'stack-trace-viewer', + columns: [frame], + defaultSortColumn: frame, + defaultSortDirection: SortDirection.ascending, + ), ), - ), ); }, ); @@ -383,10 +351,7 @@ class _IsolatePortsWidgetState extends State { return OutlineDecoration( child: SplitPane( axis: Axis.horizontal, - initialFractions: const [ - 0.3, - 0.7, - ], + initialFractions: const [0.3, 0.7], children: [ OutlineDecoration.onlyRight( child: Column( @@ -394,14 +359,13 @@ class _IsolatePortsWidgetState extends State { AreaPaneHeader( includeTopBorder: false, roundedTopBorder: false, - title: Text( - 'Open Ports (${ports.length})', - ), + title: Text('Open Ports (${ports.length})'), ), Flexible( child: FlatTable( - keyFactory: (InstanceRef? port) => - ValueKey(port!.debugName!), + keyFactory: + (InstanceRef? port) => + ValueKey(port!.debugName!), data: ports, dataKey: 'isolate-ports', columns: _columns, @@ -414,9 +378,7 @@ class _IsolatePortsWidgetState extends State { ), ), OutlineDecoration.onlyLeft( - child: StackTraceViewerWidget( - stackTrace: selectedPort, - ), + child: StackTraceViewerWidget(stackTrace: selectedPort), ), ], ), diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/class_hierarchy_explorer.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/class_hierarchy_explorer.dart index 2e2b4bdf476..f388007db34 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/class_hierarchy_explorer.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/class_hierarchy_explorer.dart @@ -32,10 +32,11 @@ class ClassHierarchyExplorer extends StatelessWidget { return TreeView( dataRootsListenable: controller.classHierarchyController.selectedIsolateClassHierarchy, - dataDisplayProvider: (node, onPressed) => VmServiceObjectLink( - object: node.cls, - onTap: controller.findAndSelectNodeForObject, - ), + dataDisplayProvider: + (node, onPressed) => VmServiceObjectLink( + object: node.cls, + onTap: controller.findAndSelectNodeForObject, + ), emptyTreeViewBuilder: () => const CenteredCircularProgressIndicator(), ); } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/class_hierarchy_explorer_controller.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/class_hierarchy_explorer_controller.dart index 627d41f7dd7..782f4ef8809 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/class_hierarchy_explorer_controller.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/class_hierarchy_explorer_controller.dart @@ -37,10 +37,7 @@ class ClassHierarchyExplorerController { @visibleForTesting void buildHierarchy(List classes) { final nodes = { - for (final cls in classes) - cls.id: ClassHierarchyNode( - cls: cls, - ), + for (final cls in classes) cls.id: ClassHierarchyNode(cls: cls), }; late final ClassHierarchyNode objectNode; 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 0e58697ed03..cedffd08024 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 @@ -35,9 +35,7 @@ class InboundReferencesTreeNode extends TreeNode { } return switch (objectRef) { - ClassRef(:final name) || - FuncRef(:final name) || - FieldRef(:final name) => + ClassRef(:final name) || FuncRef(:final name) || FieldRef(:final name) => name, LibraryRef(:final name, :final uri) => name.isNullOrEmpty ? uri : name, ScriptRef(:final uri) => fileNameFromUri(uri), @@ -65,18 +63,13 @@ class InboundReferencesTreeNode extends TreeNode { String _inboundRefDescription(InboundReference inboundRef, int? offset) { final parentListIndex = inboundRef.parentListIndex; if (parentListIndex != null) { - return 'Referenced by ${_parentListElementDescription( - parentListIndex, - inboundRef.source, - )}'; + return 'Referenced by ${_parentListElementDescription(parentListIndex, inboundRef.source)}'; } final description = StringBuffer('Referenced by '); if (offset != null) { - description.write( - 'offset $offset of ', - ); + description.write('offset $offset of '); } if (inboundRef.parentField is int) { @@ -86,14 +79,10 @@ class InboundReferencesTreeNode extends TreeNode { assert((inboundRef.source as InstanceRef).kind == InstanceKind.kRecord); description.write('${inboundRef.parentField} of '); } else if (inboundRef.parentField is FieldRef) { - description.write( - '${_objectName(inboundRef.parentField)} of ', - ); + description.write('${_objectName(inboundRef.parentField)} of '); } - description.write( - _objectDescription(inboundRef.source) ?? '', - ); + description.write(_objectDescription(inboundRef.source) ?? ''); return description.toString(); } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_inspector_view.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_inspector_view.dart index 07f9c773e8b..08630681e1b 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_inspector_view.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_inspector_view.dart @@ -23,10 +23,7 @@ import 'object_viewport.dart'; /// information about objects in the Dart VM. class ObjectInspectorView extends VMDeveloperView { ObjectInspectorView() - : super( - title: 'Objects', - icon: Icons.data_object_outlined, - ); + : super(title: 'Objects', icon: Icons.data_object_outlined); @override bool get showIsolateSelector => true; @@ -47,8 +44,9 @@ class _ObjectInspectorViewState extends State<_ObjectInspectorView> @override void didChangeDependencies() { super.didChangeDependencies(); - final vmDeveloperToolsController = - Provider.of(context); + final vmDeveloperToolsController = Provider.of( + context, + ); controller = vmDeveloperToolsController.objectInspectorViewController; unawaited(controller.init()); } @@ -60,20 +58,14 @@ class _ObjectInspectorViewState extends State<_ObjectInspectorView> initialFractions: const [0.2, 0.8], children: [ const ObjectInspectorSelector(), - SelectionArea( - child: ObjectViewport( - controller: controller, - ), - ), + SelectionArea(child: ObjectViewport(controller: controller)), ], ); } } class ObjectInspectorSelector extends StatefulWidget { - const ObjectInspectorSelector({ - super.key, - }); + const ObjectInspectorSelector({super.key}); static const kProgramExplorer = 'Program Explorer'; static const kObjectStore = 'Object Store'; @@ -91,8 +83,9 @@ class _ObjectInspectorSelectorState extends State { @override void didChangeDependencies() { super.didChangeDependencies(); - final vmDeveloperToolsController = - Provider.of(context); + final vmDeveloperToolsController = Provider.of( + context, + ); controller = vmDeveloperToolsController.objectInspectorViewController; unawaited(controller.init()); } @@ -125,9 +118,10 @@ class _ObjectInspectorSelectorState extends State { gac.classHierarchy, ), ], - onChanged: (newValue) => setState(() { - value = newValue!; - }), + onChanged: + (newValue) => setState(() { + value = newValue!; + }), ), Expanded( child: RoundedOutlinedBorder( @@ -145,10 +139,7 @@ class _ObjectInspectorSelectorState extends State { String gaId, ) { return ( - item: DropdownMenuItem( - value: text, - child: Text(text), - ), + item: DropdownMenuItem(value: text, child: Text(text)), gaId: gaId, ); } @@ -167,9 +158,7 @@ class _ObjectInspectorSelectorState extends State { onLinkTapped: controller.findAndSelectNodeForObject, ); case ObjectInspectorSelector.kClassHierarchy: - return ClassHierarchyExplorer( - controller: controller, - ); + return ClassHierarchyExplorer(controller: controller); default: throw StateError('Unexpected value: $value'); } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_inspector_view_controller.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_inspector_view_controller.dart index cd5fa64729b..76f7bafe690 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_inspector_view_controller.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_inspector_view_controller.dart @@ -25,20 +25,18 @@ class ObjectInspectorViewController extends DisposableController ObjectInspectorViewController({ ClassHierarchyExplorerController? classHierarchyController, }) : classHierarchyController = - classHierarchyController ?? ClassHierarchyExplorerController() { + classHierarchyController ?? ClassHierarchyExplorerController() { addAutoDisposeListener( scriptManager.sortedScripts, _initializeForCurrentIsolate, ); - addAutoDisposeListener( - objectHistory.current, - _onCurrentObjectChanged, - ); + addAutoDisposeListener(objectHistory.current, _onCurrentObjectChanged); } - final programExplorerController = - ProgramExplorerController(showCodeNodes: true); + final programExplorerController = ProgramExplorerController( + showCodeNodes: true, + ); final ClassHierarchyExplorerController classHierarchyController; final codeViewController = CodeViewController(); @@ -65,10 +63,11 @@ class ObjectInspectorViewController extends DisposableController if (currentObjectValue != null) { try { - final scriptRef = currentObjectValue.scriptRef ?? - (await programExplorerController - .searchFileExplorer(currentObjectValue.obj)) - .script; + final scriptRef = + currentObjectValue.scriptRef ?? + (await programExplorerController.searchFileExplorer( + currentObjectValue.obj, + )).script; if (scriptRef != null) { await programExplorerController.selectScriptNode(scriptRef); @@ -133,58 +132,29 @@ class ObjectInspectorViewController extends DisposableController }) async { VmObject object; if (objRef is ClassRef) { - object = ClassObject( - ref: objRef, - scriptRef: scriptRef, - ); + object = ClassObject(ref: objRef, scriptRef: scriptRef); } else if (objRef is FuncRef) { - object = FuncObject( - ref: objRef, - scriptRef: scriptRef, - ); + object = FuncObject(ref: objRef, scriptRef: scriptRef); } else if (objRef is FieldRef) { - object = FieldObject( - ref: objRef, - scriptRef: scriptRef, - ); + object = FieldObject(ref: objRef, scriptRef: scriptRef); } else if (objRef is LibraryRef) { - object = LibraryObject( - ref: objRef, - scriptRef: scriptRef, - ); + object = LibraryObject(ref: objRef, scriptRef: scriptRef); } else if (objRef is ScriptRef) { - object = ScriptObject( - ref: objRef, - scriptRef: scriptRef, - ); + object = ScriptObject(ref: objRef, scriptRef: scriptRef); } else if (objRef is InstanceRef) { - object = InstanceObject( - ref: objRef, - ); + object = InstanceObject(ref: objRef); } else if (objRef is CodeRef) { - object = CodeObject( - ref: objRef, - ); + object = CodeObject(ref: objRef); } else if (objRef.isObjectPool) { - object = ObjectPoolObject( - ref: objRef, - ); + object = ObjectPoolObject(ref: objRef); } else if (objRef.isICData) { - object = ICDataObject( - ref: objRef, - ); + object = ICDataObject(ref: objRef); } else if (objRef.isSubtypeTestCache) { - object = SubtypeTestCacheObject( - ref: objRef, - ); + object = SubtypeTestCacheObject(ref: objRef); } else if (objRef.isWeakArray) { - object = WeakArrayObject( - ref: objRef, - ); + object = WeakArrayObject(ref: objRef); } else { - object = UnknownObject( - ref: objRef, - ); + object = UnknownObject(ref: objRef); } await object.initialize(); @@ -203,7 +173,11 @@ class ObjectInspectorViewController extends DisposableController final service = serviceConnection.serviceManager.service!; final isolate = await service.getIsolate( serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!, + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!, ); final mainScriptRef = scriptRefs.firstWhereOrNull((ref) { diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_store_controller.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_store_controller.dart index 88f2f0dc6c3..a51537055d2 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_store_controller.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_store_controller.dart @@ -22,7 +22,8 @@ class ObjectStoreController extends DisposableController return; } _selectedIsolateObjectStore.value = null; - _selectedIsolateObjectStore.value = - await service.getObjectStore(isolate.id!); + _selectedIsolateObjectStore.value = await service.getObjectStore( + isolate.id!, + ); } } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_viewport.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_viewport.dart index 8c8462ba88d..a47d9c809c7 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_viewport.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_viewport.dart @@ -25,10 +25,7 @@ import 'vm_unknown_object_display.dart'; /// Displays the VM information for the currently selected object in the /// program explorer. class ObjectViewport extends StatelessWidget { - const ObjectViewport({ - super.key, - required this.controller, - }); + const ObjectViewport({super.key, required this.controller}); final ObjectInspectorViewController controller; @@ -36,9 +33,7 @@ class ObjectViewport extends StatelessWidget { Widget build(BuildContext context) { return HistoryViewport( history: controller.objectHistory, - controls: [ - ToolbarRefresh(onPressed: controller.refreshObject), - ], + controls: [ToolbarRefresh(onPressed: controller.refreshObject)], generateTitle: viewportTitle, contentBuilder: (context, _) { return ValueListenableBuilder( @@ -50,9 +45,10 @@ class ObjectViewport extends StatelessWidget { child = const CenteredCircularProgressIndicator(); } else { final currentObject = controller.objectHistory.current.value; - child = currentObject == null - ? const SizedBox.shrink() - : buildObjectDisplay(currentObject); + child = + currentObject == null + ? const SizedBox.shrink() + : buildObjectDisplay(currentObject); } return Expanded(child: child); @@ -84,70 +80,37 @@ class ObjectViewport extends StatelessWidget { @visibleForTesting Widget buildObjectDisplay(VmObject obj) { if (obj is ClassObject) { - return VmClassDisplay( - controller: controller, - clazz: obj, - ); + return VmClassDisplay(controller: controller, clazz: obj); } if (obj is FuncObject) { - return VmFuncDisplay( - controller: controller, - function: obj, - ); + return VmFuncDisplay(controller: controller, function: obj); } if (obj is FieldObject) { - return VmFieldDisplay( - controller: controller, - field: obj, - ); + return VmFieldDisplay(controller: controller, field: obj); } if (obj is LibraryObject) { - return VmLibraryDisplay( - controller: controller, - library: obj, - ); + return VmLibraryDisplay(controller: controller, library: obj); } if (obj is ScriptObject) { - return VmScriptDisplay( - controller: controller, - script: obj, - ); + return VmScriptDisplay(controller: controller, script: obj); } if (obj is InstanceObject) { - return VmInstanceDisplay( - controller: controller, - instance: obj, - ); + return VmInstanceDisplay(controller: controller, instance: obj); } if (obj is CodeObject) { - return VmCodeDisplay( - controller: controller, - code: obj, - ); + return VmCodeDisplay(controller: controller, code: obj); } if (obj is ObjectPoolObject) { - return VmObjectPoolDisplay( - controller: controller, - objectPool: obj, - ); + return VmObjectPoolDisplay(controller: controller, objectPool: obj); } if (obj is ICDataObject) { - return VmICDataDisplay( - controller: controller, - icData: obj, - ); + return VmICDataDisplay(controller: controller, icData: obj); } if (obj is VmListObject) { - return VmSimpleListDisplay( - controller: controller, - vmObject: obj, - ); + return VmSimpleListDisplay(controller: controller, vmObject: obj); } if (obj is UnknownObject) { - return VmUnknownObjectDisplay( - controller: controller, - object: obj, - ); + return VmUnknownObjectDisplay(controller: controller, object: obj); } return const SizedBox.shrink(); } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_class_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_class_display.dart index 541cd7184b9..9dae3364887 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_class_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_class_display.dart @@ -38,11 +38,7 @@ class VmClassDisplay extends StatelessWidget { ), ), if (displayClassInstances) - Flexible( - child: ClassInstancesWidget( - instances: clazz.instances, - ), - ), + Flexible(child: ClassInstancesWidget(instances: clazz.instances)), ], ); if (clazz.scriptRef != null) { @@ -60,15 +56,10 @@ class VmClassDisplay extends StatelessWidget { // ClassInstancesWidget implementation is completed. /// Generates a list of key-value pairs (map entries) containing the general /// information of the class object [clazz]. - List> _classDataRows( - ClassObject clazz, - ) { + List> _classDataRows(ClassObject clazz) { final superClass = clazz.obj.superClass; return [ - ...vmObjectGeneralDataRows( - controller, - clazz, - ), + ...vmObjectGeneralDataRows(controller, clazz), if (superClass != null) serviceObjectLinkBuilderMapEntry( controller: controller, @@ -88,10 +79,7 @@ class VmClassDisplay extends StatelessWidget { // all class instances. When done, remove the last row of the ClassInfoWidget. /// Displays information on the instances of the Class object. class ClassInstancesWidget extends StatelessWidget { - const ClassInstancesWidget({ - super.key, - required this.instances, - }); + const ClassInstancesWidget({super.key, required this.instances}); final InstanceSet? instances; diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_code_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_code_display.dart index 22d6288323d..2de8d52743a 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_code_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_code_display.dart @@ -26,11 +26,7 @@ abstract class _CodeColumnData extends ColumnData { } class _AddressColumn extends _CodeColumnData { - _AddressColumn() - : super( - 'Address', - fixedWidthPx: 160, - ); + _AddressColumn() : super('Address', fixedWidthPx: 160); @override int getValue(Instruction dataObject) { @@ -45,11 +41,7 @@ class _AddressColumn extends _CodeColumnData { } class _AddressRangeColumn extends _CodeColumnData { - _AddressRangeColumn() - : super( - 'Address Range', - fixedWidthPx: 300, - ); + _AddressRangeColumn() : super('Address Range', fixedWidthPx: 300); @override String getValue(InliningEntry dataObject) { @@ -79,9 +71,7 @@ class _FunctionsColumn extends _CodeColumnData object: function, onTap: controller.findAndSelectNodeForObject, ), - const SizedBox( - width: denseSpacing, - ), + const SizedBox(width: denseSpacing), ], ], ); @@ -162,11 +152,7 @@ class _ProfileRangeTicksColumn extends _CodeColumnData { class _InstructionColumn extends _CodeColumnData implements ColumnRenderer { - _InstructionColumn() - : super( - 'Disassembly', - fixedWidthPx: 240, - ); + _InstructionColumn() : super('Disassembly', fixedWidthPx: 240); @override Object? getValue(Instruction dataObject) { @@ -184,10 +170,7 @@ class _InstructionColumn extends _CodeColumnData final theme = Theme.of(context); return Text.rich( style: theme.fixedFontStyle, - _highlightAssemblyCode( - context, - data.instruction, - ), + _highlightAssemblyCode(context, data.instruction), ); } @@ -202,18 +185,14 @@ class _InstructionColumn extends _CodeColumnData ) { return TextSpan( text: _getLastMatch(scanner), - style: TextStyle( - color: colorScheme.controlFlowSyntaxColor, - ), + style: TextStyle(color: colorScheme.controlFlowSyntaxColor), ); } TextSpan _buildRegisterSpan(ColorScheme colorScheme, StringScanner scanner) { return TextSpan( text: _getLastMatch(scanner), - style: TextStyle( - color: colorScheme.variableSyntaxColor, - ), + style: TextStyle(color: colorScheme.variableSyntaxColor), ); } @@ -225,9 +204,7 @@ class _InstructionColumn extends _CodeColumnData final match = _getLastMatch(scanner); return TextSpan( text: isHex ? '0x${match.substring(2).toUpperCase()}' : match, - style: TextStyle( - color: colorScheme.numericConstantSyntaxColor, - ), + style: TextStyle(color: colorScheme.numericConstantSyntaxColor), ); } @@ -254,11 +231,7 @@ class _InstructionColumn extends _CodeColumnData } else if (scanner.scan(registerRegExp)) { spans.add(_buildRegisterSpan(colorScheme, scanner)); } else { - spans.add( - TextSpan( - text: String.fromCharCode(scanner.readChar()), - ), - ); + spans.add(TextSpan(text: String.fromCharCode(scanner.readChar()))); } } return TextSpan(children: spans); @@ -350,10 +323,7 @@ class VmCodeDisplay extends StatelessWidget { CodeObject code, ) { return [ - selectableTextBuilderMapEntry( - 'Kind', - code.obj.kind, - ), + selectableTextBuilderMapEntry('Kind', code.obj.kind), serviceObjectLinkBuilderMapEntry( controller: controller, key: 'Function', @@ -435,16 +405,8 @@ class CodeTable extends StatelessWidget { _InstructionColumn(), _DartObjectColumn(controller: controller), if (ticks != null) ...[ - _ProfileTicksColumn( - 'Total %', - ticks: code.ticksTable, - inclusive: true, - ), - _ProfileTicksColumn( - 'Self %', - ticks: code.ticksTable, - inclusive: false, - ), + _ProfileTicksColumn('Total %', ticks: code.ticksTable, inclusive: true), + _ProfileTicksColumn('Self %', ticks: code.ticksTable, inclusive: false), ], ]; @@ -519,15 +481,12 @@ class CpuProfilerTicksTable { /// Tracks inclusive and exclusive CPU profiler ticks for a single /// [Instruction]. class CodeTicks { - const CodeTicks({ - required this.inclusiveTicks, - required this.exclusiveTicks, - }); + const CodeTicks({required this.inclusiveTicks, required this.exclusiveTicks}); CodeTicks operator +(CodeTicks other) => CodeTicks( - inclusiveTicks: inclusiveTicks + other.inclusiveTicks, - exclusiveTicks: exclusiveTicks + other.exclusiveTicks, - ); + inclusiveTicks: inclusiveTicks + other.inclusiveTicks, + exclusiveTicks: exclusiveTicks + other.exclusiveTicks, + ); final int exclusiveTicks; final int inclusiveTicks; diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_field_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_field_display.dart index dbb5c6fae6e..02d1d623804 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_field_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_field_display.dart @@ -38,15 +38,10 @@ class VmFieldDisplay extends StatelessWidget { /// Generates a list of key-value pairs (map entries) containing the general /// information of the field object [field]. - List> _fieldDataRows( - FieldObject field, - ) { + List> _fieldDataRows(FieldObject field) { final staticValue = field.obj.staticValue; return [ - ...vmObjectGeneralDataRows( - controller, - field, - ), + ...vmObjectGeneralDataRows(controller, field), selectableTextBuilderMapEntry( 'Observed types', _fieldObservedTypes(field), diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_function_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_function_display.dart index 55c30af5cc5..223942627fc 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_function_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_function_display.dart @@ -61,10 +61,7 @@ class VmFuncDisplay extends StatelessWidget { } return [ - selectableTextBuilderMapEntry( - 'Kind', - _kindDescription(function.kind), - ), + selectableTextBuilderMapEntry('Kind', _kindDescription(function.kind)), selectableTextBuilderMapEntry( 'Deoptimizations', function.deoptimizations?.toString(), @@ -85,10 +82,7 @@ class VmFuncDisplay extends StatelessWidget { 'Recognized', boolYesOrNo(function.isRecognized), ), - selectableTextBuilderMapEntry( - 'Native', - boolYesOrNo(function.isNative), - ), + selectableTextBuilderMapEntry('Native', boolYesOrNo(function.isNative)), selectableTextBuilderMapEntry('VM Name', function.vmName), ]; } @@ -113,9 +107,7 @@ class VmFuncDisplay extends StatelessWidget { addSpace(); - kind.write( - funcKind.kindDescription().toLowerCase(), - ); + kind.write(funcKind.kindDescription().toLowerCase()); return kind.toString(); } @@ -135,20 +127,17 @@ class CallSiteDataArrayWidget extends StatelessWidget { Widget build(BuildContext context) { return VmExpansionTile( title: 'Call Site Data (${callSiteDataArray.length})', - children: prettyRows( - context, - [ - for (final entry in callSiteDataArray.elements!) - Row( - children: [ - VmServiceObjectLink( - object: entry as ObjRef, - onTap: controller.findAndSelectNodeForObject, - ), - ], - ), - ], - ), + children: prettyRows(context, [ + for (final entry in callSiteDataArray.elements!) + Row( + children: [ + VmServiceObjectLink( + object: entry as ObjRef, + onTap: controller.findAndSelectNodeForObject, + ), + ], + ), + ]), ); } } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_ic_data_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_ic_data_display.dart index 5762650d1a6..43339438f03 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_ic_data_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_ic_data_display.dart @@ -68,8 +68,13 @@ class _VmICDataDisplayState extends State { return; } - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!; + final isolateId = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!; final service = serviceConnection.serviceManager.service!; final argumentsDescriptorFuture = service .getObject(isolateId, icData.argumentsDescriptor.id!) @@ -80,9 +85,7 @@ class _VmICDataDisplayState extends State { _initialized = Future.wait([ argumentsDescriptorFuture, entriesFuture, - ]).then( - (result) => populateLists(result[0], result[1]), - ); + ]).then((result) => populateLists(result[0], result[1])); } @override diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_instance_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_instance_display.dart index 59e96618671..d3587fe6c94 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_instance_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_instance_display.dart @@ -64,9 +64,7 @@ class _VmInstanceDisplayState extends State { unawaited( _initialized = buildVariablesTree(_root) - .then( - (_) => _root.expand(), - ) + .then((_) => _root.expand()) .then( (_) => unawaited( Future.wait([ @@ -125,10 +123,7 @@ class _VmInstanceDisplayState extends State { } class _InstanceViewer extends StatelessWidget { - const _InstanceViewer({ - required this.controller, - required this.instance, - }); + const _InstanceViewer({required this.controller, required this.instance}); final ObjectInspectorViewController controller; final InstanceObject instance; @@ -185,17 +180,14 @@ class DisplayProvider extends StatelessWidget { SelectableText.rich( TextSpan( text: hasName ? variable.name : null, - style: variable.artificialName - ? theme.subtleFixedFontStyle - : theme.fixedFontStyle.apply( - color: theme.colorScheme.controlFlowSyntaxColor, - ), + style: + variable.artificialName + ? theme.subtleFixedFontStyle + : theme.fixedFontStyle.apply( + color: theme.colorScheme.controlFlowSyntaxColor, + ), children: [ - if (hasName) - TextSpan( - text: ': ', - style: theme.fixedFontStyle, - ), + if (hasName) TextSpan(text: ': ', style: theme.fixedFontStyle), if (variable.ref!.value is Sentinel) TextSpan( text: 'Sentinel ${variable.displayValue.toString()}', diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_library_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_library_display.dart index 60c154ab127..1605eceab5b 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_library_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_library_display.dart @@ -47,10 +47,7 @@ class VmLibraryDisplay extends StatelessWidget { LibraryObject library, ) { return [ - ...vmObjectGeneralDataRows( - controller, - library, - ), + ...vmObjectGeneralDataRows(controller, library), serviceObjectLinkBuilderMapEntry( controller: controller, key: 'URI', @@ -58,20 +55,14 @@ class VmLibraryDisplay extends StatelessWidget { object: (library.obj.uri?.isEmpty ?? false) ? library.script! : library.obj, ), - selectableTextBuilderMapEntry( - 'VM Name', - library.vmName, - ), + selectableTextBuilderMapEntry('VM Name', library.vmName), ]; } } /// An expandable tile displaying a list of library dependencies class LibraryDependencies extends StatelessWidget { - const LibraryDependencies({ - super.key, - required this.dependencies, - }); + const LibraryDependencies({super.key, required this.dependencies}); final List dependencies; @@ -82,12 +73,7 @@ class LibraryDependencies extends StatelessWidget { for (final dep in dependencies) Row( children: [ - Flexible( - child: SelectableText( - dep.description, - style: textStyle, - ), - ), + Flexible(child: SelectableText(dep.description, style: textStyle)), ], ), ]; @@ -97,10 +83,7 @@ class LibraryDependencies extends StatelessWidget { Widget build(BuildContext context) { return VmExpansionTile( title: 'Dependencies (${dependencies.length})', - children: prettyRows( - context, - dependencyRows(context), - ), + children: prettyRows(context, dependencyRows(context)), ); } } @@ -117,9 +100,7 @@ extension LibraryDependencyExtension on LibraryDependency { addSpace(); - description.write( - target?.name ?? target?.uri ?? '', - ); + description.write(target?.name ?? target?.uri ?? ''); final libPrefix = prefix; diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_model.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_model.dart index 5803fa81af2..cc8edc2d7b5 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_model.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_model.dart @@ -60,30 +60,31 @@ abstract class VmObject { ValueListenable> get inboundReferencesTree => _inboundReferencesTree; - final _inboundReferencesTree = - ListValueNotifier([]); + final _inboundReferencesTree = ListValueNotifier( + [], + ); @mustCallSuper Future initialize() async { _isolate = serviceConnection.serviceManager.isolateManager.selectedIsolate.value!; - _obj = ref is Obj - ? ref as Obj - : await _service.getObject(_isolate!.id!, ref.id!); + _obj = + ref is Obj + ? ref as Obj + : await _service.getObject(_isolate!.id!, ref.id!); if (_sourceLocation != null) { - _sourceScript = await _service.getObject( - _isolate!.id!, - scriptRef?.id ?? _sourceLocation!.script!.id!, - ) as Script; + _sourceScript = + await _service.getObject( + _isolate!.id!, + scriptRef?.id ?? _sourceLocation!.script!.id!, + ) + as Script; final token = _sourceLocation!.tokenPos!; - _pos = SourcePosition.calculatePosition( - _sourceScript!, - token, - ); + _pos = SourcePosition.calculatePosition(_sourceScript!, token); } } @@ -100,8 +101,11 @@ abstract class VmObject { } Future requestRetainingPath() async { - _retainingPath.value = - await _service.getRetainingPath(_isolate!.id!, ref.id!, 100); + _retainingPath.value = await _service.getRetainingPath( + _isolate!.id!, + ref.id!, + 100, + ); } /// Retrieves the root set of inbound references to the current object. @@ -127,9 +131,7 @@ abstract class VmObject { node.ref.source!.id!, 100, ); - node.addAllChildren( - InboundReferencesTreeNode.buildTreeRoots(inboundRefs), - ); + node.addAllChildren(InboundReferencesTreeNode.buildTreeRoots(inboundRefs)); _inboundReferencesTree.notifyListeners(); } } @@ -192,8 +194,9 @@ class FuncObject extends VmObject { final funcKind = obj.kind; return funcKind == null ? null - : FunctionKind.values - .firstWhereOrNull((element) => element.kind() == funcKind); + : FunctionKind.values.firstWhereOrNull( + (element) => element.kind() == funcKind, + ); } int? get deoptimizations => obj.deoptimizations; @@ -321,8 +324,13 @@ class CodeObject extends VmObject { await super.initialize(); final service = serviceConnection.serviceManager.service!; - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!; + final isolateId = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!; // Attempt to retrieve the CPU profile data for this code object. try { diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_pool_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_pool_display.dart index f4a9c17074a..18ceb0dd8ed 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_pool_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_pool_display.dart @@ -23,11 +23,7 @@ abstract class _ObjectPoolColumnData extends ColumnData { } class _AddressColumn extends _ObjectPoolColumnData { - _AddressColumn() - : super( - 'Offset', - fixedWidthPx: 160, - ); + _AddressColumn() : super('Offset', fixedWidthPx: 160); @override int getValue(ObjectPoolEntry dataObject) { diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_script_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_script_display.dart index e4d365caaee..ffb6d34b33e 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_script_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_script_display.dart @@ -37,23 +37,15 @@ class VmScriptDisplay extends StatelessWidget { /// Generates a list of key-value pairs (map entries) containing the general /// VM information of the Script object [widget.script]. - List> _scriptDataRows( - ScriptObject field, - ) { + List> _scriptDataRows(ScriptObject field) { return [ - ...vmObjectGeneralDataRows( - controller, - field, - ), + ...vmObjectGeneralDataRows(controller, field), serviceObjectLinkBuilderMapEntry( controller: controller, key: 'URI', object: script.obj, ), - selectableTextBuilderMapEntry( - 'Load time', - script.loadTime.toString(), - ), + selectableTextBuilderMapEntry('Load time', script.loadTime.toString()), ]; } } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_simple_list_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_simple_list_display.dart index 2a7952ea7f2..0d174297a8f 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_simple_list_display.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_simple_list_display.dart @@ -59,10 +59,17 @@ class _VmSimpleListDisplayState extends State { return; } - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!; + final isolateId = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!; final service = serviceConnection.serviceManager.service!; - _initialized = service.getObject(isolateId, elementsInstance.id!).then( + _initialized = service + .getObject(isolateId, elementsInstance.id!) + .then( (e) => entries.addAll((e as Instance).elements!.cast()), ); return; @@ -88,10 +95,7 @@ class _VmSimpleListDisplayState extends State { controller: widget.controller, object: widget.vmObject, generalDataRows: [ - ...vmObjectGeneralDataRows( - widget.controller, - widget.vmObject, - ), + ...vmObjectGeneralDataRows(widget.controller, widget.vmObject), ], expandableWidgets: [ ExpansionTileInstanceList( diff --git a/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_tree_columns.dart b/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_tree_columns.dart index f5ad49efd8f..b0745391abd 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_tree_columns.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_tree_columns.dart @@ -25,10 +25,10 @@ class DescriptionColumn extends ColumnData { class MemoryColumn extends SizeAndPercentageColumn { MemoryColumn({required VMProcessMemoryViewController controller}) - : super( - title: 'Memory Usage', - sizeProvider: (node) => node.byteSize, - percentAsDoubleProvider: (node) => - node.byteSize / controller.treeRoot.value!.byteSize, - ); + : super( + title: 'Memory Usage', + sizeProvider: (node) => node.byteSize, + percentAsDoubleProvider: + (node) => node.byteSize / controller.treeRoot.value!.byteSize, + ); } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_view.dart b/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_view.dart index 544c880ba66..ba6717ba5f1 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_view.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_view.dart @@ -31,10 +31,7 @@ import 'process_memory_view_controller.dart'; /// process's memory footprint. class VMProcessMemoryView extends VMDeveloperView { const VMProcessMemoryView() - : super( - title: 'Process Memory', - icon: Icons.memory, - ); + : super(title: 'Process Memory', icon: Icons.memory); @override Widget build(BuildContext context) => VMProcessMemoryViewBody(); @@ -55,10 +52,10 @@ enum ProcessMemoryTab { class VMProcessMemoryViewBody extends StatefulWidget { VMProcessMemoryViewBody({super.key}) - : tabs = [ - _buildTab(ProcessMemoryTab.tree), - _buildTab(ProcessMemoryTab.treeMap), - ]; + : tabs = [ + _buildTab(ProcessMemoryTab.tree), + _buildTab(ProcessMemoryTab.treeMap), + ]; static DevToolsTab _buildTab(ProcessMemoryTab processMemoryTab) { return DevToolsTab.create( @@ -105,10 +102,8 @@ class _VMProcessMemoryViewBodyState extends State ..dispose(); } - _tabController = TabController( - length: widget.tabs.length, - vsync: this, - )..addListener(_onTabChanged); + _tabController = TabController(length: widget.tabs.length, vsync: this) + ..addListener(_onTabChanged); _tabControllerInitialized = true; } @@ -178,9 +173,7 @@ class _VMProcessMemoryViewBodyState extends State } class _ProcessMemoryTree extends StatelessWidget { - _ProcessMemoryTree({ - required this.controller, - }); + _ProcessMemoryTree({required this.controller}); final VMProcessMemoryViewController controller; @@ -200,12 +193,11 @@ class _ProcessMemoryTree extends StatelessWidget { valueListenable: controller.treeRoot, builder: (context, root, _) { return TreeTable( - keyFactory: (e) => - PageStorageKey('${e.name}+${e.depth}+${e.byteSize}'), + keyFactory: + (e) => + PageStorageKey('${e.name}+${e.depth}+${e.byteSize}'), displayTreeGuidelines: true, - dataRoots: [ - if (root != null) root, - ], + dataRoots: [if (root != null) root], dataKey: 'process-memory-tree', columns: columns, treeColumn: categoryColumn, @@ -218,9 +210,7 @@ class _ProcessMemoryTree extends StatelessWidget { } class _ProcessMemoryTreeMap extends StatelessWidget { - const _ProcessMemoryTreeMap({ - required this.controller, - }); + const _ProcessMemoryTreeMap({required this.controller}); final VMProcessMemoryViewController controller; diff --git a/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_view_controller.dart b/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_view_controller.dart index b1d576658a3..c5b00679367 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_view_controller.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/process_memory/process_memory_view_controller.dart @@ -42,11 +42,9 @@ class VMProcessMemoryViewController extends DisposableController { currentRoot.addChild( TreemapNode( name: 'Other', - byteSize: currentRoot.byteSize - - currentRoot.children.fold( - 0, - (sum, e) => sum + e.byteSize, - ), + byteSize: + currentRoot.byteSize - + currentRoot.children.fold(0, (sum, e) => sum + e.byteSize), ), ); diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_common_widgets.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_common_widgets.dart index 749c67a0c25..82cfb4b4923 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_common_widgets.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_common_widgets.dart @@ -81,10 +81,7 @@ MapEntry selectableTextBuilderMapEntry( ) { return MapEntry( key, - (context) => Text( - value ?? '--', - style: Theme.of(context).fixedFontStyle, - ), + (context) => Text(value ?? '--', style: Theme.of(context).fixedFontStyle), ); } @@ -141,25 +138,20 @@ class VMInfoList extends StatelessWidget { controller: listScrollController, child: ListView( controller: listScrollController, - children: prettyRows( - context, - [ - for (final row in rowKeyValues) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '${row.key.toString()}:', - style: theme.fixedFontStyle, - ), - const SizedBox(width: denseSpacing), - Flexible( - child: Builder(builder: row.value), - ), - ], - ), - ], - ), + children: prettyRows(context, [ + for (final row in rowKeyValues) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '${row.key.toString()}:', + style: theme.fixedFontStyle, + ), + const SizedBox(width: denseSpacing), + Flexible(child: Builder(builder: row.value)), + ], + ), + ]), ), ), ), @@ -180,9 +172,7 @@ Widget _buildAlternatingRow(BuildContext context, int index, Widget row) { return Container( color: alternatingColorForIndex(index, Theme.of(context).colorScheme), height: defaultRowHeight, - padding: const EdgeInsets.symmetric( - horizontal: defaultSpacing, - ), + padding: const EdgeInsets.symmetric(horizontal: defaultSpacing), child: row, ); } @@ -222,28 +212,28 @@ class RequestableSizeWidget extends StatelessWidget { final size = sizeProvider(); return size == null ? GaDevToolsButton( - icon: Icons.call_made, - label: 'Request', - outlined: false, - gaScreen: gac.vmTools, - gaSelection: gac.requestSize, - onPressed: requestFunction, - ) + icon: Icons.call_made, + label: 'Request', + outlined: false, + gaScreen: gac.vmTools, + gaSelection: gac.requestSize, + onPressed: requestFunction, + ) : Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - size.valueAsString == null - ? '--' - : prettyPrintBytes( - int.parse(size.valueAsString!), - includeUnit: true, - maxBytes: 512, - )!, - ), - ToolbarRefresh(onPressed: requestFunction), - ], - ); + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + size.valueAsString == null + ? '--' + : prettyPrintBytes( + int.parse(size.valueAsString!), + includeUnit: true, + maxBytes: 512, + )!, + ), + ToolbarRefresh(onPressed: requestFunction), + ], + ); } }, ); @@ -292,9 +282,7 @@ class VmExpansionTile extends StatelessWidget { final theme = Theme.of(context); return Card( child: ListTileTheme( - data: ListTileTheme.of(context).copyWith( - dense: true, - ), + data: ListTileTheme.of(context).copyWith(dense: true), child: Theme( // Prevents divider lines appearing at the top and bottom of the // expanded ExpansionTile. @@ -347,10 +335,7 @@ class ExpansionTileInstanceList extends StatelessWidget { for (int i = 0; i < elements.length; ++i) Row( children: [ - Text( - '[$i]: ', - style: theme.subtleFixedFontStyle, - ), + Text('[$i]: ', style: theme.subtleFixedFontStyle), VmServiceObjectLink( object: elements[i], onTap: controller.findAndSelectNodeForObject, @@ -383,12 +368,10 @@ class RetainingPathWidget extends StatelessWidget { return ValueListenableBuilder( valueListenable: retainingPath, builder: (context, retainingPath, _) { - final retainingObjects = retainingPath == null - ? const [] - : _retainingPathList( - context, - retainingPath, - ); + final retainingObjects = + retainingPath == null + ? const [] + : _retainingPathList(context, retainingPath); return VmExpansionTile( title: 'Retaining Path', onExpanded: onExpanded, @@ -396,11 +379,11 @@ class RetainingPathWidget extends StatelessWidget { retainingPath == null ? const SizedCircularProgressIndicator() : SizedBox.fromSize( - size: Size.fromHeight( - retainingObjects.length * defaultRowHeight + densePadding, - ), - child: Column(children: retainingObjects), + size: Size.fromHeight( + retainingObjects.length * defaultRowHeight + densePadding, ), + child: Column(children: retainingObjects), + ), ], ); }, @@ -419,25 +402,19 @@ class RetainingPathWidget extends StatelessWidget { } final theme = Theme.of(context); - final emptyList = Text( - 'No retaining objects', - style: theme.fixedFontStyle, - ); + final emptyList = Text('No retaining objects', style: theme.fixedFontStyle); if (retainingPath.elements == null) return [emptyList]; - final firstRetainingObject = retainingPath.elements!.isNotEmpty - ? VmServiceObjectLink( - object: retainingPath.elements!.first.value, - onTap: onTap, - ) - : emptyList; + final firstRetainingObject = + retainingPath.elements!.isNotEmpty + ? VmServiceObjectLink( + object: retainingPath.elements!.first.value, + onTap: onTap, + ) + : emptyList; final retainingObjects = [ - Row( - children: [ - firstRetainingObject, - ], - ), + Row(children: [firstRetainingObject]), if (retainingPath.elements!.length > 1) for (final object in retainingPath.elements!.sublist(1)) Row( @@ -498,19 +475,21 @@ class _RetainingObjectDescription extends StatelessWidget { text: TextSpan( children: [ const TextSpan(text: 'Retained by element at ['), - VmServiceObjectLink(object: object.parentMapKey, onTap: onTap) - .buildTextSpan(context), + VmServiceObjectLink( + object: object.parentMapKey, + onTap: onTap, + ).buildTextSpan(context), const TextSpan(text: '] of '), - VmServiceObjectLink(object: object.value, onTap: onTap) - .buildTextSpan(context), + VmServiceObjectLink( + object: object.value, + onTap: onTap, + ).buildTextSpan(context), ], ), ); } - final entries = [ - const TextSpan(text: 'Retained by '), - ]; + final entries = [const TextSpan(text: 'Retained by ')]; if (object.parentField is int) { assert((object.value as InstanceRef).kind == InstanceKind.kRecord); @@ -521,31 +500,23 @@ class _RetainingObjectDescription extends StatelessWidget { if (object.value is FieldRef) { final field = object.value as FieldRef; - entries.addAll( - [ - VmServiceObjectLink( - object: field.declaredType, - onTap: onTap, - ).buildTextSpan(context), - const TextSpan(text: ' '), - VmServiceObjectLink( - object: field, - onTap: onTap, - ).buildTextSpan(context), - const TextSpan(text: ' of '), - VmServiceObjectLink( - object: field.owner, - onTap: onTap, - ).buildTextSpan(context), - ], - ); - } else if (object.value is FuncRef) { - final func = object.value as FuncRef; - entries.add( + entries.addAll([ + VmServiceObjectLink( + object: field.declaredType, + onTap: onTap, + ).buildTextSpan(context), + const TextSpan(text: ' '), + VmServiceObjectLink(object: field, onTap: onTap).buildTextSpan(context), + const TextSpan(text: ' of '), VmServiceObjectLink( - object: func, + object: field.owner, onTap: onTap, ).buildTextSpan(context), + ]); + } else if (object.value is FuncRef) { + final func = object.value as FuncRef; + entries.add( + VmServiceObjectLink(object: func, onTap: onTap).buildTextSpan(context), ); } else { entries.add( @@ -555,9 +526,7 @@ class _RetainingObjectDescription extends StatelessWidget { ).buildTextSpan(context), ); } - return RichText( - text: TextSpan(children: entries), - ); + return RichText(text: TextSpan(children: entries)); } } @@ -588,10 +557,11 @@ class InboundReferencesTree extends StatelessWidget { builder: (context, references, _) { return TreeView( dataRootsListenable: object.inboundReferencesTree, - dataDisplayProvider: (node, _) => InboundReferenceWidget( - controller: controller, - node: node, - ), + dataDisplayProvider: + (node, _) => InboundReferenceWidget( + controller: controller, + node: node, + ), emptyTreeViewBuilder: () { return Padding( padding: EdgeInsets.all(defaultRowHeight / 2), @@ -625,9 +595,7 @@ class InboundReferenceWidget extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); - final rowContent = [ - const Text('Referenced by '), - ]; + final rowContent = [const Text('Referenced by ')]; final parentField = node.ref.parentField; if (parentField != null) { @@ -647,9 +615,7 @@ class InboundReferenceWidget extends StatelessWidget { ); return DefaultTextStyle( style: theme.regularTextStyle, - child: Row( - children: rowContent, - ), + child: Row(children: rowContent), ); } } @@ -669,10 +635,7 @@ class VmServiceObjectLink extends StatelessWidget { final FutureOr Function(ObjRef) onTap; @visibleForTesting - static String? defaultTextBuilder( - Object? object, { - bool preferUri = false, - }) { + static String? defaultTextBuilder(Object? object, {bool preferUri = false}) { if (object == null) return null; return switch (object) { FieldRef(:final name) || @@ -725,7 +688,8 @@ class VmServiceObjectLink extends StatelessWidget { TextSpan buildTextSpan(BuildContext context) { final theme = Theme.of(context); - String? text = textBuilder?.call(object) ?? + String? text = + textBuilder?.call(object) ?? defaultTextBuilder(object, preferUri: preferUri); // Sentinels aren't objects that can be inspected. @@ -741,15 +705,16 @@ class VmServiceObjectLink extends StatelessWidget { return TextSpan( text: text, style: style.apply(overflow: TextOverflow.ellipsis), - recognizer: isServiceObject - ? (TapGestureRecognizer() - ..onTap = () async { - final obj = object; - if (obj is ObjRef) { - await onTap(obj); - } - }) - : null, + recognizer: + isServiceObject + ? (TapGestureRecognizer() + ..onTap = () async { + final obj = object; + if (obj is ObjRef) { + await onTap(obj); + } + }) + : null, ); } @@ -757,9 +722,7 @@ class VmServiceObjectLink extends StatelessWidget { Widget build(BuildContext context) { return RichText( maxLines: 1, - text: TextSpan( - children: [buildTextSpan(context)], - ), + text: TextSpan(children: [buildTextSpan(context)]), ); } } @@ -849,11 +812,7 @@ class VmObjectDisplayBasicLayout extends StatelessWidget { MapEntry shallowSizeRowBuilder(VmObject object) { return selectableTextBuilderMapEntry( 'Shallow Size', - prettyPrintBytes( - object.obj.size ?? 0, - includeUnit: true, - maxBytes: 512, - ), + prettyPrintBytes(object.obj.size ?? 0, includeUnit: true, maxBytes: 512), ); } @@ -1011,9 +970,8 @@ class _ObjectInspectorCodeViewState extends State { location.endTokenPos != null) { final script = currentParsedScript.script; final startLine = location.line!; - final endLine = script.getLineNumberFromTokenPos( - location.endTokenPos!, - )!; + final endLine = + script.getLineNumberFromTokenPos(location.endTokenPos!)!; lineRange = LineRange(startLine, endLine); } } @@ -1022,9 +980,7 @@ class _ObjectInspectorCodeViewState extends State { axis: Axis.vertical, initialFractions: const [0.5, 0.5], children: [ - OutlineDecoration.onlyBottom( - child: widget.child, - ), + OutlineDecoration.onlyBottom(child: widget.child), Column( children: [ const AreaPaneHeader( diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_controller.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_controller.dart index a2e77c973ee..af056995646 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_controller.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_controller.dart @@ -11,7 +11,7 @@ class VMDeveloperToolsController { VMDeveloperToolsController({ ObjectInspectorViewController? objectInspectorViewController, }) : objectInspectorViewController = - objectInspectorViewController ?? ObjectInspectorViewController(); + objectInspectorViewController ?? ObjectInspectorViewController(); ValueListenable get selectedIndex => _selectedIndex; final _selectedIndex = ValueNotifier(0); 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 69370c30be8..4be635b286d 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 @@ -16,10 +16,7 @@ import 'vm_developer_tools_controller.dart'; import 'vm_statistics/vm_statistics_view.dart'; abstract class VMDeveloperView { - const VMDeveloperView({ - required this.title, - required this.icon, - }); + const VMDeveloperView({required this.title, required this.icon}); /// The user-facing name of the page. final String title; @@ -68,8 +65,10 @@ class VMDeveloperToolsScreenBody extends StatefulWidget { class _VMDeveloperToolsScreenState extends State with AutoDisposeMixin, - ProvidedControllerMixin { + ProvidedControllerMixin< + VMDeveloperToolsController, + VMDeveloperToolsScreenBody + > { @override void didChangeDependencies() { super.didChangeDependencies(); @@ -98,9 +97,7 @@ class _VMDeveloperToolsScreenState extends State ), Expanded( child: Padding( - padding: const EdgeInsets.only( - left: defaultSpacing, - ), + padding: const EdgeInsets.only(left: defaultSpacing), child: IndexedStack( index: selectedIndex, children: [ 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 7802964640f..50f42dcc37f 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 @@ -79,15 +79,12 @@ class HeapStats { required this.externalSize, }); - const HeapStats.empty() - : count = 0, - size = 0, - externalSize = 0; + const HeapStats.empty() : count = 0, size = 0, externalSize = 0; HeapStats.parse(List stats) - : count = stats[0], - size = stats[1], - externalSize = stats[2]; + : count = stats[0], + size = stats[1], + externalSize = stats[2]; final int count; final int size; @@ -100,12 +97,14 @@ extension ClassHeapStatsPrivateViewExtension on ClassHeapStats { static const _newSpaceKey = '_new'; static const _oldSpaceKey = '_old'; - HeapStats get newSpace => json!.containsKey(_newSpaceKey) - ? HeapStats.parse((json![_newSpaceKey] as List).cast()) - : const HeapStats.empty(); - HeapStats get oldSpace => json!.containsKey(_oldSpaceKey) - ? HeapStats.parse((json![_oldSpaceKey] as List).cast()) - : const HeapStats.empty(); + HeapStats get newSpace => + json!.containsKey(_newSpaceKey) + ? HeapStats.parse((json![_newSpaceKey] as List).cast()) + : const HeapStats.empty(); + HeapStats get oldSpace => + json!.containsKey(_oldSpaceKey) + ? HeapStats.parse((json![_oldSpaceKey] as List).cast()) + : const HeapStats.empty(); } extension AllocationProfilePrivateViewExtension on AllocationProfile { @@ -114,14 +113,14 @@ extension AllocationProfilePrivateViewExtension on AllocationProfile { static const oldSpaceKey = 'old'; GCStats get newSpaceGCStats => GCStats.parse( - heap: HeapGeneration.newSpace.toString(), - json: (_heaps[newSpaceKey] as Map).cast(), - ); + heap: HeapGeneration.newSpace.toString(), + json: (_heaps[newSpaceKey] as Map).cast(), + ); GCStats get oldSpaceGCStats => GCStats.parse( - heap: HeapGeneration.oldSpace.toString(), - json: (_heaps[oldSpaceKey] as Map).cast(), - ); + heap: HeapGeneration.oldSpace.toString(), + json: (_heaps[oldSpaceKey] as Map).cast(), + ); Map get _heaps => (json![heapsKey] as Map).cast(); @@ -132,8 +131,8 @@ extension AllocationProfilePrivateViewExtension on AllocationProfile { final collections = newSpace.collections + oldSpace.collections; final averageCollectionTime = ((newSpace.collections * newSpace.averageCollectionTime) + - (oldSpace.collections * oldSpace.averageCollectionTime)) / - collections; + (oldSpace.collections * oldSpace.averageCollectionTime)) / + collections; return GCStats( heap: HeapGeneration.total.toString(), usage: newSpace.usage + oldSpace.usage, @@ -205,17 +204,10 @@ extension ObjPrivateViewExtension on Obj { /// not prevent referenced objects from being collected when all other /// references to the object disappear. class WeakArrayRef implements ObjRef { - WeakArrayRef({ - required this.id, - required this.json, - required this.length, - }); + WeakArrayRef({required this.id, required this.json, required this.length}); - factory WeakArrayRef.fromJson(Map json) => WeakArrayRef( - id: json['id'], - json: json, - length: json['length'], - ); + factory WeakArrayRef.fromJson(Map json) => + WeakArrayRef(id: json['id'], json: json, length: json['length']); @override bool? fixedId; @@ -252,14 +244,14 @@ class WeakArray extends WeakArrayRef implements Obj { }); factory WeakArray.fromJson(Map json) => WeakArray( - id: json['id'], - json: json, - length: json['length'], - size: json['size'], - elements: (createServiceObject(json['elements'], []) as List) - .cast(), - classRef: createServiceObject(json['class'], [])! as ClassRef, - ); + id: json['id'], + json: json, + length: json['length'], + size: json['size'], + elements: + (createServiceObject(json['elements'], []) as List).cast(), + classRef: createServiceObject(json['class'], [])! as ClassRef, + ); final List elements; @@ -278,16 +270,10 @@ class WeakArray extends WeakArrayRef implements Obj { /// A partially-populated representation of the Dart VM's subtype test cache. class SubtypeTestCacheRef implements ObjRef { - SubtypeTestCacheRef({ - required this.id, - required this.json, - }); + SubtypeTestCacheRef({required this.id, required this.json}); factory SubtypeTestCacheRef.fromJson(Map json) => - SubtypeTestCacheRef( - id: json['id'], - json: json, - ); + SubtypeTestCacheRef(id: json['id'], json: json); @override bool? fixedId; @@ -348,11 +334,11 @@ class ICDataRef implements ObjRef { }); factory ICDataRef.fromJson(Map json) => ICDataRef( - id: json['id'], - owner: createServiceObject(json['_owner'], []) as ObjRef, - selector: json['_selector'], - json: json, - ); + id: json['id'], + owner: createServiceObject(json['_owner'], []) as ObjRef, + selector: json['_selector'], + json: json, + ); final ObjRef owner; final String selector; @@ -391,17 +377,16 @@ class ICData extends ICDataRef implements Obj { }) : super(); factory ICData.fromJson(Map json) => ICData( - id: json['id'], - owner: createServiceObject(json['_owner'], []) as ObjRef, - selector: json['_selector'], - classRef: createServiceObject(json['class'], []) as ClassRef, - size: json['size'], - argumentsDescriptor: - createServiceObject(json['_argumentsDescriptor'], [])! - as InstanceRef, - entries: createServiceObject(json['_entries'], [])! as InstanceRef, - json: json, - ); + id: json['id'], + owner: createServiceObject(json['_owner'], []) as ObjRef, + selector: json['_selector'], + classRef: createServiceObject(json['class'], []) as ClassRef, + size: json['size'], + argumentsDescriptor: + createServiceObject(json['_argumentsDescriptor'], [])! as InstanceRef, + entries: createServiceObject(json['_entries'], [])! as InstanceRef, + json: json, + ); @override ClassRef? classRef; @@ -416,17 +401,18 @@ class ICData extends ICDataRef implements Obj { /// A single assembly instruction from a [Func]'s generated code disassembly. class Instruction { Instruction.parse(List data) - : address = data[0], - unknown = data[1], - instruction = data[2] { + : address = data[0], + unknown = data[1], + instruction = data[2] { if (data[3] == null) { object = null; return; } final rawObject = data[3] as Map; - object = (rawObject['type'] as List).contains('Instance') - ? InstanceRef.parse(rawObject) - : createServiceObject(data[3], const []) as Response?; + object = + (rawObject['type'] as List).contains('Instance') + ? InstanceRef.parse(rawObject) + : createServiceObject(data[3], const []) as Response?; } /// The instruction's address in memory. @@ -445,12 +431,7 @@ class Instruction { /// The Dart object this instruction is acting upon directly. late final Response? object; - List toJson() => [ - address, - unknown, - instruction, - object?.json, - ]; + List toJson() => [address, unknown, instruction, object?.json]; } /// The full disassembly of generated [Code] for a function. @@ -466,9 +447,7 @@ class Disassembly { /// The list of [Instructions] that make up the generated code. final instructions = []; - List toJson() => [ - for (final i in instructions) ...i.toJson(), - ]; + List toJson() => [for (final i in instructions) ...i.toJson()]; } /// An extension on [Func] which allows for access to VM internal fields. @@ -551,10 +530,7 @@ enum FunctionKind { final camelCase = RegExp(r'(?<=[a-z])[A-Z]'); description.write( - kind().replaceAllMapped( - camelCase, - (Match m) => ' ${m.group(0)!}', - ), + kind().replaceAllMapped(camelCase, (Match m) => ' ${m.group(0)!}'), ); return description.toString(); @@ -597,10 +573,11 @@ class InliningData { factory InliningData.fromJson(Map json) { final startAddress = int.parse(json[kStartAddressKey], radix: 16); final intervals = (json[kInlinedIntervals] as List).cast(); - final functions = (json[kInlinedFunctions] as List) - .cast>() - .map((e) => FuncRef.parse(e)!) - .toList(); + final functions = + (json[kInlinedFunctions] as List) + .cast>() + .map((e) => FuncRef.parse(e)!) + .toList(); final entries = []; @@ -618,10 +595,7 @@ class InliningData { for (int i = 3; i < interval.length; ++i) functions[interval[i]], ]; entries.add( - InliningEntry( - addressRange: range, - functions: inlinedFunctions, - ), + InliningEntry(addressRange: range, functions: inlinedFunctions), ); } @@ -639,10 +613,7 @@ class InliningData { } class InliningEntry { - const InliningEntry({ - required this.addressRange, - required this.functions, - }); + const InliningEntry({required this.addressRange, required this.functions}); final Range addressRange; final List functions; @@ -660,11 +631,8 @@ class ObjectPoolRef extends ObjRef { static const _idKey = 'id'; static const _lengthKey = 'length'; - static ObjectPoolRef parse(Map json) => ObjectPoolRef( - id: json[_idKey], - length: json[_lengthKey], - json: json, - ); + static ObjectPoolRef parse(Map json) => + ObjectPoolRef(id: json[_idKey], length: json[_lengthKey], json: json); final int length; } @@ -683,9 +651,10 @@ class ObjectPool extends ObjectPoolRef implements Obj { return ObjectPool( json: json, id: json[ObjectPoolRef._idKey], - entries: (json[_entriesKey] as List) - .map((e) => ObjectPoolEntry.parse(e)) - .toList(), + entries: + (json[_entriesKey] as List) + .map((e) => ObjectPoolEntry.parse(e)) + .toList(), length: json[ObjectPoolRef._lengthKey], ); } @@ -749,10 +718,10 @@ class ObjectPoolEntry { static const _valueKey = 'value'; static ObjectPoolEntry parse(Map json) => ObjectPoolEntry( - offset: json[_offsetKey], - kind: ObjectPoolEntryKind.fromString(json[_kindKey]), - value: createServiceObject(json[_valueKey], [])!, - ); + offset: json[_offsetKey], + kind: ObjectPoolEntryKind.fromString(json[_kindKey]), + value: createServiceObject(json[_valueKey], [])!, + ); final int offset; @@ -774,9 +743,10 @@ extension FieldPrivateViewExtension on Field { serviceConnection.serviceManager.isolateManager.selectedIsolate.value; return await service.getObject( - isolate!.id!, - guardClassData['id'] as String, - ) as Class; + isolate!.id!, + guardClassData['id'] as String, + ) + as Class; } return null; @@ -857,9 +827,7 @@ typedef ObjectStoreEntry = MapEntry; /// collector, meaning that objects in the store will be considered live, even /// if they're not referenced anywhere else in the program. class ObjectStore { - const ObjectStore({ - required this.fields, - }); + const ObjectStore({required this.fields}); static ObjectStore? parse(Map? json) { if (json?['type'] != '_ObjectStore') { @@ -930,7 +898,8 @@ class ProfileCode { } @override - String toString() => '[ProfileCode ' // + String toString() => + '[ProfileCode ' // 'kind: $kind, inclusiveTicks: $inclusiveTicks, exclusiveTicks: $exclusiveTicks, ' // 'code: $code]'; } @@ -953,10 +922,11 @@ extension CpuSamplesPrivateView on CpuSamples { } List get codes { - return _expando[this] ??= (json![_kCodesKey] as List) - .cast>() - .map((e) => ProfileCode.parse(e)!) - .toList(); + return _expando[this] ??= + (json![_kCodesKey] as List) + .cast>() + .map((e) => ProfileCode.parse(e)!) + .toList(); } } @@ -988,17 +958,20 @@ class ProfileReportRange { ProfileReportRange._fromJson(Script script, _ProfileReportRangeJson json) { final inclusiveTicks = json.inclusiveTicks; final exclusiveTicks = json.exclusiveTicks; - final lines = json.positions - .map( - // It's possible to get a synthetic token position which will either - // be a negative value or a String (e.g., 'ParallelMove' or - // 'NoSource'). We'll just use -1 as a placeholder since we won't - // display anything for these tokens anyway. - (e) => e is int - ? script.getLineNumberFromTokenPos(e) ?? _kNoSourcePosition - : _kNoSourcePosition, - ) - .toList(); + final lines = + json.positions + .map( + // It's possible to get a synthetic token position which will either + // be a negative value or a String (e.g., 'ParallelMove' or + // 'NoSource'). We'll just use -1 as a placeholder since we won't + // display anything for these tokens anyway. + (e) => + e is int + ? script.getLineNumberFromTokenPos(e) ?? + _kNoSourcePosition + : _kNoSourcePosition, + ) + .toList(); for (int i = 0; i < lines.length; ++i) { final line = lines[i]; entries[line] = ProfileReportEntry( @@ -1040,16 +1013,17 @@ extension type _ProfileReportRangeJson(Map json) { /// information for a given [Script]. class ProfileReport { ProfileReport._fromJson(Script script, Map json) - : _profileRanges = (json['ranges'] as List) - .cast>() - .where((e) => e.containsKey('profile')) - .map( - (e) => ProfileReportRange._fromJson( - script, - _ProfileReportRangeJson(e), - ), - ) - .toList(); + : _profileRanges = + (json['ranges'] as List) + .cast>() + .where((e) => e.containsKey('profile')) + .map( + (e) => ProfileReportRange._fromJson( + script, + _ProfileReportRangeJson(e), + ), + ) + .toList(); List get profileRanges => _profileRanges; final List _profileRanges; diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics/vm_statistics_view.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics/vm_statistics_view.dart index 5732522d44d..4b62fc54a4b 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics/vm_statistics_view.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics/vm_statistics_view.dart @@ -18,11 +18,7 @@ import '../vm_service_private_extensions.dart'; import 'vm_statistics_view_controller.dart'; class VMStatisticsView extends VMDeveloperView { - const VMStatisticsView() - : super( - title: 'VM', - icon: Icons.devices, - ); + const VMStatisticsView() : super(title: 'VM', icon: Icons.devices); @override Widget build(BuildContext context) => VMStatisticsViewBody(); @@ -48,9 +44,7 @@ class VMStatisticsViewBody extends StatelessWidget { child: ValueListenableBuilder( valueListenable: controller.refreshing, builder: (context, _, _) { - return VMStatisticsWidget( - controller: controller, - ); + return VMStatisticsWidget(controller: controller); }, ), ), @@ -73,15 +67,9 @@ class VMStatisticsWidget extends StatelessWidget { child: Column( children: [ Expanded( - child: GeneralVMStatisticsWidget( - controller: controller, - ), - ), - Expanded( - child: ProcessStatisticsWidget( - controller: controller, - ), + child: GeneralVMStatisticsWidget(controller: controller), ), + Expanded(child: ProcessStatisticsWidget(controller: controller)), ], ), ), @@ -89,11 +77,7 @@ class VMStatisticsWidget extends StatelessWidget { flex: 4, child: Column( children: [ - Flexible( - child: IsolatesPreviewWidget( - controller: controller, - ), - ), + Flexible(child: IsolatesPreviewWidget(controller: controller)), Flexible( child: IsolatesPreviewWidget( controller: controller, @@ -136,16 +120,13 @@ class GeneralVMStatisticsWidget extends StatelessWidget { vm == null ? null : formatDateTime( - DateTime.fromMillisecondsSinceEpoch(vm.startTime!), - ), + DateTime.fromMillisecondsSinceEpoch(vm.startTime!), + ), ), selectableTextBuilderMapEntry('Profiler Mode', vm?.profilerMode), selectableTextBuilderMapEntry( 'Current Memory', - prettyPrintBytes( - vm?.currentMemory, - includeUnit: true, - ), + prettyPrintBytes(vm?.currentMemory, includeUnit: true), ), ], ), @@ -186,24 +167,15 @@ class ProcessStatisticsWidget extends StatelessWidget { ), selectableTextBuilderMapEntry( 'Max Memory (RSS)', - prettyPrintBytes( - vm?.maxRSS, - includeUnit: true, - ), + prettyPrintBytes(vm?.maxRSS, includeUnit: true), ), selectableTextBuilderMapEntry( 'Current Memory (RSS)', - prettyPrintBytes( - vm?.currentRSS, - includeUnit: true, - ), + prettyPrintBytes(vm?.currentRSS, includeUnit: true), ), selectableTextBuilderMapEntry( 'Zone Memory', - prettyPrintBytes( - vm?.nativeZoneMemoryUsage, - includeUnit: true, - ), + prettyPrintBytes(vm?.nativeZoneMemoryUsage, includeUnit: true), ), ], ), diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics/vm_statistics_view_controller.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics/vm_statistics_view_controller.dart index 0c709f2ebc4..789b9f329aa 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics/vm_statistics_view_controller.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics/vm_statistics_view_controller.dart @@ -22,14 +22,10 @@ class VMStatisticsViewController extends DisposableController { final vm = await _service.getVM(); _vm = vm; _isolates = await Future.wait( - vm.isolates!.map( - (i) => _service.getIsolate(i.id!), - ), + vm.isolates!.map((i) => _service.getIsolate(i.id!)), ); _systemIsolates = await Future.wait( - vm.systemIsolates!.map( - (i) => _service.getIsolate(i.id!), - ), + vm.systemIsolates!.map((i) => _service.getIsolate(i.id!)), ); _refreshing.value = false; } diff --git a/packages/devtools_app/lib/src/service/editor/api_classes.dart b/packages/devtools_app/lib/src/service/editor/api_classes.dart index 0ed71882960..7a7835c7b02 100644 --- a/packages/devtools_app/lib/src/service/editor/api_classes.dart +++ b/packages/devtools_app/lib/src/service/editor/api_classes.dart @@ -52,7 +52,7 @@ enum EditorEventKind { debugSessionStopped, /// The kind for a [ThemeChangedEvent]. - themeChanged + themeChanged, } /// Constants for all fields used in JSON maps to avoid literal strings that @@ -105,10 +105,11 @@ class DeviceAddedEvent extends EditorEvent { DeviceAddedEvent({required this.device}); DeviceAddedEvent.fromJson(Map map) - : this( - device: - EditorDevice.fromJson(map[Field.device] as Map), - ); + : this( + device: EditorDevice.fromJson( + map[Field.device] as Map, + ), + ); final EditorDevice device; @@ -116,9 +117,7 @@ class DeviceAddedEvent extends EditorEvent { EditorEventKind get kind => EditorEventKind.deviceAdded; @override - Map toJson() => { - Field.device: device, - }; + Map toJson() => {Field.device: device}; } /// An event sent by an editor when an existing device is updated. @@ -129,10 +128,11 @@ class DeviceChangedEvent extends EditorEvent { DeviceChangedEvent({required this.device}); DeviceChangedEvent.fromJson(Map map) - : this( - device: - EditorDevice.fromJson(map[Field.device] as Map), - ); + : this( + device: EditorDevice.fromJson( + map[Field.device] as Map, + ), + ); final EditorDevice device; @@ -140,9 +140,7 @@ class DeviceChangedEvent extends EditorEvent { EditorEventKind get kind => EditorEventKind.deviceChanged; @override - Map toJson() => { - Field.device: device, - }; + Map toJson() => {Field.device: device}; } /// An event sent by an editor when a device is no longer available. @@ -150,9 +148,7 @@ class DeviceRemovedEvent extends EditorEvent { DeviceRemovedEvent({required this.deviceId}); DeviceRemovedEvent.fromJson(Map map) - : this( - deviceId: map[Field.deviceId] as String, - ); + : this(deviceId: map[Field.deviceId] as String); final String deviceId; @@ -160,9 +156,7 @@ class DeviceRemovedEvent extends EditorEvent { EditorEventKind get kind => EditorEventKind.deviceRemoved; @override - Map toJson() => { - Field.deviceId: deviceId, - }; + Map toJson() => {Field.deviceId: deviceId}; } /// An event sent by an editor when the current selected device was changed. @@ -175,9 +169,7 @@ class DeviceSelectedEvent extends EditorEvent { DeviceSelectedEvent({required this.deviceId}); DeviceSelectedEvent.fromJson(Map map) - : this( - deviceId: map[Field.deviceId] as String?, - ); + : this(deviceId: map[Field.deviceId] as String?); /// The ID of the device being selected, or `null` if the current device is /// being unselected without a new device being selected. @@ -187,9 +179,7 @@ class DeviceSelectedEvent extends EditorEvent { EditorEventKind get kind => EditorEventKind.deviceSelected; @override - Map toJson() => { - Field.deviceId: deviceId, - }; + Map toJson() => {Field.deviceId: deviceId}; } /// An event sent by an editor when a new debug session is started. @@ -197,11 +187,11 @@ class DebugSessionStartedEvent extends EditorEvent { DebugSessionStartedEvent({required this.debugSession}); DebugSessionStartedEvent.fromJson(Map map) - : this( - debugSession: EditorDebugSession.fromJson( - map[Field.debugSession] as Map, - ), - ); + : this( + debugSession: EditorDebugSession.fromJson( + map[Field.debugSession] as Map, + ), + ); final EditorDebugSession debugSession; @@ -209,9 +199,7 @@ class DebugSessionStartedEvent extends EditorEvent { EditorEventKind get kind => EditorEventKind.debugSessionStarted; @override - Map toJson() => { - Field.debugSession: debugSession, - }; + Map toJson() => {Field.debugSession: debugSession}; } /// An event sent by an editor when a debug session is changed (for example the @@ -220,11 +208,11 @@ class DebugSessionChangedEvent extends EditorEvent { DebugSessionChangedEvent({required this.debugSession}); DebugSessionChangedEvent.fromJson(Map map) - : this( - debugSession: EditorDebugSession.fromJson( - map[Field.debugSession] as Map, - ), - ); + : this( + debugSession: EditorDebugSession.fromJson( + map[Field.debugSession] as Map, + ), + ); final EditorDebugSession debugSession; @@ -232,9 +220,7 @@ class DebugSessionChangedEvent extends EditorEvent { EditorEventKind get kind => EditorEventKind.debugSessionChanged; @override - Map toJson() => { - Field.debugSession: debugSession, - }; + Map toJson() => {Field.debugSession: debugSession}; } /// An event sent by an editor when a debug session ends. @@ -242,9 +228,7 @@ class DebugSessionStoppedEvent extends EditorEvent { DebugSessionStoppedEvent({required this.debugSessionId}); DebugSessionStoppedEvent.fromJson(Map map) - : this( - debugSessionId: map[Field.debugSessionId] as String, - ); + : this(debugSessionId: map[Field.debugSessionId] as String); final String debugSessionId; @@ -252,20 +236,16 @@ class DebugSessionStoppedEvent extends EditorEvent { EditorEventKind get kind => EditorEventKind.debugSessionStopped; @override - Map toJson() => { - Field.debugSessionId: debugSessionId, - }; + Map toJson() => {Field.debugSessionId: debugSessionId}; } class ThemeChangedEvent extends EditorEvent { ThemeChangedEvent({required this.theme}); ThemeChangedEvent.fromJson(Map map) - : this( - theme: EditorTheme.fromJson( - map[Field.theme] as Map, - ), - ); + : this( + theme: EditorTheme.fromJson(map[Field.theme] as Map), + ); final EditorTheme theme; @@ -273,57 +253,50 @@ class ThemeChangedEvent extends EditorEvent { EditorEventKind get kind => EditorEventKind.themeChanged; @override - Map toJson() => { - Field.theme: theme, - }; + Map toJson() => {Field.theme: theme}; } /// The result of a `GetDevices` request. class GetDevicesResult with Serializable { - GetDevicesResult({ - required this.devices, - required this.selectedDeviceId, - }); + GetDevicesResult({required this.devices, required this.selectedDeviceId}); GetDevicesResult.fromJson(Map map) - : this( - devices: (map[Field.devices] as List) - .cast>() - .map(EditorDevice.fromJson) - .toList(), - selectedDeviceId: map[Field.selectedDeviceId] as String?, - ); + : this( + devices: + (map[Field.devices] as List) + .cast>() + .map(EditorDevice.fromJson) + .toList(), + selectedDeviceId: map[Field.selectedDeviceId] as String?, + ); final List devices; final String? selectedDeviceId; @override Map toJson() => { - Field.devices: devices, - Field.selectedDeviceId: selectedDeviceId, - }; + Field.devices: devices, + Field.selectedDeviceId: selectedDeviceId, + }; } /// The result of a `GetDebugSessions` request. class GetDebugSessionsResult with Serializable { - GetDebugSessionsResult({ - required this.debugSessions, - }); + GetDebugSessionsResult({required this.debugSessions}); GetDebugSessionsResult.fromJson(Map map) - : this( - debugSessions: (map[Field.debugSessions] as List) - .cast>() - .map(EditorDebugSession.fromJson) - .toList(), - ); + : this( + debugSessions: + (map[Field.debugSessions] as List) + .cast>() + .map(EditorDebugSession.fromJson) + .toList(), + ); final List debugSessions; @override - Map toJson() => { - Field.debugSessions: debugSessions, - }; + Map toJson() => {Field.debugSessions: debugSessions}; } /// A debug session running in the editor. @@ -339,15 +312,15 @@ class EditorDebugSession with Serializable { }); EditorDebugSession.fromJson(Map map) - : this( - id: map[Field.id] as String, - name: map[Field.name] as String, - vmServiceUri: map[Field.vmServiceUri] as String?, - flutterMode: map[Field.flutterMode] as String?, - flutterDeviceId: map[Field.flutterDeviceId] as String?, - debuggerType: map[Field.debuggerType] as String?, - projectRootPath: map[Field.projectRootPath] as String?, - ); + : this( + id: map[Field.id] as String, + name: map[Field.name] as String, + vmServiceUri: map[Field.vmServiceUri] as String?, + flutterMode: map[Field.flutterMode] as String?, + flutterDeviceId: map[Field.flutterDeviceId] as String?, + debuggerType: map[Field.debuggerType] as String?, + projectRootPath: map[Field.projectRootPath] as String?, + ); final String id; final String name; @@ -359,14 +332,14 @@ class EditorDebugSession with Serializable { @override Map toJson() => { - Field.id: id, - Field.name: name, - Field.vmServiceUri: vmServiceUri, - Field.flutterMode: flutterMode, - Field.flutterDeviceId: flutterDeviceId, - Field.debuggerType: debuggerType, - Field.projectRootPath: projectRootPath, - }; + Field.id: id, + Field.name: name, + Field.vmServiceUri: vmServiceUri, + Field.flutterMode: flutterMode, + Field.flutterDeviceId: flutterDeviceId, + Field.debuggerType: debuggerType, + Field.projectRootPath: projectRootPath, + }; } /// A device that is available in the editor. @@ -384,17 +357,17 @@ class EditorDevice with Serializable { }); EditorDevice.fromJson(Map map) - : this( - id: map[Field.id] as String, - name: map[Field.name] as String, - category: map[Field.category] as String?, - emulator: map[Field.emulator] as bool, - emulatorId: map[Field.emulatorId] as String?, - ephemeral: map[Field.ephemeral] as bool, - platform: map[Field.platform] as String, - platformType: map[Field.platformType] as String?, - supported: map[Field.supported] as bool, - ); + : this( + id: map[Field.id] as String, + name: map[Field.name] as String, + category: map[Field.category] as String?, + emulator: map[Field.emulator] as bool, + emulatorId: map[Field.emulatorId] as String?, + ephemeral: map[Field.ephemeral] as bool, + platform: map[Field.platform] as String, + platformType: map[Field.platformType] as String?, + supported: map[Field.supported] as bool, + ); final String id; final String name; @@ -414,16 +387,16 @@ class EditorDevice with Serializable { @override Map toJson() => { - Field.id: id, - Field.name: name, - Field.category: category, - Field.emulator: emulator, - Field.emulatorId: emulatorId, - Field.ephemeral: ephemeral, - Field.platform: platform, - Field.platformType: platformType, - Field.supported: supported, - }; + Field.id: id, + Field.name: name, + Field.category: category, + Field.emulator: emulator, + Field.emulatorId: emulatorId, + Field.ephemeral: ephemeral, + Field.platform: platform, + Field.platformType: platformType, + Field.supported: supported, + }; } /// UI settings for an editor's theme. @@ -436,12 +409,12 @@ class EditorTheme with Serializable { }); EditorTheme.fromJson(Map map) - : this( - isDarkMode: map[Field.isDarkMode] as bool, - backgroundColor: map[Field.backgroundColor] as String?, - foregroundColor: map[Field.foregroundColor] as String?, - fontSize: map[Field.fontSize] as int?, - ); + : this( + isDarkMode: map[Field.isDarkMode] as bool, + backgroundColor: map[Field.backgroundColor] as String?, + foregroundColor: map[Field.foregroundColor] as String?, + fontSize: map[Field.fontSize] as int?, + ); final bool isDarkMode; final String? backgroundColor; @@ -450,9 +423,9 @@ class EditorTheme with Serializable { @override Map toJson() => { - Field.isDarkMode: isDarkMode, - Field.backgroundColor: backgroundColor, - Field.foregroundColor: foregroundColor, - Field.fontSize: fontSize, - }; + Field.isDarkMode: isDarkMode, + Field.backgroundColor: backgroundColor, + Field.foregroundColor: foregroundColor, + Field.fontSize: fontSize, + }; } diff --git a/packages/devtools_app/lib/src/service/editor/editor_client.dart b/packages/devtools_app/lib/src/service/editor/editor_client.dart index b27cd581b46..ffd26998a24 100644 --- a/packages/devtools_app/lib/src/service/editor/editor_client.dart +++ b/packages/devtools_app/lib/src/service/editor/editor_client.dart @@ -60,16 +60,14 @@ class EditorClient extends DisposableController return; } - final info = isRegistered - ? ServiceRegistered( - service: service, - method: method, - capabilities: capabilities, - ) - : ServiceUnregistered( - service: service, - method: method, - ); + final info = + isRegistered + ? ServiceRegistered( + service: service, + method: method, + capabilities: capabilities, + ) + : ServiceUnregistered(service: service, method: method); _editorServiceChangedController.add(info); }), ); @@ -83,12 +81,15 @@ class EditorClient extends DisposableController // the rest. null => null, EditorEventKind.deviceAdded => DeviceAddedEvent.fromJson(data.data), - EditorEventKind.deviceRemoved => - DeviceRemovedEvent.fromJson(data.data), - EditorEventKind.deviceChanged => - DeviceChangedEvent.fromJson(data.data), - EditorEventKind.deviceSelected => - DeviceSelectedEvent.fromJson(data.data), + EditorEventKind.deviceRemoved => DeviceRemovedEvent.fromJson( + data.data, + ), + EditorEventKind.deviceChanged => DeviceChangedEvent.fromJson( + data.data, + ), + EditorEventKind.deviceSelected => DeviceSelectedEvent.fromJson( + data.data, + ), EditorEventKind.debugSessionStarted => DebugSessionStartedEvent.fromJson(data.data), EditorEventKind.debugSessionChanged => @@ -215,11 +216,7 @@ class EditorClient extends DisposableController EditorMethod method, { Map? params, }) { - return _dtd.call( - editorServiceName, - method.name, - params: params, - ); + return _dtd.call(editorServiceName, method.name, params: params); } } @@ -247,8 +244,5 @@ class ServiceRegistered extends ServiceRegistrationChange { /// Represents a service method that was unregistered. class ServiceUnregistered extends ServiceRegistrationChange { - ServiceUnregistered({ - required super.service, - required super.method, - }); + ServiceUnregistered({required super.service, required super.method}); } diff --git a/packages/devtools_app/lib/src/service/json_to_service_cache.dart b/packages/devtools_app/lib/src/service/json_to_service_cache.dart index 83eccc25a74..017af8008a5 100644 --- a/packages/devtools_app/lib/src/service/json_to_service_cache.dart +++ b/packages/devtools_app/lib/src/service/json_to_service_cache.dart @@ -20,10 +20,7 @@ class JsonToServiceCache { static final _kTrue = Instance( kind: InstanceKind.kBool, identityHashCode: -1, - classRef: ClassRef( - name: 'bool', - id: 'json-cache-bool', - ), + classRef: ClassRef(name: 'bool', id: 'json-cache-bool'), valueAsString: 'true', id: 'json-cache-true', ); @@ -31,10 +28,7 @@ class JsonToServiceCache { static final _kFalse = Instance( kind: InstanceKind.kBool, identityHashCode: -1, - classRef: ClassRef( - name: 'bool', - id: 'json-cache-bool', - ), + classRef: ClassRef(name: 'bool', id: 'json-cache-bool'), valueAsString: 'false', id: 'json-cache-false', ); @@ -42,10 +36,7 @@ class JsonToServiceCache { static final _kNull = Instance( kind: InstanceKind.kNull, identityHashCode: -1, - classRef: ClassRef( - name: 'Null', - id: 'json-cache-null-cls', - ), + classRef: ClassRef(name: 'Null', id: 'json-cache-null-cls'), id: 'json-cache-null', ); @@ -54,10 +45,7 @@ class JsonToServiceCache { id: 'json-cache-list-class', ); - static final _kMapClass = ClassRef( - name: 'Map', - id: 'json-cache-map-class', - ); + static final _kMapClass = ClassRef(name: 'Map', id: 'json-cache-map-class'); /// The current number of non-constant elements in the cache. @visibleForTesting @@ -71,11 +59,7 @@ class JsonToServiceCache { /// should be returned. If `offset` is provided, `count` must also be provided. /// The result will be an `Instance` containing `count` objects, starting from /// `offset`. - Instance? getObject({ - required String objectId, - int? offset, - int? count, - }) { + Instance? getObject({required String objectId, int? offset, int? count}) { final obj = _cache[objectId]; if (obj == null) return null; if (offset != null && count != null) { @@ -126,8 +110,9 @@ class JsonToServiceCache { case InstanceKind.kMap: final map = {}; for (final association in instance.associations ?? []) { - map[(association.key as Instance).valueAsString!] = - instanceToJson(association.value); + map[(association.key as Instance).valueAsString!] = instanceToJson( + association.value, + ); } return map; case InstanceKind.kList: @@ -209,9 +194,7 @@ class JsonToServiceCache { classRef: _kListClass, id: _nextId(), ); - list.elements = [ - for (final e in json) insertJsonObject(e), - ]; + list.elements = [for (final e in json) insertJsonObject(e)]; list.length = json.length; _cache[list.id!] = list; return list; @@ -232,10 +215,7 @@ class JsonToServiceCache { instance = Instance( kind: InstanceKind.kString, identityHashCode: -1, - classRef: ClassRef( - name: 'String', - id: 'json-cache-string', - ), + classRef: ClassRef(name: 'String', id: 'json-cache-string'), id: _nextId(), valueAsString: json, ); @@ -243,10 +223,7 @@ class JsonToServiceCache { instance = Instance( kind: InstanceKind.kInt, identityHashCode: json, - classRef: ClassRef( - name: 'int', - id: 'json-cache-int', - ), + classRef: ClassRef(name: 'int', id: 'json-cache-int'), valueAsString: json.toString(), id: _nextId(), ); @@ -254,10 +231,7 @@ class JsonToServiceCache { instance = Instance( kind: InstanceKind.kDouble, identityHashCode: -1, - classRef: ClassRef( - name: 'double', - id: 'json-cache-double', - ), + classRef: ClassRef(name: 'double', id: 'json-cache-double'), valueAsString: json.toString(), id: _nextId(), ); diff --git a/packages/devtools_app/lib/src/service/service_extension_widgets.dart b/packages/devtools_app/lib/src/service/service_extension_widgets.dart index 3394f16909b..9fdf6d56b6b 100644 --- a/packages/devtools_app/lib/src/service/service_extension_widgets.dart +++ b/packages/devtools_app/lib/src/service/service_extension_widgets.dart @@ -101,17 +101,15 @@ class _ServiceExtensionButtonGroupState // Track whether the extension is actually exposed by the VM. final listenable = serviceConnection - .serviceManager.serviceExtensionManager + .serviceManager + .serviceExtensionManager .hasServiceExtension(extensionName); extension.isAvailable = listenable.value; - addAutoDisposeListener( - listenable, - () { - setState(() { - extension.isAvailable = listenable.value; - }); - }, - ); + addAutoDisposeListener(listenable, () { + setState(() { + extension.isAvailable = listenable.value; + }); + }); } } @@ -164,12 +162,13 @@ class _ServiceExtensionButtonGroupState unawaited( serviceConnection.serviceManager.serviceExtensionManager .setServiceExtensionState( - extensionState.description.extension, - enabled: !wasSelected, - value: wasSelected - ? extensionState.description.disabledValue - : extensionState.description.enabledValue, - ), + extensionState.description.extension, + enabled: !wasSelected, + value: + wasSelected + ? extensionState.description.disabledValue + : extensionState.description.enabledValue, + ), ); }); } else { @@ -238,27 +237,27 @@ class HotReloadButton extends StatelessWidget { // reload directly on the VM service (e.g. for Dart CLI apps). ? _HotReloadScaffoldAction() : DevToolsTooltip( - message: _hotReloadTooltip, - child: _RegisteredServiceExtensionButton._( - serviceDescription: hotReload, - action: _callHotReload, - completedText: 'Hot reload completed.', - describeError: (error) => 'Unable to hot reload the app: $error', - ), - ); + message: _hotReloadTooltip, + child: _RegisteredServiceExtensionButton._( + serviceDescription: hotReload, + action: _callHotReload, + completedText: 'Hot reload completed.', + describeError: (error) => 'Unable to hot reload the app: $error', + ), + ); } } class _HotReloadScaffoldAction extends ScaffoldAction { _HotReloadScaffoldAction() - : super( - icon: hotReloadIcon, - tooltip: HotReloadButton._hotReloadTooltip, - onPressed: (context) { - ga.select(gac.devToolsMain, gac.hotReload); - _callHotReload(); - }, - ); + : super( + icon: hotReloadIcon, + tooltip: HotReloadButton._hotReloadTooltip, + onPressed: (context) { + ga.select(gac.devToolsMain, gac.hotReload); + _callHotReload(); + }, + ); } Future _callHotReload() { @@ -374,16 +373,17 @@ class _RegisteredServiceExtensionButtonState if (_hidden) return const SizedBox.shrink(); return InkWell( - onTap: () => unawaited( - invokeAndCatchErrors(() async { - final gaScreenName = widget.serviceDescription.gaScreenName; - final gaItem = widget.serviceDescription.gaItem; - if (gaScreenName != null && gaItem != null) { - ga.select(gaScreenName, gaItem); - } - await widget.action(); - }), - ), + onTap: + () => unawaited( + invokeAndCatchErrors(() async { + final gaScreenName = widget.serviceDescription.gaScreenName; + final gaItem = widget.serviceDescription.gaItem; + if (gaScreenName != null && gaItem != null) { + ga.select(gaScreenName, gaItem); + } + await widget.action(); + }), + ), child: Container( constraints: BoxConstraints.tightFor( width: actionWidgetSize, @@ -407,8 +407,8 @@ class StructuredErrorsToggle extends StatelessWidget { Widget build(BuildContext context) { return _ServiceExtensionToggle( service: structuredErrors, - describeError: (error) => - 'Failed to update structuredError settings: $error', + describeError: + (error) => 'Failed to update structuredError settings: $error', ); } } @@ -420,9 +420,7 @@ class _ServiceExtensionToggle extends ServiceExtensionWidget { const _ServiceExtensionToggle({ required this.service, required super.describeError, - }) : super( - completedText: null, - ); + }) : super(completedText: null); final ToggleableServiceExtensionDescription service; @override @@ -487,12 +485,13 @@ class _ServiceExtensionToggleState extends State<_ServiceExtensionToggle> invokeAndCatchErrors(() async { await serviceConnection.serviceManager.serviceExtensionManager .setServiceExtensionState( - widget.service.extension, - enabled: value, - value: value - ? widget.service.enabledValue - : widget.service.disabledValue, - ); + widget.service.extension, + enabled: value, + value: + value + ? widget.service.enabledValue + : widget.service.disabledValue, + ); }), ); } @@ -507,12 +506,10 @@ class ServiceExtensionCheckbox extends ServiceExtensionWidget { required this.serviceExtension, this.showDescription = true, }) : super( - completedText: null, - describeError: (error) => _errorMessage( - serviceExtension.extension, - error, - ), - ); + completedText: null, + describeError: + (error) => _errorMessage(serviceExtension.extension, error), + ); static String _errorMessage(String extensionName, Object? error) { return 'Failed to update $extensionName setting: $error'; @@ -562,16 +559,18 @@ class _ServiceExtensionCheckboxState extends State serviceConnection.serviceManager.serviceExtensionManager .waitForServiceExtensionAvailable(widget.serviceExtension.extension) .then((isServiceAvailable) { - if (isServiceAvailable) { - extensionAvailable.value = true; - final state = serviceConnection.serviceManager.serviceExtensionManager - .getServiceExtensionState(widget.serviceExtension.extension); - _setValueFromState(state.value); - addAutoDisposeListener(state, () { - _setValueFromState(state.value); - }); - } - }), + if (isServiceAvailable) { + extensionAvailable.value = true; + final state = serviceConnection + .serviceManager + .serviceExtensionManager + .getServiceExtensionState(widget.serviceExtension.extension); + _setValueFromState(state.value); + addAutoDisposeListener(state, () { + _setValueFromState(state.value); + }); + } + }), ); } @@ -593,9 +592,10 @@ class _ServiceExtensionCheckboxState extends State child: CheckboxSetting( notifier: value, title: widget.serviceExtension.title, - description: widget.showDescription - ? widget.serviceExtension.description - : null, + description: + widget.showDescription + ? widget.serviceExtension.description + : null, tooltip: widget.serviceExtension.tooltip, onChanged: _onChanged, enabled: available, @@ -627,12 +627,13 @@ class _ServiceExtensionCheckboxState extends State if (widget.serviceExtension.inverted) enabled = !enabled; await serviceConnection.serviceManager.serviceExtensionManager .setServiceExtensionState( - widget.serviceExtension.extension, - enabled: enabled, - value: enabled - ? widget.serviceExtension.enabledValue - : widget.serviceExtension.disabledValue, - ); + widget.serviceExtension.extension, + enabled: enabled, + value: + enabled + ? widget.serviceExtension.enabledValue + : widget.serviceExtension.disabledValue, + ); }), ); } @@ -1015,10 +1016,7 @@ class ServiceExtensionTooltip extends StatelessWidget { preferBelow: true, decoration: BoxDecoration( color: colorScheme.surface, - border: Border.all( - color: focusColor, - width: hoverCardBorderSize, - ), + border: Border.all(color: focusColor, width: hoverCardBorderSize), borderRadius: defaultBorderRadius, ), textStyle: theme.regularTextStyle.copyWith(color: colorScheme.onSurface), @@ -1058,9 +1056,7 @@ class ServiceExtensionRichTooltip extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - description.tooltip, - ), + Text(description.tooltip), if (description.documentationUrl != null && description.gaScreenName != null) Align( @@ -1086,15 +1082,13 @@ class ServiceExtensionIcon extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); - final color = extensionState.isSelected - ? theme.colorScheme.primary - : theme.colorScheme.onSurface; + final color = + extensionState.isSelected + ? theme.colorScheme.primary + : theme.colorScheme.onSurface; final description = extensionState.description; if (description.iconData != null) { - return Icon( - description.iconData, - color: color, - ); + return Icon(description.iconData, color: color); } return Image( image: AssetImage(extensionState.description.iconAsset!), diff --git a/packages/devtools_app/lib/src/service/service_extensions.dart b/packages/devtools_app/lib/src/service/service_extensions.dart index 4a32575a3d6..c0f3275e583 100644 --- a/packages/devtools_app/lib/src/service/service_extensions.dart +++ b/packages/devtools_app/lib/src/service/service_extensions.dart @@ -38,8 +38,9 @@ abstract class ServiceExtensionInterface { /// A subclass of [extensions.ToggleableServiceExtension] that includes metadata /// for displaying and interacting with a toggleable service extension in the /// DevTools UI. -class ToggleableServiceExtensionDescription extends extensions - .ToggleableServiceExtension implements ServiceExtensionInterface { +class ToggleableServiceExtensionDescription + extends extensions.ToggleableServiceExtension + implements ServiceExtensionInterface { ToggleableServiceExtensionDescription._({ required super.extension, required super.enabledValue, @@ -56,10 +57,10 @@ class ToggleableServiceExtensionDescription extends extensions this.iconAsset, this.iconData, this.shortTitle, - }) : displayValues = - [enabledValue, disabledValue].map((v) => v.toString()).toList(), - assert((iconAsset == null) != (iconData == null)), - assert((documentationUrl == null) == (gaDocsItem == null)); + }) : displayValues = + [enabledValue, disabledValue].map((v) => v.toString()).toList(), + assert((iconAsset == null) != (iconData == null)), + assert((documentationUrl == null) == (gaDocsItem == null)); factory ToggleableServiceExtensionDescription.from( extensions.ToggleableServiceExtension extension, { @@ -149,10 +150,10 @@ class ServiceExtensionDescription extends extensions.ServiceExtension this.documentationUrl, this.shortTitle, this.gaDocsItem, - }) : displayValues = - displayValues ?? values.map((v) => v.toString()).toList(), - assert((iconAsset == null) != (iconData == null)), - assert((documentationUrl == null) == (gaDocsItem == null)); + }) : displayValues = + displayValues ?? values.map((v) => v.toString()).toList(), + assert((iconAsset == null) != (iconData == null)), + assert((documentationUrl == null) == (gaDocsItem == null)); factory ServiceExtensionDescription.from( extensions.ServiceExtension extension, { @@ -294,8 +295,9 @@ final profileWidgetBuilds = ToggleableServiceExtensionDescription.from( gaDocsItem: gac.PerformanceDocs.trackWidgetBuildsDocs.name, ); -final profileUserWidgetBuilds = - ToggleableServiceExtensionDescription.from( +final profileUserWidgetBuilds = ToggleableServiceExtensionDescription< + bool +>.from( extensions.profileUserWidgetBuilds, title: 'Trace user-created widget builds', iconAsset: 'icons/trackwidget-white.png', @@ -308,31 +310,33 @@ final profileUserWidgetBuilds = final profileRenderObjectPaints = ToggleableServiceExtensionDescription.from( - extensions.profileRenderObjectPaints, - title: 'Trace paints', - iconData: Icons.format_paint, - gaScreenName: gac.performance, - gaItem: gac.PerformanceEvents.trackPaints.name, - description: 'Adds an event to the timeline for every RenderObject painted.', - tooltip: '', - documentationUrl: - 'https://docs.flutter.dev/tools/devtools/performance#track-paints', - gaDocsItem: gac.PerformanceDocs.trackPaintsDocs.name, -); + extensions.profileRenderObjectPaints, + title: 'Trace paints', + iconData: Icons.format_paint, + gaScreenName: gac.performance, + gaItem: gac.PerformanceEvents.trackPaints.name, + description: + 'Adds an event to the timeline for every RenderObject painted.', + tooltip: '', + documentationUrl: + 'https://docs.flutter.dev/tools/devtools/performance#track-paints', + gaDocsItem: gac.PerformanceDocs.trackPaintsDocs.name, + ); final profileRenderObjectLayouts = ToggleableServiceExtensionDescription.from( - extensions.profileRenderObjectLayouts, - title: 'Trace layouts', - iconData: Icons.auto_awesome_mosaic, - gaScreenName: gac.performance, - gaItem: gac.PerformanceEvents.trackLayouts.name, - description: 'Adds an event to the timeline for every RenderObject layout.', - tooltip: '', - documentationUrl: - 'https://docs.flutter.dev/tools/devtools/performance#track-layouts', - gaDocsItem: gac.PerformanceDocs.trackLayoutsDocs.name, -); + extensions.profileRenderObjectLayouts, + title: 'Trace layouts', + iconData: Icons.auto_awesome_mosaic, + gaScreenName: gac.performance, + gaItem: gac.PerformanceEvents.trackLayouts.name, + description: + 'Adds an event to the timeline for every RenderObject layout.', + tooltip: '', + documentationUrl: + 'https://docs.flutter.dev/tools/devtools/performance#track-layouts', + gaDocsItem: gac.PerformanceDocs.trackLayoutsDocs.name, + ); final repaintRainbow = ToggleableServiceExtensionDescription.from( extensions.repaintRainbow, @@ -405,8 +409,9 @@ option disabled, try to reduce the use of opacity effects in your app.''', gaDocsItem: gac.PerformanceDocs.disableOpacityLayersDocs.name, ); -final disablePhysicalShapeLayers = - ToggleableServiceExtensionDescription.from( +final disablePhysicalShapeLayers = ToggleableServiceExtensionDescription< + bool +>.from( extensions.disablePhysicalShapeLayers, title: 'Render Physical Shape layers', iconData: Icons.format_shapes, @@ -424,17 +429,18 @@ use of physical modeling effects in your app.''', final httpEnableTimelineLogging = ToggleableServiceExtensionDescription.from( - extensions.httpEnableTimelineLogging, - title: 'Whether HTTP timeline logging is enabled', - iconData: Icons.http, - gaScreenName: null, - gaItem: null, - tooltip: 'Toggle HTTP timeline logging', -); + extensions.httpEnableTimelineLogging, + title: 'Whether HTTP timeline logging is enabled', + iconData: Icons.http, + gaScreenName: null, + gaItem: null, + tooltip: 'Toggle HTTP timeline logging', + ); // Legacy extension to show the inspector and enable inspector select mode. -final toggleOnDeviceWidgetInspector = - ToggleableServiceExtensionDescription.from( +final toggleOnDeviceWidgetInspector = ToggleableServiceExtensionDescription< + bool +>.from( extensions.toggleOnDeviceWidgetInspector, // Technically this enables the on-device widget inspector but for older // versions of package:flutter it makes sense to describe this extension as @@ -473,13 +479,13 @@ final toggleSelectWidgetMode = ToggleableServiceExtensionDescription.from( /// mode is triggered. final enableOnDeviceInspector = ToggleableServiceExtensionDescription.from( - extensions.enableOnDeviceInspector, - title: 'Enable on-device inspector', - iconAsset: 'icons/general/locate@2x.png', - gaScreenName: gac.inspector, - gaItem: gac.enableOnDeviceInspector, - tooltip: 'Toggle on-device inspector', -); + extensions.enableOnDeviceInspector, + title: 'Enable on-device inspector', + iconAsset: 'icons/general/locate@2x.png', + gaScreenName: gac.inspector, + gaItem: gac.enableOnDeviceInspector, + tooltip: 'Toggle on-device inspector', + ); final structuredErrors = ToggleableServiceExtensionDescription.from( extensions.structuredErrors, @@ -503,8 +509,9 @@ summary of these counts using the Rebuild Stats tool.''', // TODO(https://github.com/flutter/website/issues/10666): link docs ); -final profilePlatformChannels = - ToggleableServiceExtensionDescription.from( +final profilePlatformChannels = ToggleableServiceExtensionDescription< + bool +>.from( extensions.profilePlatformChannels, title: 'Trace platform channels', iconAsset: 'icons/trackwidget-white.png', diff --git a/packages/devtools_app/lib/src/service/service_manager.dart b/packages/devtools_app/lib/src/service/service_manager.dart index 09d9d9cde03..bde8343972c 100644 --- a/packages/devtools_app/lib/src/service/service_manager.dart +++ b/packages/devtools_app/lib/src/service/service_manager.dart @@ -36,29 +36,30 @@ const defaultRefreshRate = 60.0; class ServiceConnectionManager { ServiceConnectionManager() { - serviceManager = ServiceManager() - ..registerLifecycleCallback( - ServiceManagerLifecycle.beforeOpenVmService, - _beforeOpenVmService, - ) - ..registerLifecycleCallback( - ServiceManagerLifecycle.afterOpenVmService, - _afterOpenVmService, - ) - ..registerLifecycleCallback( - ServiceManagerLifecycle.beforeCloseVmService, - _beforeCloseVmService, - ) - ..registerLifecycleCallback( - ServiceManagerLifecycle.afterCloseVmService, - _afterCloseVmService, - ) - ..registerOverride( - ServiceManagerOverride.initIsolates, - (service) async => await serviceManager.isolateManager.init( - serviceManager.vm?.isolatesForDevToolsMode() ?? [], - ), - ); + serviceManager = + ServiceManager() + ..registerLifecycleCallback( + ServiceManagerLifecycle.beforeOpenVmService, + _beforeOpenVmService, + ) + ..registerLifecycleCallback( + ServiceManagerLifecycle.afterOpenVmService, + _afterOpenVmService, + ) + ..registerLifecycleCallback( + ServiceManagerLifecycle.beforeCloseVmService, + _beforeCloseVmService, + ) + ..registerLifecycleCallback( + ServiceManagerLifecycle.afterCloseVmService, + _afterCloseVmService, + ) + ..registerOverride( + ServiceManagerOverride.initIsolates, + (service) async => await serviceManager.isolateManager.init( + serviceManager.vm?.isolatesForDevToolsMode() ?? [], + ), + ); } late final ServiceManager serviceManager; @@ -100,15 +101,17 @@ class ServiceConnectionManager { Future _afterOpenVmService(VmServiceWrapper? service) async { // Re-initialize isolates when VM developer mode is enabled/disabled to // display/hide system isolates. - preferences.vmDeveloperModeEnabled - .addListener(_handleVmDeveloperModeChanged); + preferences.vmDeveloperModeEnabled.addListener( + _handleVmDeveloperModeChanged, + ); // This needs to be called before calling // `ga.setupUserApplicationDimensions()` and before initializing // [_inspectorService], since both require access to an initialized // [serviceManager.connectedApp] object. - await serviceManager.connectedApp! - .initializeValues(onComplete: generateDevToolsTitle); + await serviceManager.connectedApp!.initializeValues( + onComplete: generateDevToolsTitle, + ); // Set up analytics dimensions for the connected app. ga.setupUserApplicationDimensions(); @@ -135,9 +138,10 @@ class ServiceConnectionManager { // Set [offlineController.previousConnectedApp] in case we need it for // viewing data after disconnect. This must be done before resetting the // rest of the service manager state. - final previousConnectedApp = serviceManager.connectedApp != null - ? OfflineConnectedApp.parse(serviceManager.connectedApp!.toJson()) - : null; + final previousConnectedApp = + serviceManager.connectedApp != null + ? OfflineConnectedApp.parse(serviceManager.connectedApp!.toJson()) + : null; offlineDataController.previousConnectedApp = previousConnectedApp; // This must be called before we close the VM service so that @@ -159,8 +163,9 @@ class ServiceConnectionManager { _inspectorService?.dispose(); _inspectorService = null; serviceTrafficLogger?.dispose(); - preferences.vmDeveloperModeEnabled - .removeListener(_handleVmDeveloperModeChanged); + preferences.vmDeveloperModeEnabled.removeListener( + _handleVmDeveloperModeChanged, + ); } Future _handleVmDeveloperModeChanged() async { @@ -169,8 +174,9 @@ class ServiceConnectionManager { final vmDeveloperModeEnabled = preferences.vmDeveloperModeEnabled.value; if (serviceManager.isolateManager.selectedIsolate.value!.isSystemIsolate! && !vmDeveloperModeEnabled) { - serviceManager.isolateManager - .selectIsolate(serviceManager.isolateManager.isolates.value.first); + serviceManager.isolateManager.selectIsolate( + serviceManager.isolateManager.isolates.value.first, + ); } await serviceManager.isolateManager.init(isolates); } @@ -185,12 +191,11 @@ class ServiceConnectionManager { /// /// Throws an Exception if no 'FlutterView' is present in this isolate. Future get flutterViewId async { - final flutterViewListResponse = - await serviceManager.callServiceExtensionOnMainIsolate( - registrations.flutterListViews, - ); - final views = (flutterViewListResponse.json!['views'] as List) - .cast>(); + final flutterViewListResponse = await serviceManager + .callServiceExtensionOnMainIsolate(registrations.flutterListViews); + final views = + (flutterViewListResponse.json!['views'] as List) + .cast>(); // Each isolate should only have one FlutterView. final flutterView = views.firstWhereOrNull( @@ -223,9 +228,7 @@ class ServiceConnectionManager { return await serviceManager.callServiceExtensionOnMainIsolate( registrations.flutterEngineEstimateRasterCache, - args: { - 'viewId': viewId, - }, + args: {'viewId': viewId}, ); } @@ -239,9 +242,7 @@ class ServiceConnectionManager { return await serviceManager.callServiceExtensionOnMainIsolate( registrations.renderFrameWithRasterStats, - args: { - 'viewId': viewId, - }, + args: {'viewId': viewId}, ); } @@ -254,11 +255,11 @@ class ServiceConnectionManager { const unknownRefreshRate = 0.0; final viewId = await flutterViewId; - final displayRefreshRateResponse = - await serviceManager.callServiceExtensionOnMainIsolate( - registrations.displayRefreshRate, - args: {'viewId': viewId}, - ); + final displayRefreshRateResponse = await serviceManager + .callServiceExtensionOnMainIsolate( + registrations.displayRefreshRate, + args: {'viewId': viewId}, + ); final double fps = displayRefreshRateResponse.json!['fps']; // The Flutter engine returns 0.0 if the refresh rate is unknown. Return @@ -281,10 +282,7 @@ class ServiceConnectionManager { registrations.dwdsSendEvent, args: { 'type': 'DevtoolsEvent', - 'payload': { - 'screen': screen, - 'action': action, - }, + 'payload': {'screen': screen, 'action': action}, }, ); } diff --git a/packages/devtools_app/lib/src/service/timeline_streams.dart b/packages/devtools_app/lib/src/service/timeline_streams.dart index d5e8469df55..d5d8bc3d595 100644 --- a/packages/devtools_app/lib/src/service/timeline_streams.dart +++ b/packages/devtools_app/lib/src/service/timeline_streams.dart @@ -36,14 +36,14 @@ class TimelineStreamManager with DisposerMixin { final _streamDescriptions = { dartTimelineStream: 'Events emitted from dart:developer Timeline APIs (including' - ' Flutter framework events)', + ' Flutter framework events)', embedderTimelineStream: 'Additional platform events (often emitted from the Flutter engine)', gcTimelineStream: 'Garbage collection', apiTimelineStream: 'Calls to the VM embedding API', compilerTimelineStream: 'Compiler phases (loading code, compilation, optimization,' - ' etc.)', + ' etc.)', compilerVerboseTimelineStream: 'More detailed compiler phases', debuggerTimelineStream: 'Debugger paused events', isolateTimelineStream: @@ -75,21 +75,19 @@ class TimelineStreamManager with DisposerMixin { final timelineFlags = await service!.getVMTimelineFlags(); _streams ..clear() - ..addEntries( - [ - for (final streamName in timelineFlags.availableStreams ?? []) - MapEntry( - streamName, - TimelineStream( - name: streamName, - description: _streamDescriptions[streamName] ?? '', - advanced: _advancedStreams.contains(streamName), - recorded: timelineFlags.recordedStreams?.contains(streamName) ?? - false, - ), + ..addEntries([ + for (final streamName in timelineFlags.availableStreams ?? []) + MapEntry( + streamName, + TimelineStream( + name: streamName, + description: _streamDescriptions[streamName] ?? '', + advanced: _advancedStreams.contains(streamName), + recorded: + timelineFlags.recordedStreams?.contains(streamName) ?? false, ), - ], - ); + ), + ]); } /// Handles events from the VM service 'TimelineEvent' stream to track updates @@ -120,10 +118,7 @@ class TimelineStreamManager with DisposerMixin { } } - void vmServiceOpened( - VmServiceWrapper service, - ConnectedApp connectedApp, - ) { + void vmServiceOpened(VmServiceWrapper service, ConnectedApp connectedApp) { cancelStreamSubscriptions(); _service = service; @@ -158,17 +153,19 @@ class TimelineStreamManager with DisposerMixin { /// Sends an update to the VM service that the new recorded value for [stream] /// should match [value]. Future updateTimelineStream(TimelineStream stream, bool value) async { - final recordedStreamNames = _streams.keys - .where((streamName) => _streams[streamName]!.recorded.value) - .toList(); + final recordedStreamNames = + _streams.keys + .where((streamName) => _streams[streamName]!.recorded.value) + .toList(); final alreadyBeingRecorded = recordedStreamNames.contains(stream.name); if (alreadyBeingRecorded && !value) { recordedStreamNames.remove(stream.name); } else if (!alreadyBeingRecorded && value) { recordedStreamNames.add(stream.name); } - await serviceConnection.serviceManager.service! - .setVMTimelineFlags(recordedStreamNames); + await serviceConnection.serviceManager.service!.setVMTimelineFlags( + recordedStreamNames, + ); } } diff --git a/packages/devtools_app/lib/src/service/vm_flags.dart b/packages/devtools_app/lib/src/service/vm_flags.dart index 72ef638c9c9..fb8da58b5ca 100644 --- a/packages/devtools_app/lib/src/service/vm_flags.dart +++ b/packages/devtools_app/lib/src/service/vm_flags.dart @@ -43,12 +43,13 @@ class VmFlagManager with DisposerMixin { if (event.kind == EventKind.kVMFlagUpdate) { if (_flagNotifiers.containsKey(event.flag)) { final currentFlag = _flagNotifiers[event.flag]!.value; - _flagNotifiers[event.flag]!.value = Flag.parse({ - 'name': currentFlag.name, - 'comment': currentFlag.comment, - 'modified': true, - 'valueAsString': event.newValue, - })!; + _flagNotifiers[event.flag]!.value = + Flag.parse({ + 'name': currentFlag.name, + 'comment': currentFlag.comment, + 'modified': true, + 'valueAsString': event.newValue, + })!; _flags.value = await service.getFlagList(); } } diff --git a/packages/devtools_app/lib/src/service/vm_service_logger.dart b/packages/devtools_app/lib/src/service/vm_service_logger.dart index dd3c240199d..d350e893422 100644 --- a/packages/devtools_app/lib/src/service/vm_service_logger.dart +++ b/packages/devtools_app/lib/src/service/vm_service_logger.dart @@ -33,10 +33,7 @@ class VmServiceTrafficLogger { final String? id = m['id']; messageBus.addEvent( - BusEvent( - eventName, - data: '⇨ #$id $method()\n$message', - ), + BusEvent(eventName, data: '⇨ #$id $method()\n$message'), ); } diff --git a/packages/devtools_app/lib/src/service/vm_service_wrapper.dart b/packages/devtools_app/lib/src/service/vm_service_wrapper.dart index d0aa6301cb8..c8a906f1f8f 100644 --- a/packages/devtools_app/lib/src/service/vm_service_wrapper.dart +++ b/packages/devtools_app/lib/src/service/vm_service_wrapper.dart @@ -85,11 +85,12 @@ class VmServiceWrapper extends VmService { Future get allFuturesCompleted => _allFuturesCompleter.future; - Completer _allFuturesCompleter = Completer() - // Mark the future as completed by default so if we don't track any - // futures but someone tries to wait on [allFuturesCompleted] they don't - // hang. The first tracked future will replace this with a new completer. - ..complete(true); + Completer _allFuturesCompleter = + Completer() + // Mark the future as completed by default so if we don't track any + // futures but someone tries to wait on [allFuturesCompleted] they don't + // hang. The first tracked future will replace this with a new completer. + ..complete(true); // A local cache of "fake" service objects. Used to convert JSON objects to // VM service response formats to be used with APIs that require them. @@ -163,12 +164,7 @@ class VmServiceWrapper extends VmService { if (cachedObj != null) { return Future.value(cachedObj); } - return super.getObject( - isolateId, - objectId, - offset: offset, - count: count, - ); + return super.getObject(isolateId, objectId, offset: offset, count: count); } Future getHeapSnapshotGraph( @@ -341,10 +337,7 @@ class VmServiceWrapper extends VmService { /// /// All logs from this run will have matching unique ids, so that they can /// be associated together in the logs. - Future _maybeLogWrappedFuture( - String name, - Future future, - ) async { + Future _maybeLogWrappedFuture(String name, Future future) async { // If the logger is not accepting FINE logs, then we won't be logging any // messages. So just return the [future] as-is. if (!_log.isLoggable(Level.FINE)) return future; @@ -356,10 +349,7 @@ class VmServiceWrapper extends VmService { _log.fine('[$logId]-wrapFuture($name,...): Succeeded'); return result; } catch (error) { - _log.severe( - '[$logId]-wrapFuture($name,...): Failed', - error, - ); + _log.severe('[$logId]-wrapFuture($name,...): Failed', error); rethrow; } } @@ -418,18 +408,14 @@ class VmServiceWrapper extends VmService { } /// Forces the VM to perform a full garbage collection. - Future collectAllGarbage() => _privateRpcInvoke( - 'collectAllGarbage', - parser: Success.parse, - ); + Future collectAllGarbage() => + _privateRpcInvoke('collectAllGarbage', parser: Success.parse); Future getReachableSize(String isolateId, String targetId) => _privateRpcInvoke( 'getReachableSize', isolateId: isolateId, - args: { - 'targetId': targetId, - }, + args: {'targetId': targetId}, parser: InstanceRef.parse, ); @@ -437,17 +423,15 @@ class VmServiceWrapper extends VmService { _privateRpcInvoke( 'getRetainedSize', isolateId: isolateId, - args: { - 'targetId': targetId, - }, + args: {'targetId': targetId}, parser: InstanceRef.parse, ); Future getObjectStore(String isolateId) => _privateRpcInvoke( - 'getObjectStore', - isolateId: isolateId, - parser: ObjectStore.parse, - ); + 'getObjectStore', + isolateId: isolateId, + parser: ObjectStore.parse, + ); Future dapVariablesRequest( dap.VariablesArguments args, @@ -455,9 +439,7 @@ class VmServiceWrapper extends VmService { final response = await _sendDapRequest('variables', args: args); if (response == null) return null; - return dap.VariablesResponseBody.fromJson( - response as Map, - ); + return dap.VariablesResponseBody.fromJson(response as Map); } Future dapScopesRequest( @@ -466,9 +448,7 @@ class VmServiceWrapper extends VmService { final response = await _sendDapRequest('scopes', args: args); if (response == null) return null; - return dap.ScopesResponseBody.fromJson( - response as Map, - ); + return dap.ScopesResponseBody.fromJson(response as Map); } Future dapStackTraceRequest( @@ -496,11 +476,7 @@ class VmServiceWrapper extends VmService { final response = await sendDapRequest( jsonEncode( - dap.Request( - command: command, - seq: _dapSeq++, - arguments: args, - ), + dap.Request(command: command, seq: _dapSeq++, arguments: args), ), ); diff --git a/packages/devtools_app/lib/src/shared/analytics/_analytics_stub.dart b/packages/devtools_app/lib/src/shared/analytics/_analytics_stub.dart index a6f5d1d6e17..6392dd76833 100644 --- a/packages/devtools_app/lib/src/shared/analytics/_analytics_stub.dart +++ b/packages/devtools_app/lib/src/shared/analytics/_analytics_stub.dart @@ -28,10 +28,7 @@ void initializeGA() {} void jsHookupListenerForGA() {} -void screen( - String screenName, [ - int value = 0, -]) { +void screen(String screenName, [int value = 0]) { _log.fine('Event: screen(screenName:$screenName, value:$value)'); } 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 1cd77d5fd33..51a623af304 100644 --- a/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart +++ b/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart @@ -67,7 +67,6 @@ extension type GtagEventDevTools._(JSObject _) implements GtagEvent { // NOTE: Do not reorder any of these. Order here must match the order in the // Google Analytics console. - String? user_app, // dimension1 (flutter or web) String? user_build, // dimension2 (debug or profile) String? user_platform, // dimension3 (android/ios/fuchsia/linux/mac/windows) @@ -76,11 +75,10 @@ extension type GtagEventDevTools._(JSObject _) implements GtagEvent { String? devtools_version, // dimension6 DevTools version # String? ide_launched, // dimension7 Devtools launched (CLI, VSCode, Android) String? - flutter_client_id, // dimension8 Flutter tool client_id (~/.flutter). + flutter_client_id, // dimension8 Flutter tool client_id (~/.flutter). String? is_external_build, // dimension9 External build or google3 String? is_embedded, // dimension10 Whether devtools is embedded String? g3_username, // dimension11 g3 username (null for external users) - // dimension12 IDE feature that launched Devtools // The following is a non-exhaustive list of possible values for this dimension: // "command" - VS Code command palette @@ -93,7 +91,6 @@ extension type GtagEventDevTools._(JSObject _) implements GtagEvent { // "languageStatus" - launched from the language status popout String? ide_launched_feature, String? is_wasm, // dimension13 whether DevTools is running with WASM. - // Performance screen metrics. See [PerformanceScreenMetrics]. int? ui_duration_micros, // metric1 int? raster_duration_micros, // metric2 @@ -148,53 +145,66 @@ extension type GtagEventDevTools._(JSObject _) implements GtagEvent { ide_launched_feature: ideLaunchedFeature, is_wasm: kIsWasm.toString(), // [PerformanceScreenMetrics] - ui_duration_micros: screenMetrics is PerformanceScreenMetrics - ? screenMetrics.uiDuration?.inMicroseconds - : null, - raster_duration_micros: screenMetrics is PerformanceScreenMetrics - ? screenMetrics.rasterDuration?.inMicroseconds - : null, + ui_duration_micros: + screenMetrics is PerformanceScreenMetrics + ? screenMetrics.uiDuration?.inMicroseconds + : null, + raster_duration_micros: + screenMetrics is PerformanceScreenMetrics + ? screenMetrics.rasterDuration?.inMicroseconds + : null, shader_compilation_duration_micros: screenMetrics is PerformanceScreenMetrics ? screenMetrics.shaderCompilationDuration?.inMicroseconds : null, - trace_event_count: screenMetrics is PerformanceScreenMetrics - ? screenMetrics.traceEventCount - : null, + trace_event_count: + screenMetrics is PerformanceScreenMetrics + ? screenMetrics.traceEventCount + : null, // [ProfilerScreenMetrics] - cpu_sample_count: screenMetrics is ProfilerScreenMetrics - ? screenMetrics.cpuSampleCount - : null, - cpu_stack_depth: screenMetrics is ProfilerScreenMetrics - ? screenMetrics.cpuStackDepth - : null, + cpu_sample_count: + screenMetrics is ProfilerScreenMetrics + ? screenMetrics.cpuSampleCount + : null, + cpu_stack_depth: + screenMetrics is ProfilerScreenMetrics + ? screenMetrics.cpuStackDepth + : null, // [MemoryScreenMetrics] - heap_diff_objects_before: screenMetrics is MemoryScreenMetrics - ? screenMetrics.heapDiffObjectsBefore - : null, - heap_diff_objects_after: screenMetrics is MemoryScreenMetrics - ? screenMetrics.heapDiffObjectsAfter - : null, - heap_objects_total: screenMetrics is MemoryScreenMetrics - ? screenMetrics.heapObjectsTotal - : null, + heap_diff_objects_before: + screenMetrics is MemoryScreenMetrics + ? screenMetrics.heapDiffObjectsBefore + : null, + heap_diff_objects_after: + screenMetrics is MemoryScreenMetrics + ? screenMetrics.heapDiffObjectsAfter + : null, + heap_objects_total: + screenMetrics is MemoryScreenMetrics + ? screenMetrics.heapObjectsTotal + : null, // [InspectorScreenMetrics] - root_set_count: screenMetrics is InspectorScreenMetrics - ? screenMetrics.rootSetCount - : null, - row_count: screenMetrics is InspectorScreenMetrics - ? screenMetrics.rowCount - : null, - inspector_tree_controller_id: screenMetrics is InspectorScreenMetrics - ? screenMetrics.inspectorTreeControllerId - : null, + root_set_count: + screenMetrics is InspectorScreenMetrics + ? screenMetrics.rootSetCount + : null, + row_count: + screenMetrics is InspectorScreenMetrics + ? screenMetrics.rowCount + : null, + inspector_tree_controller_id: + screenMetrics is InspectorScreenMetrics + ? screenMetrics.inspectorTreeControllerId + : null, // [DeepLinkScreenMetrics] - android_app_id: screenMetrics is DeepLinkScreenMetrics - ? screenMetrics.androidAppId - : null, - ios_bundle_id: screenMetrics is DeepLinkScreenMetrics - ? screenMetrics.iosBundleId - : null, + android_app_id: + screenMetrics is DeepLinkScreenMetrics + ? screenMetrics.androidAppId + : null, + ios_bundle_id: + screenMetrics is DeepLinkScreenMetrics + ? screenMetrics.iosBundleId + : null, // [InspectorScreenMetrics] is_v2_inspector: screenMetrics is InspectorScreenMetrics ? screenMetrics.isV2 : null, @@ -244,7 +254,6 @@ extension type GtagExceptionDevTools._(JSObject _) implements GtagException { // NOTE: Do not reorder any of these. Order here must match the order in the // Google Analytics console. - String? user_app, // dimension1 (flutter or web) String? user_build, // dimension2 (debug or profile) String? user_platform, // dimension3 (android or ios) @@ -256,7 +265,6 @@ extension type GtagExceptionDevTools._(JSObject _) implements GtagException { String? is_external_build, // dimension9 External build or google3 String? is_embedded, // dimension10 Whether devtools is embedded String? g3_username, // dimension11 g3 username (null for external users) - // dimension12 IDE feature that launched Devtools // The following is a non-exhaustive list of possible values for this dimension: // "command" - VS Code command palette @@ -269,7 +277,6 @@ extension type GtagExceptionDevTools._(JSObject _) implements GtagException { // "languageStatus" - launched from the language status popout String? ide_launched_feature, String? is_wasm, // dimension13 whether DevTools is running with WASM. - // Performance screen metrics. See [PerformanceScreenMetrics]. int? ui_duration_micros, // metric1 int? raster_duration_micros, // metric2 @@ -316,53 +323,66 @@ extension type GtagExceptionDevTools._(JSObject _) implements GtagException { ide_launched_feature: ideLaunchedFeature, is_wasm: kIsWasm.toString(), // [PerformanceScreenMetrics] - ui_duration_micros: screenMetrics is PerformanceScreenMetrics - ? screenMetrics.uiDuration?.inMicroseconds - : null, - raster_duration_micros: screenMetrics is PerformanceScreenMetrics - ? screenMetrics.rasterDuration?.inMicroseconds - : null, - trace_event_count: screenMetrics is PerformanceScreenMetrics - ? screenMetrics.traceEventCount - : null, + ui_duration_micros: + screenMetrics is PerformanceScreenMetrics + ? screenMetrics.uiDuration?.inMicroseconds + : null, + raster_duration_micros: + screenMetrics is PerformanceScreenMetrics + ? screenMetrics.rasterDuration?.inMicroseconds + : null, + trace_event_count: + screenMetrics is PerformanceScreenMetrics + ? screenMetrics.traceEventCount + : null, shader_compilation_duration_micros: screenMetrics is PerformanceScreenMetrics ? screenMetrics.shaderCompilationDuration?.inMicroseconds : null, // [ProfilerScreenMetrics] - cpu_sample_count: screenMetrics is ProfilerScreenMetrics - ? screenMetrics.cpuSampleCount - : null, - cpu_stack_depth: screenMetrics is ProfilerScreenMetrics - ? screenMetrics.cpuStackDepth - : null, + cpu_sample_count: + screenMetrics is ProfilerScreenMetrics + ? screenMetrics.cpuSampleCount + : null, + cpu_stack_depth: + screenMetrics is ProfilerScreenMetrics + ? screenMetrics.cpuStackDepth + : null, // [MemoryScreenMetrics] - heap_diff_objects_before: screenMetrics is MemoryScreenMetrics - ? screenMetrics.heapDiffObjectsBefore - : null, - heap_diff_objects_after: screenMetrics is MemoryScreenMetrics - ? screenMetrics.heapDiffObjectsAfter - : null, - heap_objects_total: screenMetrics is MemoryScreenMetrics - ? screenMetrics.heapObjectsTotal - : null, + heap_diff_objects_before: + screenMetrics is MemoryScreenMetrics + ? screenMetrics.heapDiffObjectsBefore + : null, + heap_diff_objects_after: + screenMetrics is MemoryScreenMetrics + ? screenMetrics.heapDiffObjectsAfter + : null, + heap_objects_total: + screenMetrics is MemoryScreenMetrics + ? screenMetrics.heapObjectsTotal + : null, // [InspectorScreenMetrics] - root_set_count: screenMetrics is InspectorScreenMetrics - ? screenMetrics.rootSetCount - : null, - row_count: screenMetrics is InspectorScreenMetrics - ? screenMetrics.rowCount - : null, - inspector_tree_controller_id: screenMetrics is InspectorScreenMetrics - ? screenMetrics.inspectorTreeControllerId - : null, + root_set_count: + screenMetrics is InspectorScreenMetrics + ? screenMetrics.rootSetCount + : null, + row_count: + screenMetrics is InspectorScreenMetrics + ? screenMetrics.rowCount + : null, + inspector_tree_controller_id: + screenMetrics is InspectorScreenMetrics + ? screenMetrics.inspectorTreeControllerId + : null, // [DeepLinkScreenMetrics] - android_app_id: screenMetrics is DeepLinkScreenMetrics - ? screenMetrics.androidAppId - : null, - ios_bundle_id: screenMetrics is DeepLinkScreenMetrics - ? screenMetrics.iosBundleId - : null, + android_app_id: + screenMetrics is DeepLinkScreenMetrics + ? screenMetrics.androidAppId + : null, + ios_bundle_id: + screenMetrics is DeepLinkScreenMetrics + ? screenMetrics.iosBundleId + : null, // [InspectorScreenMetrics] is_v2_inspector: screenMetrics is InspectorScreenMetrics ? screenMetrics.isV2 : null, @@ -462,10 +482,7 @@ final _timedOperationsInProgress = {}; // end marks. void timeStart(String screenName, String timedOperation) { final startTime = DateTime.now(); - final operationKey = _operationKey( - screenName, - timedOperation, - ); + final operationKey = _operationKey(screenName, timedOperation); _timedOperationsInProgress[operationKey] = startTime; } @@ -478,10 +495,7 @@ void timeEnd( ScreenAnalyticsMetrics Function()? screenMetricsProvider, }) { final endTime = DateTime.now(); - final operationKey = _operationKey( - screenName, - timedOperation, - ); + final operationKey = _operationKey(screenName, timedOperation); final startTime = _timedOperationsInProgress.remove(operationKey); assert(startTime != null); if (startTime == null) { @@ -504,10 +518,7 @@ void timeEnd( } void cancelTimingOperation(String screenName, String timedOperation) { - final operationKey = _operationKey( - screenName, - timedOperation, - ); + final operationKey = _operationKey(screenName, timedOperation); final operation = _timedOperationsInProgress.remove(operationKey); assert( operation != null, @@ -901,10 +912,7 @@ void legacyOnSetupAnalytics() { } void _sendEvent(GtagEventDevTools gtagEvent) { - GTag.event( - gtagEvent.screen!, - gaEventProvider: () => gtagEvent, - ); + GTag.event(gtagEvent.screen!, gaEventProvider: () => gtagEvent); final uaEvent = _uaEventFromGtagEvent(gtagEvent); unawaited(dtdManager.sendAnalyticsEvent(uaEvent)); } @@ -1040,7 +1048,8 @@ final class _DevToolsEventMetrics extends ua.CustomMetrics { final String? iosBundleId; @override - Map toMap() => ({ + Map toMap() => + ({ 'uiDurationMicros': uiDurationMicros, 'rasterDurationMicros': rasterDurationMicros, 'shaderCompilationDurationMicros': shaderCompilationDurationMicros, @@ -1056,6 +1065,5 @@ final class _DevToolsEventMetrics extends ua.CustomMetrics { 'isV2Inspector': isV2Inspector, 'androidAppId': androidAppId, 'iosBundleId': iosBundleId, - }..removeWhere((key, value) => value == null)) - .cast(); + }..removeWhere((key, value) => value == null)).cast(); } 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 50f0e21d6a3..2ed6ba5139e 100644 --- a/packages/devtools_app/lib/src/shared/analytics/analytics_controller.dart +++ b/packages/devtools_app/lib/src/shared/analytics/analytics_controller.dart @@ -23,7 +23,8 @@ Future get analyticsController async { var shouldShowConsentMessage = false; try { enabled = await ga.isAnalyticsEnabled(); - shouldShowConsentMessage = debugShowAnalyticsConsentMessage || + shouldShowConsentMessage = + debugShowAnalyticsConsentMessage || await ga.shouldShowAnalyticsConsentMessage(); } catch (_) { // Ignore issues if analytics could not be initialized. @@ -52,10 +53,10 @@ class AnalyticsController { this.legacyOnEnableAnalytics, this.legacyOnDisableAnalytics, this.legacyOnSetupAnalytics, - }) : analyticsEnabled = ValueNotifier(enabled), - _shouldPrompt = ValueNotifier( - shouldShowConsentMessage && consentMessage.isNotEmpty, - ) { + }) : analyticsEnabled = ValueNotifier(enabled), + _shouldPrompt = ValueNotifier( + shouldShowConsentMessage && consentMessage.isNotEmpty, + ) { if (_shouldPrompt.value) { unawaited(toggleAnalyticsEnabled(true)); } diff --git a/packages/devtools_app/lib/src/shared/analytics/constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants.dart index f673774c831..25d897e647d 100644 --- a/packages/devtools_app/lib/src/shared/analytics/constants.dart +++ b/packages/devtools_app/lib/src/shared/analytics/constants.dart @@ -91,11 +91,7 @@ final defaultDetailsViewToLayoutExplorer = final defaultDetailsViewToWidgetDetails = InspectorDetailsViewType.widgetDetailsTree.name; -enum HomeScreenEvents { - connectToApp, - connectToNewApp, - viewVmFlags, -} +enum HomeScreenEvents { connectToApp, connectToNewApp, viewVmFlags } // Logging UX actions: const structuredErrors = 'structuredErrors'; 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 1bf8aee7c2b..706d4c6c417 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 @@ -11,9 +11,7 @@ enum CpuProfilerEvents { cpuProfileFlameChartHelp, cpuProfileProcessingTime, openDataFile, - loadDataFromFile; + loadDataFromFile, } -enum CpuProfilerDocs { - profileGranularityDocs, -} +enum CpuProfilerDocs { profileGranularityDocs } diff --git a/packages/devtools_app/lib/src/shared/analytics/constants/_inspector_constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants/_inspector_constants.dart index 9b38c3fdfde..970d4b33561 100644 --- a/packages/devtools_app/lib/src/shared/analytics/constants/_inspector_constants.dart +++ b/packages/devtools_app/lib/src/shared/analytics/constants/_inspector_constants.dart @@ -5,6 +5,4 @@ part of '../constants.dart'; /// Events for opening documentation for the inspector tab. -enum InspectorDocs { - packageDirectoriesDocs; -} +enum InspectorDocs { packageDirectoriesDocs } diff --git a/packages/devtools_app/lib/src/shared/analytics/constants/_logging_constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants/_logging_constants.dart index 8c4f96fd6ac..a1560e80235 100644 --- a/packages/devtools_app/lib/src/shared/analytics/constants/_logging_constants.dart +++ b/packages/devtools_app/lib/src/shared/analytics/constants/_logging_constants.dart @@ -5,7 +5,4 @@ part of '../constants.dart'; /// Logging event constants specific for logging screen. -enum LoggingEvents { - changeRetentionLimit, - changeDetailsFormat, -} +enum LoggingEvents { changeRetentionLimit, changeDetailsFormat } diff --git a/packages/devtools_app/lib/src/shared/analytics/constants/_memory_constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants/_memory_constants.dart index df2188afb41..aa288a73c5d 100644 --- a/packages/devtools_app/lib/src/shared/analytics/constants/_memory_constants.dart +++ b/packages/devtools_app/lib/src/shared/analytics/constants/_memory_constants.dart @@ -5,10 +5,7 @@ part of '../constants.dart'; /// Analytics time constants specific for memory screen. -enum MemoryTime { - calculateDiff, - updateValues, -} +enum MemoryTime { calculateDiff, updateValues } enum MemoryEvents { browseRefLimit, diff --git a/packages/devtools_app/lib/src/shared/analytics/constants/_network_constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants/_network_constants.dart index 5ac4bbfa2cd..ea6f0f6df91 100644 --- a/packages/devtools_app/lib/src/shared/analytics/constants/_network_constants.dart +++ b/packages/devtools_app/lib/src/shared/analytics/constants/_network_constants.dart @@ -4,6 +4,4 @@ part of '../constants.dart'; -enum NetworkEvent { - downloadAsHar, -} +enum NetworkEvent { downloadAsHar } diff --git a/packages/devtools_app/lib/src/shared/analytics/metrics.dart b/packages/devtools_app/lib/src/shared/analytics/metrics.dart index 2b0e6b13acb..dc4ef4ed74b 100644 --- a/packages/devtools_app/lib/src/shared/analytics/metrics.dart +++ b/packages/devtools_app/lib/src/shared/analytics/metrics.dart @@ -95,10 +95,7 @@ class InspectorScreenMetrics extends ScreenAnalyticsMetrics { } class DeepLinkScreenMetrics extends ScreenAnalyticsMetrics { - DeepLinkScreenMetrics({ - this.androidAppId, - this.iosBundleId, - }); + DeepLinkScreenMetrics({this.androidAppId, this.iosBundleId}); /// The Android app id of the Flutter project. final String? androidAppId; diff --git a/packages/devtools_app/lib/src/shared/analytics/prompt.dart b/packages/devtools_app/lib/src/shared/analytics/prompt.dart index 2945f24dc8f..915063b2d52 100644 --- a/packages/devtools_app/lib/src/shared/analytics/prompt.dart +++ b/packages/devtools_app/lib/src/shared/analytics/prompt.dart @@ -43,18 +43,13 @@ class _AnalyticsPromptState extends State return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (showPrompt) child!, - Expanded(child: widget.child), - ], + children: [if (showPrompt) child!, Expanded(child: widget.child)], ); }, child: Card( shape: RoundedRectangleBorder( borderRadius: defaultBorderRadius, - side: BorderSide( - color: theme.focusColor, - ), + side: BorderSide(color: theme.focusColor), ), color: theme.canvasColor, margin: const EdgeInsets.only(bottom: denseSpacing), @@ -91,9 +86,9 @@ class _AnalyticsPromptState extends State Widget _analyticsDescription(ThemeData theme) { final consentMessageRegExpResults = - parseAnalyticsConsentMessage(controller.consentMessage) - ?.map((e) => adjustLineBreaks(e)) - .toList(); + parseAnalyticsConsentMessage( + controller.consentMessage, + )?.map((e) => adjustLineBreaks(e)).toList(); // When failing to parse the consent message, fallback to displaying the // consent message in its regular form. @@ -166,8 +161,10 @@ class _AnalyticsPromptState extends State @visibleForTesting List? parseAnalyticsConsentMessage(String consentMessage) { final results = []; - final pattern = - RegExp(r'^([\S\s]*)(https?:\/\/[^\s]+)(\)\.)$', multiLine: true); + final pattern = RegExp( + r'^([\S\s]*)(https?:\/\/[^\s]+)(\)\.)$', + multiLine: true, + ); final matches = pattern.allMatches(consentMessage); if (matches.isEmpty) { @@ -193,7 +190,9 @@ List? parseAnalyticsConsentMessage(String consentMessage) { /// match the width of the view. @visibleForTesting String adjustLineBreaks(String value) { - final pattern = - RegExp(r'(? m.key == message.key) - .isNotEmpty; + return _messagesForScreen( + message.screenId, + ).value.where((m) => m.key == message.key).isNotEmpty; } ListValueNotifier _messagesForScreen(String screenId) { @@ -126,14 +125,10 @@ class BannerMessages extends StatelessWidget { ValueListenableBuilder>( valueListenable: messagesForScreen, builder: (context, messages, _) { - return Column( - children: messages, - ); + return Column(children: messages); }, ), - Expanded( - child: screen.build(context), - ), + Expanded(child: screen.build(context)), ], ); } @@ -170,9 +165,10 @@ class BannerMessage extends StatelessWidget { final theme = Theme.of(context); final colorScheme = theme.colorScheme; return Card( - color: messageType == BannerMessageType.error - ? colorScheme.errorContainer - : colorScheme.warningContainer, + color: + messageType == BannerMessageType.error + ? colorScheme.errorContainer + : colorScheme.warningContainer, margin: const EdgeInsets.only(bottom: intermediateSpacing), child: Padding( padding: const EdgeInsets.symmetric( @@ -193,18 +189,20 @@ class BannerMessage extends StatelessWidget { ? Icons.error_outline : Icons.warning_amber_outlined, size: actionsIconSize, - color: messageType == BannerMessageType.error - ? colorScheme.onErrorContainer - : colorScheme.onWarningContainer, + color: + messageType == BannerMessageType.error + ? colorScheme.onErrorContainer + : colorScheme.onWarningContainer, ), ), Expanded( child: RichText( text: TextSpan( style: theme.regularTextStyle.copyWith( - color: messageType == BannerMessageType.error - ? colorScheme.onErrorContainer - : colorScheme.onWarningContainer, + color: + messageType == BannerMessageType.error + ? colorScheme.onErrorContainer + : colorScheme.onWarningContainer, ), children: textSpans, ), @@ -215,12 +213,13 @@ class BannerMessage extends StatelessWidget { icon: Icon( Icons.close, size: actionsIconSize, - color: messageType == BannerMessageType.error - ? colorScheme.onErrorContainer - : colorScheme.onWarningContainer, + color: + messageType == BannerMessageType.error + ? colorScheme.onErrorContainer + : colorScheme.onWarningContainer, ), - onPressed: () => - bannerMessages.removeMessage(this, dismiss: true), + onPressed: + () => bannerMessages.removeMessage(this, dismiss: true), ), ], ), @@ -236,9 +235,7 @@ class _BannerError extends BannerMessage { required Key super.key, required List super.textSpans, required super.screenId, - }) : super( - messageType: BannerMessageType.error, - ); + }) : super(messageType: BannerMessageType.error); } // TODO(kenz): add "Do not show this again" option to warnings. @@ -274,9 +271,7 @@ class DebugModePerformanceMessage { screenId: screenId, style: theme.warningMessageLinkStyle, ), - const TextSpan( - text: '.', - ), + const TextSpan(text: '.'), ], screenId: screenId, ); @@ -330,7 +325,8 @@ class ShaderJankMessage { key: Key('ShaderJankMessage - $screenId'), textSpans: [ TextSpan( - text: 'Shader compilation jank detected. $jankyFramesCount ' + text: + 'Shader compilation jank detected. $jankyFramesCount ' '${pluralize('frame', jankyFramesCount)} janked with a total of ' '$jankDurationText spent in shader compilation. To pre-compile ' 'shaders, see the instructions at ', @@ -349,7 +345,8 @@ class ShaderJankMessage { const TextSpan(text: '.'), if (serviceConnection.serviceManager.connectedApp!.isIosApp) ...[ const TextSpan( - text: '\n\nNote: this is a legacy solution with many pitfalls. ' + text: + '\n\nNote: this is a legacy solution with many pitfalls. ' 'Try ', ), GaLinkTextSpan( @@ -363,9 +360,7 @@ class ShaderJankMessage { context: context, style: theme.errorMessageLinkStyle, ), - const TextSpan( - text: ' instead!', - ), + const TextSpan(text: ' instead!'), ], ], screenId: screenId, @@ -375,7 +370,7 @@ class ShaderJankMessage { class HighCpuSamplingRateMessage { HighCpuSamplingRateMessage(this.screenId) - : key = Key('HighCpuSamplingRateMessage - $screenId'); + : key = Key('HighCpuSamplingRateMessage - $screenId'); final Key key; @@ -412,7 +407,7 @@ You are opting in to a high CPU sampling rate. This may affect the performance o class HttpLoggingEnabledMessage { HttpLoggingEnabledMessage(this.screenId) - : key = Key('HttpLoggingEnabledMessage - $screenId'); + : key = Key('HttpLoggingEnabledMessage - $screenId'); final Key key; @@ -431,15 +426,16 @@ HTTP traffic is being logged for debugging purposes. This may result in increase TextSpan( text: 'disabling http logging', style: theme.warningMessageLinkStyle, - recognizer: TapGestureRecognizer() - ..onTap = () async { - await http_service.toggleHttpRequestLogging(false).then((_) { - if (!http_service.httpLoggingEnabled) { - notificationService.push('Http logging disabled.'); - bannerMessages.removeMessage(message); - } - }); - }, + recognizer: + TapGestureRecognizer() + ..onTap = () async { + await http_service.toggleHttpRequestLogging(false).then((_) { + if (!http_service.httpLoggingEnabled) { + notificationService.push('Http logging disabled.'); + bannerMessages.removeMessage(message); + } + }); + }, ), const TextSpan( text: ' before profiling the memory of your application.', @@ -470,9 +466,7 @@ For the most accurate absolute memory stats, relaunch your application in ''', screenId: screenId, style: Theme.of(context).warningMessageLinkStyle, ), - const TextSpan( - text: '.', - ), + const TextSpan(text: '.'), ], screenId: screenId, ); @@ -522,10 +516,7 @@ void maybePushDebugModePerformanceMessage( } } -void maybePushDebugModeMemoryMessage( - BuildContext context, - String screenId, -) { +void maybePushDebugModeMemoryMessage(BuildContext context, String screenId) { if (offlineDataController.showingOfflineData.value) return; if (serviceConnection.serviceManager.connectedApp?.isDebugFlutterAppNow ?? false) { @@ -533,10 +524,7 @@ void maybePushDebugModeMemoryMessage( } } -void maybePushHttpLoggingMessage( - BuildContext context, - String screenId, -) { +void maybePushHttpLoggingMessage(BuildContext context, String screenId) { if (http_service.httpLoggingEnabled) { bannerMessages.addMessage( HttpLoggingEnabledMessage(screenId).build(context), @@ -555,14 +543,14 @@ void pushDebuggerIdeRecommendationMessage( extension BannerMessageThemeExtension on ThemeData { TextStyle get warningMessageLinkStyle => regularTextStyle.copyWith( - decoration: TextDecoration.underline, - color: colorScheme.onWarningContainerLink, - ); + decoration: TextDecoration.underline, + color: colorScheme.onWarningContainerLink, + ); TextStyle get errorMessageLinkStyle => regularTextStyle.copyWith( - decoration: TextDecoration.underline, - color: colorScheme.onErrorContainerLink, - ); + decoration: TextDecoration.underline, + color: colorScheme.onErrorContainerLink, + ); } GaLinkTextSpan _runInProfileModeTextSpan( diff --git a/packages/devtools_app/lib/src/shared/charts/chart.dart b/packages/devtools_app/lib/src/shared/charts/chart.dart index b0b70697c92..b283788fb58 100644 --- a/packages/devtools_app/lib/src/shared/charts/chart.dart +++ b/packages/devtools_app/lib/src/shared/charts/chart.dart @@ -40,11 +40,7 @@ void drawTranslate( } class Chart extends StatefulWidget { - Chart( - this.controller, { - super.key, - String title = '', - }) { + Chart(this.controller, {super.key, String title = ''}) { controller.title = title; } @@ -99,26 +95,28 @@ class ChartState extends State with AutoDisposeMixin { return RepaintBoundary( child: LayoutBuilder( // Inner container - builder: (_, constraints) => GestureDetector( - onTapDown: (TapDownDetails details) { - final xLocalPosition = details.localPosition.dx; - final timestampIndex = - controller.xCoordToTimestampIndex(xLocalPosition); - final timestamp = controller.xCoordToTimestamp(xLocalPosition); - controller.tapLocation.value = TapLocation( - details, - timestamp, - timestampIndex, - ); - }, - child: SizedBox( - width: constraints.widthConstraints().maxWidth, - height: constraints.widthConstraints().maxHeight, - child: CustomPaint( - painter: ChartPainter(controller, colorScheme), + builder: + (_, constraints) => GestureDetector( + onTapDown: (TapDownDetails details) { + final xLocalPosition = details.localPosition.dx; + final timestampIndex = controller.xCoordToTimestampIndex( + xLocalPosition, + ); + final timestamp = controller.xCoordToTimestamp(xLocalPosition); + controller.tapLocation.value = TapLocation( + details, + timestamp, + timestampIndex, + ); + }, + child: SizedBox( + width: constraints.widthConstraints().maxWidth, + height: constraints.widthConstraints().maxHeight, + child: CustomPaint( + painter: ChartPainter(controller, colorScheme), + ), + ), ), - ), - ), ), ); } @@ -128,11 +126,7 @@ class ChartState extends State with AutoDisposeMixin { /// is for stacked traces. If the Trace is stacked then yBase is the previous /// trace's Y position. If a trace is not stacked then yBase is always 0. class PointAndBase { - PointAndBase( - this.x, - this.y, { - double? yBase, - }) : base = yBase; + PointAndBase(this.x, this.y, {double? yBase}) : base = yBase; final double x; final double y; @@ -141,7 +135,7 @@ class PointAndBase { class ChartPainter extends CustomPainter { ChartPainter(this.chartController, this.colorScheme) { -// marginTopY = createText(chartController.title, 1.5).height + paddingY; + // marginTopY = createText(chartController.title, 1.5).height + paddingY; } final debugTrackPaintTime = false; @@ -160,9 +154,10 @@ class ChartPainter extends CustomPainter { // sampling 1 point per horizontal pixel. final startTime = DateTime.now(); - final axis = Paint() - ..strokeWidth = axisWidth - ..color = Colors.grey; + final axis = + Paint() + ..strokeWidth = axisWidth + ..color = Colors.grey; if (size != chartController.size) { chartController.size = size; @@ -174,22 +169,15 @@ class ChartPainter extends CustomPainter { chartController.xCanvasChart, chartController.yCanvasChart, (canavas) { - drawAxes( - canvas, - axis, - displayX: chartController.displayXAxis, - ); + drawAxes(canvas, axis, displayX: chartController.displayXAxis); }, ); final traces = chartController.traces; - final tracesDataIndex = List.generate( - traces.length, - (int index) { - final length = traces[index].data.length; - return length > 0 ? length - 1 : -1; - }, - ); + final tracesDataIndex = List.generate(traces.length, (int index) { + final length = traces[index].data.length; + return length > 0 ? length - 1 : -1; + }); /// Key is trace index and value is x,y point. final previousTracesData = {}; @@ -243,35 +231,89 @@ class ChartPainter extends CustomPainter { final yValue = (trace.stacked) ? stackedY + traceData.y : traceData.y; final xTimestamp = traceData.timestamp; - final xCanvasCoord = - chartController.timestampToXCanvasCoord(xTimestamp); + final xCanvasCoord = chartController.timestampToXCanvasCoord( + xTimestamp, + ); if (currentTimestamp == xTimestamp) { // Get ready to render on canvas. Remember old canvas state // and setup translations for x,y coordinates into the rendering // area of the chart. - drawTranslate( - canvas, - xTranslation, - yTranslation, - (canvas) { - final xCoord = xCanvasCoord; - final yCoord = chartController.yPositionToYCanvasCoord(yValue); - final hasMultipleExtensionEvents = - traceData is DataAggregate ? traceData.count > 1 : false; - - // Is the visible Y-axis max larger. - if (yValue > visibleYMax) { - visibleYMax = yValue; - } + drawTranslate(canvas, xTranslation, yTranslation, (canvas) { + final xCoord = xCanvasCoord; + final yCoord = chartController.yPositionToYCanvasCoord(yValue); + final hasMultipleExtensionEvents = + traceData is DataAggregate ? traceData.count > 1 : false; + + // Is the visible Y-axis max larger. + if (yValue > visibleYMax) { + visibleYMax = yValue; + } + + currentTracesData[index] = PointAndBase( + xCoord, + yCoord, + yBase: chartController.yPositionToYCanvasCoord(stackedY), + ); - currentTracesData[index] = PointAndBase( + if (trace.chartType == ChartType.symbol) { + assert(!trace.stacked); + drawSymbol( + canvas, + trace.characteristics, xCoord, yCoord, - yBase: chartController.yPositionToYCanvasCoord(stackedY), + hasMultipleExtensionEvents, + trace.symbolPath, ); + } else if (trace.chartType == ChartType.line) { + if (trace.characteristics.symbol == ChartSymbol.dashedLine) { + // TODO(terry): Collect all points and draw a dashed line using + // path_drawing package. + drawDashed( + canvas, + trace.characteristics, + xCoord, + yCoord, + chartController.tickWidth - 4, + ); + } else if (previousTracesData[index] != null) { + final previous = previousTracesData[index]!; + final current = currentTracesData[index]!; - if (trace.chartType == ChartType.symbol) { - assert(!trace.stacked); + // Stacked lines. + // Drawline from previous plotted point to new point. + drawConnectedLine( + canvas, + trace.characteristics, + xCoord, + yCoord, + previous.x, + previous.y, + ); + drawSymbol( + canvas, + trace.characteristics, + xCoord, + yCoord, + hasMultipleExtensionEvents, + trace.symbolPath, + ); + // TODO(terry): Honor z-order and also maybe path just on the traces e.g., + // fill from top of trace 0 to top of trace 1 don't origin + // from zero. + // Fill area between traces. + drawFillArea( + canvas, + trace.characteristics, + previous.x, + previous.y, + previous.base!, + current.x, + current.y, + current.base!, + ); + } else { + // Draw point drawSymbol( canvas, trace.characteristics, @@ -280,83 +322,17 @@ class ChartPainter extends CustomPainter { hasMultipleExtensionEvents, trace.symbolPath, ); - } else if (trace.chartType == ChartType.line) { - if (trace.characteristics.symbol == ChartSymbol.dashedLine) { - // TODO(terry): Collect all points and draw a dashed line using - // path_drawing package. - drawDashed( - canvas, - trace.characteristics, - xCoord, - yCoord, - chartController.tickWidth - 4, - ); - } else if (previousTracesData[index] != null) { - final previous = previousTracesData[index]!; - final current = currentTracesData[index]!; - - // Stacked lines. - // Drawline from previous plotted point to new point. - drawConnectedLine( - canvas, - trace.characteristics, - xCoord, - yCoord, - previous.x, - previous.y, - ); - drawSymbol( - canvas, - trace.characteristics, - xCoord, - yCoord, - hasMultipleExtensionEvents, - trace.symbolPath, - ); - // TODO(terry): Honor z-order and also maybe path just on the traces e.g., - // fill from top of trace 0 to top of trace 1 don't origin - // from zero. - // Fill area between traces. - drawFillArea( - canvas, - trace.characteristics, - previous.x, - previous.y, - previous.base!, - current.x, - current.y, - current.base!, - ); - } else { - // Draw point - drawSymbol( - canvas, - trace.characteristics, - xCoord, - yCoord, - hasMultipleExtensionEvents, - trace.symbolPath, - ); - } } - tracesDataIndex[index]--; - }, - ); + } + tracesDataIndex[index]--; + }); final tapLocation = chartController.tapLocation.value; if (tapLocation?.index == xTickIndex || tapLocation?.timestamp == currentTimestamp) { - drawTranslate( - canvas, - xTranslation, - yTranslation, - (canavas) { - drawSelection( - canvas, - xCanvasCoord, - ); - }, - ); + drawTranslate(canvas, xTranslation, yTranslation, (canavas) { + drawSelection(canvas, xCanvasCoord); + }); } } @@ -378,36 +354,30 @@ class ChartPainter extends CustomPainter { if (chartController.displayXAxis || chartController.displayXLabels) { // Y translation is below X-axis line. - drawTranslate( + drawTranslate(canvas, xTranslation, chartController.zeroYPosition + 1, ( canvas, - xTranslation, - chartController.zeroYPosition + 1, - (canvas) { - // Draw the X-axis labels. - for (final timestamp in chartController.labelTimestamps) { - final xCoord = chartController.timestampToXCanvasCoord(timestamp); - drawXTick(canvas, timestamp, xCoord, axis, displayTime: true); - } - }, - ); + ) { + // Draw the X-axis labels. + for (final timestamp in chartController.labelTimestamps) { + final xCoord = chartController.timestampToXCanvasCoord(timestamp); + drawXTick(canvas, timestamp, xCoord, axis, displayTime: true); + } + }); // X translation is left-most edge of chart widget. - drawTranslate( + drawTranslate(canvas, chartController.xCanvasChart, yTranslation, ( canvas, - chartController.xCanvasChart, - yTranslation, - (canvas) { - // Rescale Y-axis to max visible Y range. - chartController.resetYMaxValue(visibleYMax); - - // Draw Y-axis ticks and labels. - // TODO(terry): Optimization add a listener for Y-axis range changing - // only need to redraw Y-axis if the range changed. - if (chartController.displayYLabels) { - drawYTicks(canvas, chartController, axis); - } - }, - ); + ) { + // Rescale Y-axis to max visible Y range. + chartController.resetYMaxValue(visibleYMax); + + // Draw Y-axis ticks and labels. + // TODO(terry): Optimization add a listener for Y-axis range changing + // only need to redraw Y-axis if the range changed. + if (chartController.displayYLabels) { + drawYTicks(canvas, chartController, axis); + } + }); } drawTitle(canvas, size, chartController.title); @@ -457,11 +427,7 @@ class ChartPainter extends CustomPainter { // Left-side of chart if (displayY) { - canvas.drawLine( - const Offset(0, 0), - Offset(0, chartHeight), - axis, - ); + canvas.drawLine(const Offset(0, 0), Offset(0, chartHeight), axis); } // Bottom line of chart. @@ -475,9 +441,10 @@ class ChartPainter extends CustomPainter { } void drawSelection(Canvas canvas, double x) { - final paint = Paint() - ..strokeWidth = 2.0 - ..color = colorScheme.hoverSelectionBarColor; + final paint = + Paint() + ..strokeWidth = 2.0 + ..color = colorScheme.hoverSelectionBarColor; // Draw the vertical selection bar. canvas.drawLine( @@ -506,11 +473,7 @@ class ChartPainter extends CustomPainter { drawText(labelName, canvas, -chartController.xCanvasChart / 2, yCoord); // Draw horizontal tick 6 pixels from Y-axis line. - canvas.drawLine( - Offset(0, yCoord), - Offset(-6, yCoord), - axis, - ); + canvas.drawLine(Offset(0, yCoord), Offset(-6, yCoord), axis); } } @@ -580,10 +543,7 @@ class ChartPainter extends CustomPainter { final tp = createText(prettyTimestamp(timestamp), 1); tp.paint( canvas, - Offset( - xTickCoord - tp.width ~/ 2, - 15.0 - tp.height ~/ 2, - ), + Offset(xTickCoord - tp.width ~/ 2, 15.0 - tp.height ~/ 2), ); } } @@ -644,12 +604,14 @@ class ChartPainter extends CustomPainter { break; } - final paintFirst = Paint() - ..style = firstStyle - ..strokeWidth = characteristics.strokeWidth - ..color = aggregateEvents - ? characteristics.colorAggregate! - : characteristics.color; + final paintFirst = + Paint() + ..style = firstStyle + ..strokeWidth = characteristics.strokeWidth + ..color = + aggregateEvents + ? characteristics.colorAggregate! + : characteristics.color; switch (characteristics.symbol) { case ChartSymbol.dashedLine: @@ -670,13 +632,15 @@ class ChartPainter extends CustomPainter { canvas.drawCircle(Offset(x, y), characteristics.diameter, paintFirst); // Inner disc. - final paintSecond = Paint() - ..style = secondStyle - ..strokeWidth = 0 - // TODO(terry): Aggregate for concentric maybe needed someday. - ..color = aggregateEvents - ? characteristics.colorAggregate! - : characteristics.concentricCenterColor; + final paintSecond = + Paint() + ..style = secondStyle + ..strokeWidth = 0 + // TODO(terry): Aggregate for concentric maybe needed someday. + ..color = + aggregateEvents + ? characteristics.colorAggregate! + : characteristics.concentricCenterColor; canvas.drawCircle( Offset(x, y), characteristics.concentricCenterDiameter, @@ -691,10 +655,7 @@ class ChartPainter extends CustomPainter { case ChartSymbol.triangleDown: // Draw symbol centered on [x,y] point (*). final path = symbolPathToDraw!.shift( - Offset( - x - characteristics.width / 2, - y - characteristics.height / 2, - ), + Offset(x - characteristics.width / 2, y - characteristics.height / 2), ); canvas.drawPath(path, paintFirst); break; @@ -710,13 +671,7 @@ class ChartPainter extends CustomPainter { double tickWidth, ) { assert(characteristics.symbol == ChartSymbol.dashedLine); - drawLine( - canvas, - characteristics, - x, - y, - tickWidth, - ); + drawLine(canvas, characteristics, x, y, tickWidth); } void drawConnectedLine( @@ -727,10 +682,11 @@ class ChartPainter extends CustomPainter { double endX, double endY, ) { - final paint = Paint() - ..style = PaintingStyle.stroke - ..strokeWidth = characteristics.strokeWidth - ..color = characteristics.color; + final paint = + Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = characteristics.strokeWidth + ..color = characteristics.color; canvas.drawLine(Offset(startX, startY), Offset(endX, endY), paint); } @@ -742,10 +698,11 @@ class ChartPainter extends CustomPainter { double y, double tickWidth, ) { - final paint = Paint() - ..style = PaintingStyle.stroke - ..strokeWidth = characteristics.strokeWidth - ..color = characteristics.color; + final paint = + Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = characteristics.strokeWidth + ..color = characteristics.color; canvas.drawLine(Offset(x, y), Offset(x + tickWidth, y), paint); } @@ -762,16 +719,18 @@ class ChartPainter extends CustomPainter { double y1, double y1Bottom, ) { - final paint = Paint() - ..style = PaintingStyle.fill - ..strokeWidth = characteristics.strokeWidth - ..color = characteristics.color.withAlpha(140); - - final fillArea = Path() - ..moveTo(x0, y0) - ..lineTo(x1, y1) - ..lineTo(x1, y1Bottom) - ..lineTo(x0, y0Bottom); + final paint = + Paint() + ..style = PaintingStyle.fill + ..strokeWidth = characteristics.strokeWidth + ..color = characteristics.color.withAlpha(140); + + final fillArea = + Path() + ..moveTo(x0, y0) + ..lineTo(x1, y1) + ..lineTo(x1, y1Bottom) + ..lineTo(x0, y0Bottom); fillArea.close(); canvas.drawPath(fillArea, paint); diff --git a/packages/devtools_app/lib/src/shared/charts/chart_controller.dart b/packages/devtools_app/lib/src/shared/charts/chart_controller.dart index a8a1beae231..65078e178ac 100644 --- a/packages/devtools_app/lib/src/shared/charts/chart_controller.dart +++ b/packages/devtools_app/lib/src/shared/charts/chart_controller.dart @@ -223,19 +223,22 @@ class ChartController extends DisposableController final startOfLastNMinutes = // We need this cast to be able to return null if nothing is found. // ignore: unnecessary_cast - timestamps.reversed.firstWhereOrNull((timestamp) { - final currentDT = DateTime.fromMillisecondsSinceEpoch(timestamp); - final diff = lastDT.difference(currentDT); - if (diff.inMinutes >= duration.inMinutes) { - return true; - } - - return false; - }); - - final ticksVisible = startOfLastNMinutes != null - ? timestampsLength - timestamps.indexOf(startOfLastNMinutes) - : timestampsLength + 1; + timestamps + .reversed + .firstWhereOrNull((timestamp) { + final currentDT = DateTime.fromMillisecondsSinceEpoch(timestamp); + final diff = lastDT.difference(currentDT); + if (diff.inMinutes >= duration.inMinutes) { + return true; + } + + return false; + }); + + final ticksVisible = + startOfLastNMinutes != null + ? timestampsLength - timestamps.indexOf(startOfLastNMinutes) + : timestampsLength + 1; _tickWidth = canvasChartWidth / ticksVisible; } else { // No but lets scale x-axis based on the last two timestamps diffs we have. @@ -245,8 +248,9 @@ class ChartController extends DisposableController // Enough data (at least 2 points) to know how many ticks for the duration. if (length > 1) { final lastTS = DateTime.fromMillisecondsSinceEpoch(timestamps.last); - final previousTS = - DateTime.fromMillisecondsSinceEpoch(timestamps[length - 2]); + final previousTS = DateTime.fromMillisecondsSinceEpoch( + timestamps[length - 2], + ); final diffTS = lastTS.difference(previousTS); final ticksPerMinute = oneMinuteInMs / diffTS.inMilliseconds; final ticksVisible = ticksPerMinute * duration.inMinutes; @@ -358,10 +362,12 @@ class ChartController extends DisposableController if (labelTimestamps.isEmpty) return; final rightLabelTimestamp = labelTimestamps.last; - final rightMostLabelDT = - DateTime.fromMillisecondsSinceEpoch(rightLabelTimestamp); - final rightMostTimestampDT = - DateTime.fromMillisecondsSinceEpoch(timestamps.last); + final rightMostLabelDT = DateTime.fromMillisecondsSinceEpoch( + rightLabelTimestamp, + ); + final rightMostTimestampDT = DateTime.fromMillisecondsSinceEpoch( + timestamps.last, + ); final nSeconds = rightMostTimestampDT.difference(rightMostLabelDT).inSeconds; @@ -565,9 +571,9 @@ class TapLocation { /// but the multiple charts tied to the same timeline should be highlighted /// (selection point). TapLocation.copy(TapLocation original) - : tapDownDetails = null, - timestamp = original.timestamp, - index = original.index; + : tapDownDetails = null, + timestamp = original.timestamp, + index = original.index; final TapDownDetails? tapDownDetails; 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 5ec81c8343e..74792a6403b 100644 --- a/packages/devtools_app/lib/src/shared/charts/chart_trace.dart +++ b/packages/devtools_app/lib/src/shared/charts/chart_trace.dart @@ -197,12 +197,7 @@ class Trace { _symbolPath = Path(); _symbolPath!.addRect( - Rect.fromLTWH( - 0, - 0, - characteristics.width, - characteristics.height, - ), + Rect.fromLTWH(0, 0, characteristics.width, characteristics.height), ); _symbolPath!.close(); @@ -270,10 +265,7 @@ class TraceNotifier { TraceNotifier(); } -enum ChartType { - symbol, - line, -} +enum ChartType { symbol, line } enum ChartSymbol { ring, // Lined circle @@ -365,16 +357,17 @@ class AxisScale { // Fractional part of range. final fraction = range / pow(10, exponent); // Nice, rounded fraction. - final niceFraction = round - ? fraction.roundToDouble() - : switch (fraction) { - <= 1 => 1.0, - <= 2 => 2.0, - <= 3 => 3.0, - <= 5 => 5.0, - <= 7 => 7.0, - _ => 10.0, - }; + final niceFraction = + round + ? fraction.roundToDouble() + : switch (fraction) { + <= 1 => 1.0, + <= 2 => 2.0, + <= 3 => 3.0, + <= 5 => 5.0, + <= 7 => 7.0, + _ => 10.0, + }; return niceFraction * pow(10, exponent); } 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 721a1d9abd9..59005f5120d 100644 --- a/packages/devtools_app/lib/src/shared/charts/flame_chart.dart +++ b/packages/devtools_app/lib/src/shared/charts/flame_chart.dart @@ -98,8 +98,11 @@ abstract class FlameChart extends StatefulWidget { // performance improvements. Optionally we could also do something clever with // grouping nodes that are close together until they are zoomed in (quad tree // like implementation). -abstract class FlameChartState> extends State +abstract class FlameChartState< + T extends FlameChart, + V extends FlameChartDataMixin +> + extends State with AutoDisposeMixin, FlameChartColorMixin, TickerProviderStateMixin { int get rowOffsetForTopPadding => 2; @@ -156,14 +159,16 @@ abstract class FlameChartState - rows[index].nodes.isEmpty ? sectionSpacing : rowHeightWithPadding, + computeExtent: + (index) => + rows[index].nodes.isEmpty ? sectionSpacing : rowHeightWithPadding, computeLength: () => rows.length, ); @@ -299,12 +305,7 @@ abstract class FlameChartState= rows.length) { return -1; @@ -466,21 +469,13 @@ abstract class FlameChartState= 0 - ? fixedX * newZoom / previousZoom + widget.startInset - safeMouseHoverX - // We are in the fixed portion of the window - no need to transform. - : lastScrollOffset; + final newScrollOffset = + fixedX >= 0 + ? fixedX * newZoom / previousZoom + + widget.startInset - + safeMouseHoverX + // We are in the fixed portion of the window - no need to transform. + : lastScrollOffset; setState(() { currentZoom = zoomController.value; @@ -549,10 +547,7 @@ abstract class FlameChartState scrollToX( - double offset, { - bool jump = false, - }) async { + FutureOr scrollToX(double offset, {bool jump = false}) async { final target = offset.clamp( FlameChart.minScrollOffset, horizontalControllerGroup.position.maxScrollExtent, @@ -624,7 +619,8 @@ abstract class FlameChartState> } class ScrollingFlameChartRowState> - extends State> with AutoDisposeMixin { + extends State> + with AutoDisposeMixin { late final ScrollController scrollController; late final _ScrollingFlameChartRowExtentDelegate _extentDelegate; @@ -916,7 +913,7 @@ class FlameChartUtils { } else { padding = (node.rect.left - chartStartInset) * zoomForNode(node, chartZoom) + - chartStartInset; + chartStartInset; } // Floating point rounding error can result in slightly negative padding. return math.max(0.0, padding); @@ -943,11 +940,12 @@ class FlameChartUtils { // Node right with zoom and insets taken into consideration. final nodeRight = (node.rect.right - chartStartInset) * nodeZoom + chartStartInset; - final padding = nextNode == null - ? chartWidth - nodeRight - : ((nextNode.rect.left - chartStartInset) * nextNodeZoom + - chartStartInset) - - nodeRight; + final padding = + nextNode == null + ? chartWidth - nodeRight + : ((nextNode.rect.left - chartStartInset) * nextNodeZoom + + chartStartInset) - + nodeRight; // Floating point rounding error can result in slightly negative padding. return math.max(0.0, padding); } @@ -987,11 +985,7 @@ class FlameChartUtils { } class FlameChartSection { - FlameChartSection( - this.index, { - required this.startRow, - required this.endRow, - }); + FlameChartSection(this.index, {required this.startRow, required this.endRow}); final int index; @@ -1096,28 +1090,25 @@ class FlameChartNode> { activeSearchMatch: activeSearchMatch, colorScheme: theme.colorScheme, ), - child: zoomedWidth >= _minWidthForText - ? Text( - text, - textAlign: TextAlign.left, - overflow: TextOverflow.ellipsis, - style: theme.regularTextStyleWithColor( - _textColor( - selected: selected, - searchMatch: searchMatch, - activeSearchMatch: activeSearchMatch, - colorScheme: theme.colorScheme, + child: + zoomedWidth >= _minWidthForText + ? Text( + text, + textAlign: TextAlign.left, + overflow: TextOverflow.ellipsis, + style: theme.regularTextStyleWithColor( + _textColor( + selected: selected, + searchMatch: searchMatch, + activeSearchMatch: activeSearchMatch, + colorScheme: theme.colorScheme, + ), ), - ), - ) - : const SizedBox(), + ) + : const SizedBox(), ); return (hovered || !selectable) - ? DevToolsTooltip( - key: key, - message: data.tooltip, - child: node, - ) + ? DevToolsTooltip(key: key, message: data.tooltip, child: node) : node; } @@ -1156,8 +1147,10 @@ class FlameChartNode> { // small events that have padding. // // See https://github.com/flutter/devtools/issues/1503 for details. - final zoomedLeft = - math.max(0.0, (rect.left - chartStartInset) * zoom + chartStartInset); + final zoomedLeft = math.max( + 0.0, + (rect.left - chartStartInset) * zoom + chartStartInset, + ); final zoomedWidth = math.max(0.0, rect.width * zoom); return Rect.fromLTWH(zoomedLeft, rect.top, zoomedWidth, rect.height); } @@ -1353,9 +1346,11 @@ class TimelineGridPainter extends FlameChartPainter { final microsPerInterval = _microsPerInterval(intervalWidth); int timestampMicros = _startingTimestamp(intervalWidth, microsPerInterval); double lineX; - lineX = visible.left <= chartStartInset - ? chartStartInset - visible.left - : intervalWidth - ((visible.left - chartStartInset) % intervalWidth); + lineX = + visible.left <= chartStartInset + ? chartStartInset - visible.left + : intervalWidth - + ((visible.left - chartStartInset) % intervalWidth); while (lineX < constraints.maxWidth) { _paintTimestamp(canvas, timestampMicros, intervalWidth, lineX); @@ -1426,9 +1421,10 @@ class TimelineGridPainter extends FlameChartPainter { } int _startingTimestamp(double intervalWidth, int microsPerInterval) { - final startingIntervalIndex = horizontalScrollOffset < chartStartInset - ? 0 - : (horizontalScrollOffset - chartStartInset) ~/ intervalWidth + 1; + final startingIntervalIndex = + horizontalScrollOffset < chartStartInset + ? 0 + : (horizontalScrollOffset - chartStartInset) ~/ intervalWidth + 1; return startingIntervalIndex * microsPerInterval; } @@ -1448,13 +1444,13 @@ class TimelineGridPainter extends FlameChartPainter { @override int get hashCode => Object.hash( - zoom, - constraints, - flameChartWidth, - horizontalScrollOffset, - duration, - colorScheme, - ); + zoom, + constraints, + flameChartWidth, + horizontalScrollOffset, + duration, + colorScheme, + ); } class FlameChartHelpButton extends StatelessWidget { @@ -1502,18 +1498,9 @@ class FlameChartHelpButton extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ - Text( - 'WASD • ', - style: theme.fixedFontStyle, - ), - Text( - 'click + drag • ', - style: theme.fixedFontStyle, - ), - Text( - 'click + fling • ', - style: theme.fixedFontStyle, - ), + Text('WASD • ', style: theme.fixedFontStyle), + Text('click + drag • ', style: theme.fixedFontStyle), + Text('click + fling • ', style: theme.fixedFontStyle), ], ), ), @@ -1555,11 +1542,7 @@ class EmptyFlameChartRow extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - height: height, - width: width, - color: backgroundColor, - ); + return Container(height: height, width: width, color: backgroundColor); } } diff --git a/packages/devtools_app/lib/src/shared/charts/treemap.dart b/packages/devtools_app/lib/src/shared/charts/treemap.dart index efdf3ef332c..09d24fd1fdb 100644 --- a/packages/devtools_app/lib/src/shared/charts/treemap.dart +++ b/packages/devtools_app/lib/src/shared/charts/treemap.dart @@ -234,13 +234,15 @@ class _TreemapState extends State { final pivotAndList2Ratio = (pivotByteSize + list2Size) / totalByteSize; final pivotRatio = pivotByteSize / (pivotByteSize + list2Size); - final pivotWidth = isHorizontalRectangle - ? pivotAndList2Ratio * width - : pivotRatio * width; + final pivotWidth = + isHorizontalRectangle + ? pivotAndList2Ratio * width + : pivotRatio * width; - final pivotHeight = isHorizontalRectangle - ? pivotRatio * height - : pivotAndList2Ratio * height; + final pivotHeight = + isHorizontalRectangle + ? pivotRatio * height + : pivotAndList2Ratio * height; final pivotAspectRatio = pivotWidth / pivotHeight; @@ -267,12 +269,14 @@ class _TreemapState extends State { final pivotAndList2Ratio = (pivotByteSize + list2ByteSize) / totalByteSize; final pivotRatio = pivotByteSize / (pivotByteSize + list2ByteSize); - pivotBestWidth = isHorizontalRectangle - ? pivotAndList2Ratio * width - : pivotRatio * width; - pivotBestHeight = isHorizontalRectangle - ? pivotRatio * height - : pivotAndList2Ratio * height; + pivotBestWidth = + isHorizontalRectangle + ? pivotAndList2Ratio * width + : pivotRatio * width; + pivotBestHeight = + isHorizontalRectangle + ? pivotRatio * height + : pivotAndList2Ratio * height; } final positionedTreemaps = []; @@ -396,7 +400,8 @@ class _TreemapState extends State { // A key is required to force a rebuild of the tooltips for each cell. // Use tooltipMessage as the key to prevent rebuilds within a cell. key: Key(hoveredNode?.displayText() ?? ''), - richMessage: hoveredNode?.displayTextSpan( + richMessage: + hoveredNode?.displayTextSpan( defaultTextStyle: defaultTextStyle, ) ?? const TextSpan(text: ''), @@ -474,10 +479,7 @@ class _TreemapState extends State { Column buildTreemapFromRoot() { final rootNode = widget.rootNode!; - final child = _TreeMapCell( - treeMapHeight: widget.height, - node: rootNode, - ); + final child = _TreeMapCell(treeMapHeight: widget.height, node: rootNode); return Column( children: [ if (widget.isOutermostLevel) @@ -487,13 +489,14 @@ class _TreemapState extends State { onRootChangedCallback: widget.onRootChangedCallback, ), Expanded( - child: widget.isOutermostLevel - ? child - : _SelectableTreemapNode( - node: rootNode, - onRootChangedCallback: widget.onRootChangedCallback, - child: child, - ), + child: + widget.isOutermostLevel + ? child + : _SelectableTreemapNode( + node: rootNode, + onRootChangedCallback: widget.onRootChangedCallback, + child: child, + ), ), ], ); @@ -503,10 +506,7 @@ class _TreemapState extends State { /// a cell in [positionedCells]. /// /// If so, saves the matching hoveredNode. - void _onHover( - PointerHoverEvent event, - List positionedCells, - ) { + void _onHover(PointerHoverEvent event, List positionedCells) { final x = event.localPosition.dx; final y = event.localPosition.dy; final touchPoint = Offset(x, y); @@ -524,10 +524,7 @@ class _TreemapState extends State { } class _TreeMapCell extends StatelessWidget { - const _TreeMapCell({ - required this.treeMapHeight, - required this.node, - }); + const _TreeMapCell({required this.treeMapHeight, required this.node}); final double treeMapHeight; final TreemapNode node; @@ -540,13 +537,14 @@ class _TreeMapCell extends StatelessWidget { border: Border.all(color: Colors.black87), ), child: Center( - child: treeMapHeight > Treemap.minHeightToDisplayCellText - ? _NameAndSizeText( - node: node, - color: node.showDiff ? Colors.white : Colors.black, - singleLine: false, - ) - : const SizedBox(), + child: + treeMapHeight > Treemap.minHeightToDisplayCellText + ? _NameAndSizeText( + node: node, + color: node.showDiff ? Colors.white : Colors.black, + singleLine: false, + ) + : const SizedBox(), ), ); } @@ -577,9 +575,7 @@ class _TitleBar extends StatelessWidget { child: Container( height: Treemap.treeMapHeaderHeight, width: double.infinity, - decoration: BoxDecoration( - border: Border.all(color: Colors.black87), - ), + decoration: BoxDecoration(border: Border.all(color: Colors.black87)), child: _NameAndSizeText( node: rootNode, color: Theme.of(context).colorScheme.onSurface, @@ -635,9 +631,10 @@ class _BreadcrumbNavigator extends StatelessWidget { builder: (context, index) { final node = pathFromRoot[index]; return Breadcrumb( - text: index < pathFromRoot.length - 1 - ? node.name - : node.displayText(), + text: + index < pathFromRoot.length - 1 + ? node.name + : node.displayText(), isRoot: index == 0, onPressed: () => onRootChangedCallback(node), ); @@ -831,11 +828,11 @@ class PositionedCell extends Positioned { required this.node, required super.child, }) : super( - left: rect.left, - top: rect.top, - width: rect.width, - height: rect.height, - ); + left: rect.left, + top: rect.top, + width: rect.width, + height: rect.height, + ); final Rect rect; @@ -873,9 +870,10 @@ class MultiCellPainter extends CustomPainter { rectPaint.color = node.displayColor; canvas.drawRect(bounds, rectPaint); - final borderPaint = Paint() - ..color = Colors.black45 - ..style = PaintingStyle.stroke; + final borderPaint = + Paint() + ..color = Colors.black45 + ..style = PaintingStyle.stroke; canvas.drawRect(bounds, borderPaint); if (positionedCell.width! > Treemap.minWidthToDisplayCellText && @@ -894,10 +892,7 @@ class MultiCellPainter extends CustomPainter { positionedCell.left! + bounds.width / 2 - textPainter.width / 2; final centerY = positionedCell.top! + bounds.height / 2 - textPainter.height / 2; - textPainter.paint( - canvas, - Offset(centerX, centerY), - ); + textPainter.paint(canvas, Offset(centerX, centerY)); } } diff --git a/packages/devtools_app/lib/src/shared/collapsible_mixin.dart b/packages/devtools_app/lib/src/shared/collapsible_mixin.dart index 98074c19f0e..db907bdcd76 100644 --- a/packages/devtools_app/lib/src/shared/collapsible_mixin.dart +++ b/packages/devtools_app/lib/src/shared/collapsible_mixin.dart @@ -40,8 +40,10 @@ mixin CollapsibleAnimationMixin super.initState(); expandController = defaultAnimationController(this); expandCurve = defaultCurvedAnimation(expandController); - expandArrowAnimation = - Tween(begin: 0.75, end: 1.0).animate(expandCurve); + expandArrowAnimation = Tween( + begin: 0.75, + end: 1.0, + ).animate(expandCurve); if (isExpanded) { expandController.value = 1.0; } diff --git a/packages/devtools_app/lib/src/shared/common_widgets.dart b/packages/devtools_app/lib/src/shared/common_widgets.dart index 1747c044b70..da2f68cb553 100644 --- a/packages/devtools_app/lib/src/shared/common_widgets.dart +++ b/packages/devtools_app/lib/src/shared/common_widgets.dart @@ -45,9 +45,10 @@ TextStyle semibold(TextStyle style) => TextStyle primaryColor(TextStyle style, BuildContext context) { final theme = Theme.of(context); return style.copyWith( - color: (theme.brightness == Brightness.light) - ? theme.primaryColor - : theme.colorScheme.secondary, + color: + (theme.brightness == Brightness.light) + ? theme.primaryColor + : theme.colorScheme.secondary, fontWeight: FontWeight.w400, ); } @@ -80,13 +81,14 @@ class GaDevToolsButton extends DevToolsButton { super.outlined, super.tooltipPadding, }) : super( - onPressed: onPressed != null - ? () { - ga.select(gaScreen, gaSelection); - onPressed(); - } - : null, - ); + onPressed: + onPressed != null + ? () { + ga.select(gaScreen, gaSelection); + onPressed(); + } + : null, + ); factory GaDevToolsButton.iconOnly({ required IconData icon, @@ -117,10 +119,7 @@ class PauseButton extends GaDevToolsButton { super.outlined = true, super.minScreenWidthForTextBeforeScaling, bool iconOnly = false, - }) : super( - label: iconOnly ? null : 'Pause', - icon: Icons.pause, - ); + }) : super(label: iconOnly ? null : 'Pause', icon: Icons.pause); } class ResumeButton extends GaDevToolsButton { @@ -133,10 +132,7 @@ class ResumeButton extends GaDevToolsButton { super.outlined = true, super.minScreenWidthForTextBeforeScaling, bool iconOnly = false, - }) : super( - label: iconOnly ? null : 'Resume', - icon: Icons.play_arrow, - ); + }) : super(label: iconOnly ? null : 'Resume', icon: Icons.play_arrow); } /// A button that groups pause and resume controls and automatically manages @@ -245,11 +241,11 @@ class StartStopRecordingButton extends GaDevToolsButton { Color? colorOverride, String? labelOverride, }) : super( - icon: _icon(recording), - label: labelOverride ?? _label(recording), - color: colorOverride ?? _color(recording), - tooltip: tooltipOverride ?? _tooltip(recording), - ); + icon: _icon(recording), + label: labelOverride ?? _label(recording), + color: colorOverride ?? _color(recording), + tooltip: tooltipOverride ?? _tooltip(recording), + ); static IconData _icon(bool recording) => recording ? Icons.stop : Icons.fiber_manual_record; @@ -283,10 +279,10 @@ class RecordButton extends GaDevToolsButton { super.tooltip = 'Start recording', String? labelOverride, }) : super( - onPressed: recording ? null : onPressed, - icon: Icons.fiber_manual_record, - label: labelOverride ?? 'Record', - ); + onPressed: recording ? null : onPressed, + icon: Icons.fiber_manual_record, + label: labelOverride ?? 'Record', + ); } /// Button to stop recording data. @@ -305,10 +301,10 @@ class StopRecordingButton extends GaDevToolsButton { super.minScreenWidthForTextBeforeScaling, super.tooltip = 'Stop recording', }) : super( - onPressed: !recording ? null : onPressed, - icon: Icons.stop, - label: 'Stop', - ); + onPressed: !recording ? null : onPressed, + icon: Icons.stop, + label: 'Stop', + ); } class SettingsOutlinedButton extends GaDevToolsButton { @@ -328,10 +324,7 @@ class HelpButton extends GaDevToolsButton { required super.gaSelection, required super.onPressed, super.outlined = true, - }) : super( - icon: Icons.help_outline, - tooltip: 'Help', - ); + }) : super(icon: Icons.help_outline, tooltip: 'Help'); } class ExpandAllButton extends StatelessWidget { @@ -510,9 +503,7 @@ class ProcessingInfo extends StatelessWidget { const SizedBox(height: defaultSpacing), SizedBox( width: 200.0, - child: LinearProgressIndicator( - value: progressValue, - ), + child: LinearProgressIndicator(value: progressValue), ), ], ), @@ -570,9 +561,7 @@ class OfflineAwareControls extends StatelessWidget { padding: const EdgeInsets.only(right: defaultSpacing), child: ExitOfflineButton(gaScreen: gaScreen), ), - Expanded( - child: controlsBuilder(offline), - ), + Expanded(child: controlsBuilder(offline)), ], ); }, @@ -694,10 +683,7 @@ class SmallAction extends StatelessWidget { return tooltip == null ? button - : DevToolsTooltip( - message: tooltip, - child: button, - ); + : DevToolsTooltip(message: tooltip, child: button); } } @@ -711,9 +697,9 @@ abstract class ScaffoldAction extends StatelessWidget { this.iconAsset, this.color, }) : assert( - (icon == null) != (iconAsset == null), - 'Exactly one of icon and iconAsset must be specified.', - ); + (icon == null) != (iconAsset == null), + 'Exactly one of icon and iconAsset must be specified.', + ); /// The icon to use for this scaffold action. /// @@ -806,10 +792,7 @@ class OutlinedRowGroup extends StatelessWidget { ), ]); } - return Row( - mainAxisSize: MainAxisSize.min, - children: childrenWithOutlines, - ); + return Row(mainAxisSize: MainAxisSize.min, children: childrenWithOutlines); } } @@ -828,9 +811,9 @@ class ThickDivider extends StatelessWidget { } BoxDecoration roundedBorderDecoration(BuildContext context) => BoxDecoration( - border: Border.all(color: Theme.of(context).focusColor), - borderRadius: defaultBorderRadius, - ); + border: Border.all(color: Theme.of(context).focusColor), + borderRadius: defaultBorderRadius, +); class LeftBorder extends StatelessWidget { const LeftBorder({super.key, this.child}); @@ -839,8 +822,9 @@ class LeftBorder extends StatelessWidget { @override Widget build(BuildContext context) { - final leftBorder = - Border(left: BorderSide(color: Theme.of(context).focusColor)); + final leftBorder = Border( + left: BorderSide(color: Theme.of(context).focusColor), + ); return Container( decoration: BoxDecoration(border: leftBorder), @@ -858,11 +842,8 @@ final goldenRatio = 1 + sqrt(5) / 2; /// /// Only one of [message] or [richMessage] can be specified. class CenteredMessage extends StatelessWidget { - const CenteredMessage({ - this.message, - this.richMessage, - super.key, - }) : assert((message == null) != (richMessage == null)); + const CenteredMessage({this.message, this.richMessage, super.key}) + : assert((message == null) != (richMessage == null)); final String? message; @@ -878,9 +859,7 @@ class CenteredMessage extends StatelessWidget { style: Theme.of(context).regularTextStyle, ); } else { - child = RichText( - text: TextSpan(children: richMessage), - ); + child = RichText(text: TextSpan(children: richMessage)); } return Center(child: child); } @@ -893,17 +872,11 @@ class CenteredCircularProgressIndicator extends StatelessWidget { @override Widget build(BuildContext context) { - const indicator = Center( - child: CircularProgressIndicator(), - ); + const indicator = Center(child: CircularProgressIndicator()); if (size == null) return indicator; - return SizedBox( - width: size, - height: size, - child: indicator, - ); + return SizedBox(width: size, height: size, child: indicator); } } @@ -1103,19 +1076,13 @@ class TextViewer extends StatelessWidget { } else { displayText = text; } - return SelectableText( - displayText, - style: style, - ); + return SelectableText(displayText, style: style); } } class JsonViewer extends StatefulWidget { - JsonViewer({ - super.key, - required this.encodedJson, - this.scrollable = true, - }) : assert(encodedJson.isNotEmpty); + JsonViewer({super.key, required this.encodedJson, this.scrollable = true}) + : assert(encodedJson.isNotEmpty); final String encodedJson; final bool scrollable; @@ -1129,9 +1096,7 @@ class _JsonViewerState extends State { late DartObjectNode variable; static const jsonEncoder = JsonEncoder.withIndent(' '); - Future _buildAndExpand( - DartObjectNode variable, - ) async { + Future _buildAndExpand(DartObjectNode variable) async { // Build the root node await buildVariablesTree(variable); // Build the contents of all children @@ -1183,8 +1148,9 @@ class _JsonViewerState extends State { super.dispose(); // Remove the JSON object from the fake service cache to avoid holding on // to large objects indefinitely. - serviceConnection.serviceManager.service!.fakeServiceCache - .removeJsonObject(variable.value as Instance); + serviceConnection.serviceManager.service!.fakeServiceCache.removeJsonObject( + variable.value as Instance, + ); } @override @@ -1212,15 +1178,10 @@ class _JsonViewerState extends State { }, ); if (widget.scrollable) { - child = SingleChildScrollView( - child: child, - ); + child = SingleChildScrollView(child: child); } return SelectionArea( - child: Padding( - padding: const EdgeInsets.all(denseSpacing), - child: child, - ), + child: Padding(padding: const EdgeInsets.all(denseSpacing), child: child), ); } } @@ -1254,10 +1215,7 @@ class MoreInfoLink extends StatelessWidget { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, children: [ - Text( - 'More info', - style: theme.linkTextStyle, - ), + Text('More info', style: theme.linkTextStyle), const SizedBox(width: densePadding), Icon( Icons.launch, @@ -1295,11 +1253,7 @@ class LinkIconLabel extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - Icon( - icon, - size: defaultIconSize, - color: color, - ), + Icon(icon, size: defaultIconSize, color: color), const SizedBox(width: densePadding), Padding( padding: const EdgeInsets.only(bottom: densePadding), @@ -1329,17 +1283,14 @@ class GaLinkTextSpan extends LinkTextSpan { required super.context, TextStyle? style, }) : super( - link: link, - onTap: () { - if (link.gaScreenName != null && - link.gaSelectedItemDescription != null) { - ga.select( - link.gaScreenName!, - link.gaSelectedItemDescription!, - ); - } - }, - ); + link: link, + onTap: () { + if (link.gaScreenName != null && + link.gaSelectedItemDescription != null) { + ga.select(link.gaScreenName!, link.gaSelectedItemDescription!); + } + }, + ); } class GaLink extends Link { @@ -1355,11 +1306,7 @@ class GaLink extends Link { } class Legend extends StatelessWidget { - const Legend({ - super.key, - required this.entries, - this.dense = false, - }); + const Legend({super.key, required this.entries, this.dense = false}); double get legendSquareSize => dense ? scaleByFontFactor(12.0) : scaleByFontFactor(16.0); @@ -1372,13 +1319,7 @@ class Legend extends StatelessWidget { Widget build(BuildContext context) { final textStyle = dense ? Theme.of(context).legendTextStyle : null; final legendItems = entries - .map( - (entry) => _legendItem( - entry.description, - entry.color, - textStyle, - ), - ) + .map((entry) => _legendItem(entry.description, entry.color, textStyle)) .toList() .joinWith(const SizedBox(height: denseRowSpacing)); return Column( @@ -1396,10 +1337,7 @@ class Legend extends StatelessWidget { color: color, ), const SizedBox(width: denseSpacing), - Text( - description, - style: style, - ), + Text(description, style: style), ], ); } @@ -1441,19 +1379,20 @@ class CopyToClipboardControl extends StatelessWidget { @override Widget build(BuildContext context) { - final onPressed = dataProvider == null - ? null - : () { - if (gaScreen != null && gaItem != null) { - ga.select(gaScreen!, gaItem!); - } - unawaited( - copyToClipboard( - dataProvider!() ?? '', - successMessage: successMessage, - ), - ); - }; + final onPressed = + dataProvider == null + ? null + : () { + if (gaScreen != null && gaItem != null) { + ga.select(gaScreen!, gaItem!); + } + unawaited( + copyToClipboard( + dataProvider!() ?? '', + successMessage: successMessage, + ), + ); + }; final size = this.size ?? defaultIconSize; return SizedBox( height: size, @@ -1673,10 +1612,7 @@ class CheckboxSetting extends StatelessWidget { child: Row( children: [ RichText( - text: TextSpan( - text: ' • ', - style: theme.subtleTextStyle, - ), + text: TextSpan(text: ' • ', style: theme.subtleTextStyle), ), Flexible( child: RichText( @@ -1740,18 +1676,12 @@ class SwitchSetting extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - if (isScreenWiderThan( - context, - minScreenWidthForTextBeforeScaling, - )) + if (isScreenWiderThan(context, minScreenWidthForTextBeforeScaling)) Flexible( child: RichText( overflow: TextOverflow.visible, maxLines: 3, - text: TextSpan( - text: title, - style: theme.regularTextStyle, - ), + text: TextSpan(text: title, style: theme.regularTextStyle), ), ), NotifierSwitch( @@ -1789,25 +1719,21 @@ class PubWarningText extends StatelessWidget { final minSdkVersion = isFlutterApp ? '2.8.0' : '2.15.0'; return SelectableText.rich( TextSpan( - text: 'Warning: you should no longer be launching DevTools from' + 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 ' + 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, - ), + TextSpan(text: '`dart devtools`', style: theme.subtleFixedFontStyle), + TextSpan(text: '\ncommand.', style: theme.subtleTextStyle), ], ), ); @@ -1866,11 +1792,7 @@ class _BlinkingIconState extends State { } Widget _icon({Color? color}) { - return Icon( - widget.icon, - size: widget.size, - color: color, - ); + return Icon(widget.icon, size: widget.size, color: color); } } @@ -1897,7 +1819,8 @@ class MultiValueListenableBuilder extends StatefulWidget { BuildContext context, List values, Widget? child, - ) builder; + ) + builder; final Widget? child; @@ -1907,7 +1830,8 @@ class MultiValueListenableBuilder extends StatefulWidget { } class _MultiValueListenableBuilderState - extends State with AutoDisposeMixin { + extends State + with AutoDisposeMixin { @override void initState() { super.initState(); @@ -1916,28 +1840,20 @@ class _MultiValueListenableBuilderState @override Widget build(BuildContext context) { - return widget.builder( - context, - [for (final listenable in widget.listenables) listenable.value], - widget.child, - ); + return widget.builder(context, [ + for (final listenable in widget.listenables) listenable.value, + ], widget.child); } } class SmallCircularProgressIndicator extends StatelessWidget { - const SmallCircularProgressIndicator({ - super.key, - required this.valueColor, - }); + const SmallCircularProgressIndicator({super.key, required this.valueColor}); final Animation valueColor; @override Widget build(BuildContext context) { - return CircularProgressIndicator( - strokeWidth: 2, - valueColor: valueColor, - ); + return CircularProgressIndicator(strokeWidth: 2, valueColor: valueColor); } } @@ -1960,9 +1876,7 @@ class ElevatedCard extends StatelessWidget { return Card( elevation: defaultElevation, color: Theme.of(context).scaffoldBackgroundColor, - shape: RoundedRectangleBorder( - borderRadius: defaultBorderRadius, - ), + shape: RoundedRectangleBorder(borderRadius: defaultBorderRadius), child: Container( width: width, height: height, @@ -2084,10 +1998,7 @@ class VerticalLineSpacer extends StatelessWidget { return Padding( padding: const EdgeInsets.symmetric(horizontal: _paddingWidth), child: OutlineDecoration.onlyLeft( - child: SizedBox( - width: _lineWidth, - height: height, - ), + child: SizedBox(width: _lineWidth, height: height), ), ); } @@ -2185,8 +2096,11 @@ class ContextMenuButton extends StatelessWidget { Widget build(BuildContext context) { return MenuAnchor( menuChildren: menuChildren, - builder: - (BuildContext context, MenuController controller, Widget? child) { + builder: ( + BuildContext context, + MenuController controller, + Widget? child, + ) { return SizedBox( width: buttonWidth, child: ToolbarAction( @@ -2246,8 +2160,8 @@ class _PositiveIntegerSettingState extends State () => _textEditingController.text = widget.notifier.value.toString(), ); - _textEditingController = TextEditingController() - ..text = widget.notifier.value.toString(); + _textEditingController = + TextEditingController()..text = widget.notifier.value.toString(); } @override @@ -2268,10 +2182,7 @@ class _PositiveIntegerSettingState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(widget.title), - Text( - widget.subTitle, - style: theme.subtleTextStyle, - ), + Text(widget.subTitle, style: theme.subtleTextStyle), ], ), ), diff --git a/packages/devtools_app/lib/src/shared/config_specific/copy_to_clipboard/_copy_to_clipboard_web.dart b/packages/devtools_app/lib/src/shared/config_specific/copy_to_clipboard/_copy_to_clipboard_web.dart index e00b987428e..721c75ac430 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/copy_to_clipboard/_copy_to_clipboard_web.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/copy_to_clipboard/_copy_to_clipboard_web.dart @@ -10,10 +10,7 @@ void copyToClipboardVSCode(String data) { // listening for this command, then it will attempt to copy the contents // to the clipboard in the context of the parent frame. window.parent?.postMessage( - { - 'command': 'clipboard-write', - 'data': data, - }.jsify(), + {'command': 'clipboard-write', 'data': data}.jsify(), '*'.toJS, ); } 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 25eb106de48..eade739c688 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 @@ -65,8 +65,11 @@ abstract class DragAndDropManager { /// newly active [DragAndDrop] widgets accordingly. void hitTestAndUpdateActiveId(double x, double y) { final hitTestResult = HitTestResult(); - RendererBinding.instance - .hitTestInView(hitTestResult, Offset(x, y), _viewId); + RendererBinding.instance.hitTestInView( + hitTestResult, + Offset(x, y), + _viewId, + ); // Starting at bottom of [hitTestResult.path], look for the first // [DragAndDrop] widget. This widget will be marked by a [RenderMetaData] @@ -94,11 +97,7 @@ abstract class DragAndDropManager { } class DragAndDrop extends StatefulWidget { - const DragAndDrop({ - super.key, - required this.child, - this.handleDrop, - }); + const DragAndDrop({super.key, required this.child, this.handleDrop}); /// Callback to handle parsed data from drag and drop. /// @@ -151,18 +150,19 @@ class DragAndDropState extends State { _refreshDragAndDropManager(View.of(context).viewId); return MetaData( metaData: DragAndDropMetaData(state: this), - child: widget.handleDrop != null - ? ValueListenableBuilder( - valueListenable: _dragging, - builder: (context, dragging, _) { - // TODO(kenz): use AnimatedOpacity instead. - return Opacity( - opacity: dragging ? 0.5 : 1.0, - child: widget.child, - ); - }, - ) - : widget.child, + child: + widget.handleDrop != null + ? ValueListenableBuilder( + valueListenable: _dragging, + builder: (context, dragging, _) { + // TODO(kenz): use AnimatedOpacity instead. + return Opacity( + opacity: dragging ? 0.5 : 1.0, + child: widget.child, + ); + }, + ) + : widget.child, ); } diff --git a/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_web.dart b/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_web.dart index d091c9ca44f..f8fceb02bdd 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_web.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_web.dart @@ -17,7 +17,9 @@ import '../../server/server_api_client.dart'; /// Return the url the application is launched from. Future initializePlatform() async { // Clear out the unneeded HTML from index.html. - document.body!.querySelectorAll('.legacy-dart').forEach( + document.body! + .querySelectorAll('.legacy-dart') + .forEach( (Node element) { if (element.parentNode != null) { element.parentNode!.removeChild(element); diff --git a/packages/devtools_app/lib/src/shared/config_specific/import_export/_export_desktop.dart b/packages/devtools_app/lib/src/shared/config_specific/import_export/_export_desktop.dart index 7529b7ad994..8a4e9fa105f 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/import_export/_export_desktop.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/import_export/_export_desktop.dart @@ -15,10 +15,7 @@ class ExportControllerDesktop extends ExportController { static final _fs = FileSystemDesktop(); @override - void saveFile({ - required T content, - required String fileName, - }) { + void saveFile({required T content, required String fileName}) { _fs.writeContentsToFile(fileName, content); } } diff --git a/packages/devtools_app/lib/src/shared/config_specific/import_export/_export_web.dart b/packages/devtools_app/lib/src/shared/config_specific/import_export/_export_web.dart index ab383779475..c94851429f2 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/import_export/_export_web.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/import_export/_export_web.dart @@ -17,10 +17,7 @@ class ExportControllerWeb extends ExportController { ExportControllerWeb() : super.impl(); @override - void saveFile({ - required T content, - required String fileName, - }) { + void saveFile({required T content, required String fileName}) { final element = document.createElement('a') as HTMLAnchorElement; final Blob blob; 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 2745f3eb7e1..789e3f7ba86 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 @@ -14,7 +14,8 @@ import '../../screen.dart'; import '../../utils.dart'; import '_export_desktop.dart' if (dart.library.js_interop) '_export_web.dart'; -const nonDevToolsFileMessage = 'The imported file is not a Dart DevTools file.' +const nonDevToolsFileMessage = + 'The imported file is not a Dart DevTools file.' ' At this time, DevTools only supports importing files that were originally' ' exported from DevTools.'; @@ -34,9 +35,7 @@ enum DevToolsExportKeys { } class ImportController { - ImportController( - this._pushSnapshotScreenForImport, - ); + ImportController(this._pushSnapshotScreenForImport); static const repeatImportTimeBufferMs = 500; @@ -59,7 +58,8 @@ class ImportController { previousImportTime = now; final json = jsonFile.data; - final isDevToolsSnapshot = json is Map && + final isDevToolsSnapshot = + json is Map && json[DevToolsExportKeys.devToolsSnapshot.name] == true; if (!isDevToolsSnapshot) { notificationService.push(nonDevToolsFileMessage); @@ -89,8 +89,9 @@ class ImportController { } } - final connectedApp = - OfflineConnectedApp.parse(devToolsOfflineData.connectedApp); + final connectedApp = OfflineConnectedApp.parse( + devToolsOfflineData.connectedApp, + ); offlineDataController ..startShowingOfflineData(offlineApp: connectedApp) ..offlineDataJson = devToolsOfflineData.json; @@ -153,10 +154,7 @@ abstract class ExportController { } /// Saves [content] to the [fileName]. - void saveFile({ - required T content, - required String fileName, - }); + void saveFile({required T content, required String fileName}); Map generateDataForExport({ required Map offlineScreenData, @@ -165,7 +163,8 @@ abstract class ExportController { final contents = { DevToolsExportKeys.devToolsSnapshot.name: true, DevToolsExportKeys.devToolsVersion.name: devToolsVersion, - DevToolsExportKeys.connectedApp.name: connectedApp?.toJson() ?? + DevToolsExportKeys.connectedApp.name: + connectedApp?.toJson() ?? serviceConnection.serviceManager.connectedApp!.toJson(), ...offlineScreenData, }; @@ -176,9 +175,6 @@ abstract class ExportController { String encode(Map offlineScreenData) { final data = generateDataForExport(offlineScreenData: offlineScreenData); - return jsonEncode( - data, - toEncodable: toEncodable, - ); + return jsonEncode(data, toEncodable: toEncodable); } } diff --git a/packages/devtools_app/lib/src/shared/config_specific/logger/logger.dart b/packages/devtools_app/lib/src/shared/config_specific/logger/logger.dart index 5af1b879253..77681b9265c 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/logger/logger.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/logger/logger.dart @@ -4,8 +4,4 @@ export '_logger_io.dart' if (dart.library.js_interop) '_logger_web.dart'; -enum LogLevel { - debug, - warning, - error, -} +enum LogLevel { debug, warning, error } diff --git a/packages/devtools_app/lib/src/shared/config_specific/notifications/_notifications_web.dart b/packages/devtools_app/lib/src/shared/config_specific/notifications/_notifications_web.dart index 1eec76cff13..bb32d53f684 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/notifications/_notifications_web.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/notifications/_notifications_web.dart @@ -8,10 +8,7 @@ import 'package:web/web.dart' as web; class Notification { Notification(String title, {String body = ''}) { - _impl = web.Notification( - title, - web.NotificationOptions(body: body), - ); + _impl = web.Notification(title, web.NotificationOptions(body: body)); } late final web.Notification _impl; 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 36d15b68c79..c5096f85b14 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 @@ -10,10 +10,8 @@ import 'post_message.dart'; Stream get onPostMessage { return window.onMessage.map( - (message) => PostMessageEvent( - origin: message.origin, - data: message.data.dartify(), - ), + (message) => + PostMessageEvent(origin: message.origin, 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 a13c74d73a5..02633765c10 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,10 +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.origin, required this.data}); final String origin; final Object? data; diff --git a/packages/devtools_app/lib/src/shared/connection_info.dart b/packages/devtools_app/lib/src/shared/connection_info.dart index bd1a348e3d8..95ce958a440 100644 --- a/packages/devtools_app/lib/src/shared/connection_info.dart +++ b/packages/devtools_app/lib/src/shared/connection_info.dart @@ -29,8 +29,10 @@ class ConnectedAppSummary extends StatelessWidget { return const SizedBox(); } - final connectionDescriptionEntries = - generateDeviceDescription(vm, connectedApp); + final connectionDescriptionEntries = generateDeviceDescription( + vm, + connectedApp, + ); // Ensure the screen is large enough to render two columns, even if // [narrowView] is false. @@ -78,10 +80,7 @@ class _ConnectionDescriptionColumn extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Text('${entry.title}: ', style: boldText), - SelectableText( - entry.description, - style: theme.subtleTextStyle, - ), + SelectableText(entry.description, style: theme.subtleTextStyle), if (entry.actions.isNotEmpty) ...entry.actions, ], ), diff --git a/packages/devtools_app/lib/src/shared/console/console.dart b/packages/devtools_app/lib/src/shared/console/console.dart index 56f6b096b53..ea9fec2bee3 100644 --- a/packages/devtools_app/lib/src/shared/console/console.dart +++ b/packages/devtools_app/lib/src/shared/console/console.dart @@ -21,12 +21,7 @@ import 'widgets/expandable_variable.dart'; /// Renders a Console widget with output [lines] and an optional [title] and /// [footer]. class Console extends StatelessWidget { - const Console({ - super.key, - required this.lines, - this.title, - this.footer, - }); + const Console({super.key, required this.lines, this.title, this.footer}); final Widget? title; final Widget? footer; @@ -42,11 +37,7 @@ class Console extends StatelessWidget { } class ConsoleFrame extends StatelessWidget { - const ConsoleFrame({ - super.key, - required this.child, - this.title, - }); + const ConsoleFrame({super.key, required this.child, this.title}); final Widget? title; final Widget child; @@ -57,12 +48,7 @@ class ConsoleFrame extends StatelessWidget { padding: const EdgeInsets.only(bottom: densePadding), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - if (title != null) title!, - Expanded( - child: child, - ), - ], + children: [if (title != null) title!, Expanded(child: child)], ), ); } @@ -72,10 +58,7 @@ class ConsoleFrame extends StatelessWidget { /// /// This is a ListView of text lines, with a monospace font and a border. class _ConsoleOutput extends StatefulWidget { - const _ConsoleOutput({ - required this.lines, - this.footer, - }); + const _ConsoleOutput({required this.lines, this.footer}); final ValueListenable> lines; diff --git a/packages/devtools_app/lib/src/shared/console/console_service.dart b/packages/devtools_app/lib/src/shared/console/console_service.dart index 473d970aaba..6c01025fa6b 100644 --- a/packages/devtools_app/lib/src/shared/console/console_service.dart +++ b/packages/devtools_app/lib/src/shared/console/console_service.dart @@ -24,23 +24,13 @@ import '../primitives/utils.dart'; /// TODO(jacobr): support console lines that are structured error messages as /// well. class ConsoleLine { - factory ConsoleLine.text( - String text, { - bool forceScrollIntoView = false, - }) => - TextConsoleLine( - text, - forceScrollIntoView: forceScrollIntoView, - ); + factory ConsoleLine.text(String text, {bool forceScrollIntoView = false}) => + TextConsoleLine(text, forceScrollIntoView: forceScrollIntoView); factory ConsoleLine.dartObjectNode( DartObjectNode variable, { bool forceScrollIntoView = false, - }) => - VariableConsoleLine( - variable, - forceScrollIntoView: forceScrollIntoView, - ); + }) => VariableConsoleLine(variable, forceScrollIntoView: forceScrollIntoView); ConsoleLine._(this.forceScrollIntoView); @@ -50,7 +40,7 @@ class ConsoleLine { class TextConsoleLine extends ConsoleLine { TextConsoleLine(this.text, {bool forceScrollIntoView = false}) - : super._(forceScrollIntoView); + : super._(forceScrollIntoView); final String text; @override @@ -61,9 +51,7 @@ class TextConsoleLine extends ConsoleLine { class VariableConsoleLine extends ConsoleLine { VariableConsoleLine(this.variable, {bool forceScrollIntoView = false}) - : super._( - forceScrollIntoView, - ); + : super._(forceScrollIntoView); final DartObjectNode variable; @override @@ -178,8 +166,9 @@ class ConsoleService with DisposerMixin { last is TextConsoleLine) { _stdio.last = ConsoleLine.text('${last.text}${newLines.first}'); if (newLines.length > 1) { - _stdio - .addAll(newLines.sublist(1).map((text) => ConsoleLine.text(text))); + _stdio.addAll( + newLines.sublist(1).map((text) => ConsoleLine.text(text)), + ); } } else { _stdio.addAll(newLines.map((text) => ConsoleLine.text(text))); @@ -267,7 +256,9 @@ class ConsoleService with DisposerMixin { ); autoDisposeStreamSubscription( serviceConnection - .serviceManager.service!.onExtensionEventWithHistorySafe + .serviceManager + .service! + .onExtensionEventWithHistorySafe .listen(_handleExtensionEvent), ); _serviceInitialized = true; diff --git a/packages/devtools_app/lib/src/shared/console/eval/auto_complete.dart b/packages/devtools_app/lib/src/shared/console/eval/auto_complete.dart index d717a2f32df..a3db1267227 100644 --- a/packages/devtools_app/lib/src/shared/console/eval/auto_complete.dart +++ b/packages/devtools_app/lib/src/shared/console/eval/auto_complete.dart @@ -59,10 +59,7 @@ Future> autoCompleteResultsFor( final libraryRef = await evalService.findOwnerLibrary(function); if (libraryRef != null) { result.addAll( - await libraryMemberAndImportsAutocompletes( - libraryRef, - evalService, - ), + await libraryMemberAndImportsAutocompletes(libraryRef, evalService), ); } } @@ -113,11 +110,13 @@ Future> libraryMemberAndImportsAutocompletes( LibraryRef libraryRef, EvalService evalService, ) async { - final autocompletes = - await _appState.cache.libraryMemberAndImportsAutocomplete.putIfAbsent( - libraryRef, - () => _libraryMemberAndImportsAutocompletes(libraryRef, evalService), - ); + final autocompletes = await _appState + .cache + .libraryMemberAndImportsAutocomplete + .putIfAbsent( + libraryRef, + () => _libraryMemberAndImportsAutocompletes(libraryRef, evalService), + ); return autocompletes.nonNulls.toSet(); } @@ -171,11 +170,11 @@ Future> libraryMemberAutocompletes( LibraryRef libraryRef, { required bool includePrivates, }) async { - var result = (await _appState.cache.libraryMemberAutocomplete.putIfAbsent( - libraryRef, - () => _libraryMemberAutocompletes(evalService, libraryRef), - )) - .nonNulls; + var result = + (await _appState.cache.libraryMemberAutocomplete.putIfAbsent( + libraryRef, + () => _libraryMemberAutocompletes(evalService, libraryRef), + )).nonNulls; if (!includePrivates) { result = result.where((name) => !isPrivateMember(name)); } @@ -196,8 +195,9 @@ Future> _libraryMemberAutocompletes( final functions = library.functions; if (functions != null) { // The VM shows setters as `=`. - final members = - functions.map((funcRef) => funcRef.name!.replaceAll('=', '')); + final members = functions.map( + (funcRef) => funcRef.name!.replaceAll('=', ''), + ); result.addAll(members.nonNulls); } final classes = library.classes; @@ -242,11 +242,7 @@ Future _addAllInstanceMembersToAutocompleteList( final classRef = instance.classRef; if (classRef == null) return; result.addAll( - await _autoCompleteMembersFor( - classRef, - controller, - staticContext: false, - ), + await _autoCompleteMembersFor(classRef, controller, staticContext: false), ); final clazz = await controller.classFor(classRef); final fields = clazz?.fields; @@ -255,9 +251,7 @@ Future _addAllInstanceMembersToAutocompleteList( .where((field) => field.isStatic ?? false) .map((field) => field.name); result.addAll( - fieldNames.nonNulls.where( - (member) => _isAccessible(member, clazz), - ), + fieldNames.nonNulls.where((member) => _isAccessible(member, clazz)), ); } @@ -319,34 +313,31 @@ bool _validFunction(FuncRef funcRef, Class clazz, bool staticContext) { } bool _isOperator(FuncRef funcRef) => const { - '==', - '+', - '-', - '*', - '/', - '&', - '~', - '|', - '>', - '<', - '>=', - '<=', - '>>', - '<<', - '>>>', - '^', - '%', - '~/', - 'unary-', - }.contains(funcRef.name); + '==', + '+', + '-', + '*', + '/', + '&', + '~', + '|', + '>', + '<', + '>=', + '<=', + '>>', + '<<', + '>>>', + '^', + '%', + '~/', + 'unary-', +}.contains(funcRef.name); bool _isConstructor(FuncRef funcRef, Class clazz) => funcRef.name == clazz.name || funcRef.name!.startsWith('${clazz.name}.'); -bool _isAccessible( - String member, - Class? clazz, -) { +bool _isAccessible(String member, Class? clazz) { final frame = _appState.currentFrame.value!; final currentScript = frame.location!.script; return !isPrivateMember(member) || diff --git a/packages/devtools_app/lib/src/shared/console/eval/eval_service.dart b/packages/devtools_app/lib/src/shared/console/eval/eval_service.dart index 5238e64cba5..ef60f5f98a5 100644 --- a/packages/devtools_app/lib/src/shared/console/eval/eval_service.dart +++ b/packages/devtools_app/lib/src/shared/console/eval/eval_service.dart @@ -24,7 +24,11 @@ class EvalService extends DisposableController with AutoDisposeControllerMixin { String? get _isolateRefId { return serviceConnection - .serviceManager.isolateManager.selectedIsolate.value?.id; + .serviceManager + .isolateManager + .selectedIsolate + .value + ?.id; } /// Returns the class for the provided [ClassRef]. @@ -165,12 +169,12 @@ class EvalService extends DisposableController with AutoDisposeControllerMixin { } Future evalFunction() => _service.evaluateInFrame( - isolateRefId, - frame.index!, - expression, - disableBreakpoints: true, - scope: scope.value(isolateId: isolateRefId), - ); + isolateRefId, + frame.index!, + expression, + disableBreakpoints: true, + scope: scope.value(isolateId: isolateRefId), + ); return await _evalWithVariablesRefresh(evalFunction, isolateRefId); } @@ -182,9 +186,9 @@ class EvalService extends DisposableController with AutoDisposeControllerMixin { final isolateId = isolateRef.id!; final theClass = (await serviceConnection.serviceManager.service! - .getClassList(isolateId)) - .classes! - .firstWhereOrNull((ref) => object.className?.matches(ref) ?? false); + .getClassList(isolateId)).classes!.firstWhereOrNull( + (ref) => object.className?.matches(ref) ?? false, + ); return await findInstance(isolateId, theClass?.id, object.code); } 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 2e204e2ee6e..7aa7abeba8e 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 @@ -36,12 +36,10 @@ double get inspectorRowHeight => scaleByFontFactor(16.0); /// specific as that is the only case we care about. // TODO(kenz): extend TreeNode class to share tree logic. class InspectorTreeNode { - InspectorTreeNode({ - InspectorTreeNode? parent, - bool expandChildren = true, - }) : _children = [], - _parent = parent, - _isExpanded = expandChildren; + InspectorTreeNode({InspectorTreeNode? parent, bool expandChildren = true}) + : _children = [], + _parent = parent, + _isExpanded = expandChildren; bool get showLinesToChildren { return _children.length > 1 && !_children.last.isProperty; @@ -197,7 +195,8 @@ class InspectorTreeNode { // Iterate till getting the result to return. while (true) { final style = node.diagnostic?.style; - final indented = style != DiagnosticsTreeStyle.flat && + final indented = + style != DiagnosticsTreeStyle.flat && style != DiagnosticsTreeStyle.error; if (current == index) { return InspectorTreeRow( @@ -205,7 +204,8 @@ class InspectorTreeNode { index: index, ticks: ticks, depth: depth, - lineToParent: !node.isProperty && + lineToParent: + !node.isProperty && index != 0 && node.parent!.showLinesToChildren, ); @@ -278,10 +278,11 @@ class InspectorTreeRow with SearchableDataMixin { } /// Callback issued every time a node is added to the tree. -typedef NodeAddedCallback = void Function( - InspectorTreeNode node, - RemoteDiagnosticsNode diagnosticsNode, -); +typedef NodeAddedCallback = + void Function( + InspectorTreeNode node, + RemoteDiagnosticsNode diagnosticsNode, + ); class InspectorTreeConfig { InspectorTreeConfig({ diff --git a/packages/devtools_app/lib/src/shared/console/eval/inspector_tree_v2.dart b/packages/devtools_app/lib/src/shared/console/eval/inspector_tree_v2.dart index ed97e4e0bf7..cdc4c5bcb8f 100644 --- a/packages/devtools_app/lib/src/shared/console/eval/inspector_tree_v2.dart +++ b/packages/devtools_app/lib/src/shared/console/eval/inspector_tree_v2.dart @@ -40,9 +40,9 @@ class InspectorTreeNode { InspectorTreeNode? parent, bool expandChildren = true, this.whenDirty, - }) : _children = [], - _parent = parent, - _isExpanded = expandChildren; + }) : _children = [], + _parent = parent, + _isExpanded = expandChildren; /// Callback that is called when the node is marked as dirty. void Function(InspectorTreeNode node)? whenDirty; @@ -184,10 +184,11 @@ class InspectorTreeRow with SearchableDataMixin { } /// Callback issued every time a node is added to the tree. -typedef NodeAddedCallback = void Function( - InspectorTreeNode node, - RemoteDiagnosticsNode diagnosticsNode, -); +typedef NodeAddedCallback = + void Function( + InspectorTreeNode node, + RemoteDiagnosticsNode diagnosticsNode, + ); class InspectorTreeConfig { InspectorTreeConfig({ diff --git a/packages/devtools_app/lib/src/shared/console/primitives/assignment.dart b/packages/devtools_app/lib/src/shared/console/primitives/assignment.dart index 470d970490d..08d274bb912 100644 --- a/packages/devtools_app/lib/src/shared/console/primitives/assignment.dart +++ b/packages/devtools_app/lib/src/shared/console/primitives/assignment.dart @@ -18,8 +18,12 @@ class ConsoleVariableAssignment { const variableNameGroup = '([_a-zA-Z][_a-zA-Z0-9]{0,30})'; const indexGroup = '([_012345])'; - final regex = - RegExp(r'var\s+' '$variableNameGroup' r'\s*=\s*\$' '$indexGroup'); + final regex = RegExp( + r'var\s+' + '$variableNameGroup' + r'\s*=\s*\$' + '$indexGroup', + ); final matches = regex.allMatches(expression); if (matches.length != 1) return null; diff --git a/packages/devtools_app/lib/src/shared/console/primitives/scope.dart b/packages/devtools_app/lib/src/shared/console/primitives/scope.dart index 4576fad4224..d371b63e45c 100644 --- a/packages/devtools_app/lib/src/shared/console/primitives/scope.dart +++ b/packages/devtools_app/lib/src/shared/console/primitives/scope.dart @@ -48,10 +48,7 @@ class EvalScope { return result; } - Future _refreshRef( - InstanceRef ref, - String isolateId, - ) async { + Future _refreshRef(InstanceRef ref, String isolateId) async { Obj? object; try { object = await serviceConnection.serviceManager.service!.getObject( diff --git a/packages/devtools_app/lib/src/shared/console/primitives/simple_items.dart b/packages/devtools_app/lib/src/shared/console/primitives/simple_items.dart index 76e96ffc21d..7f35dc1ba2d 100644 --- a/packages/devtools_app/lib/src/shared/console/primitives/simple_items.dart +++ b/packages/devtools_app/lib/src/shared/console/primitives/simple_items.dart @@ -3,6 +3,4 @@ // found in the LICENSE file. // TODO(jacobr): add render, semantics, and layer trees. -enum FlutterTreeType { - widget, -} +enum FlutterTreeType { widget } diff --git a/packages/devtools_app/lib/src/shared/console/widgets/console_pane.dart b/packages/devtools_app/lib/src/shared/console/widgets/console_pane.dart index 847f2b083b4..f6e0d81c6de 100644 --- a/packages/devtools_app/lib/src/shared/console/widgets/console_pane.dart +++ b/packages/devtools_app/lib/src/shared/console/widgets/console_pane.dart @@ -17,35 +17,34 @@ import 'help_dialog.dart'; class ConsolePaneHeader extends AreaPaneHeader { ConsolePaneHeader({super.key}) - : super( - title: const Text('Console'), - roundedTopBorder: true, - actions: [ - const ConsoleHelpLink(), - const SizedBox(width: densePadding), - CopyToClipboardControl( - dataProvider: () => - serviceConnection.consoleService.stdio.value.join('\n'), - buttonKey: ConsolePane.copyToClipboardButtonKey, - ), - const SizedBox(width: densePadding), - DeleteControl( - buttonKey: ConsolePane.clearStdioButtonKey, - tooltip: 'Clear console output', - onPressed: () => serviceConnection.consoleService.clearStdio(), - ), - ], - ); + : super( + title: const Text('Console'), + roundedTopBorder: true, + actions: [ + const ConsoleHelpLink(), + const SizedBox(width: densePadding), + CopyToClipboardControl( + dataProvider: + () => serviceConnection.consoleService.stdio.value.join('\n'), + buttonKey: ConsolePane.copyToClipboardButtonKey, + ), + const SizedBox(width: densePadding), + DeleteControl( + buttonKey: ConsolePane.clearStdioButtonKey, + tooltip: 'Clear console output', + onPressed: () => serviceConnection.consoleService.clearStdio(), + ), + ], + ); } /// Display the stdout and stderr output from the process under debug. class ConsolePane extends StatelessWidget { - const ConsolePane({ - super.key, - }); + const ConsolePane({super.key}); - static const copyToClipboardButtonKey = - Key('console_copy_to_clipboard_button'); + static const copyToClipboardButtonKey = Key( + 'console_copy_to_clipboard_button', + ); static const clearStdioButtonKey = Key('console_clear_stdio_button'); ValueListenable> get stdio => @@ -63,14 +62,7 @@ class ConsolePane extends StatelessWidget { } return Column( - children: [ - Expanded( - child: Console( - lines: stdio, - footer: footer, - ), - ), - ], + children: [Expanded(child: Console(lines: stdio, footer: footer))], ); } } 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 212342a8e93..f0413252806 100644 --- a/packages/devtools_app/lib/src/shared/console/widgets/description.dart +++ b/packages/devtools_app/lib/src/shared/console/widgets/description.dart @@ -79,12 +79,11 @@ class DiagnosticsNodeDescription extends StatelessWidget { /// Approximates the width of the elements inside a [RemoteDiagnosticsNode] /// widget. - static double approximateNodeWidth( - RemoteDiagnosticsNode? diagnostic, - ) { + static double approximateNodeWidth(RemoteDiagnosticsNode? diagnostic) { // If we have rendered this node, then we know it's text style, // otherwise assume defaultFontSize for the TextStyle. - final textStyle = diagnostic?.descriptionTextStyleFromBuild ?? + final textStyle = + diagnostic?.descriptionTextStyleFromBuild ?? TextStyle(fontSize: defaultFontSize); final spans = DiagnosticsNodeDescription.buildDescriptionTextSpans( @@ -110,8 +109,9 @@ class DiagnosticsNodeDescription extends StatelessWidget { // If there is a description then a separator will show with the name. name += ': '; } - spanWidth += - calculateTextSpanWidth(TextSpan(text: name, style: textStyle)); + spanWidth += calculateTextSpanWidth( + TextSpan(text: name, style: textStyle), + ); } else { final approximateIconWidth = IconKind.info.icon.width + iconPadding; @@ -137,8 +137,9 @@ class DiagnosticsNodeDescription extends StatelessWidget { if (match.group(2)?.isNotEmpty == true) { yield TextSpan( text: match.group(2), - style: - textStyle.merge(DiagnosticsTextStyles.unimportant(colorScheme)), + style: textStyle.merge( + DiagnosticsTextStyles.unimportant(colorScheme), + ), ); } return; @@ -161,10 +162,7 @@ class DiagnosticsNodeDescription extends StatelessWidget { final preview = textPreview.replaceAll('\n', ' '); yield TextSpan( children: [ - TextSpan( - text: ': ', - style: textStyle, - ), + TextSpan(text: ': ', style: textStyle), _buildHighlightedSearchPreview( preview, searchValue, @@ -191,23 +189,25 @@ class DiagnosticsNodeDescription extends StatelessWidget { diagnostic?.descriptionTextStyleFromBuild = textStyle; final textSpan = TextSpan( - children: buildDescriptionTextSpans( - description: description, - textStyle: textStyle, - colorScheme: colorScheme, - diagnostic: diagnostic, - searchValue: searchValue, - nodeDescriptionHighlightStyle: nodeDescriptionHighlightStyle, - ).toList(), + children: + buildDescriptionTextSpans( + description: description, + textStyle: textStyle, + colorScheme: colorScheme, + diagnostic: diagnostic, + searchValue: searchValue, + nodeDescriptionHighlightStyle: nodeDescriptionHighlightStyle, + ).toList(), ); final diagnosticLocal = diagnostic!; final inspectorService = serviceConnection.inspectorService!; return HoverCardTooltip.async( - enabled: () => - preferences.inspector.hoverEvalModeEnabled.value && - diagnosticLocal.objectGroupApi != null, + enabled: + () => + preferences.inspector.hoverEvalModeEnabled.value && + diagnosticLocal.objectGroupApi != null, asyncGenerateHoverCardData: ({ required event, required isHoverStale, @@ -215,8 +215,9 @@ class DiagnosticsNodeDescription extends StatelessWidget { final group = inspectorService.createObjectGroup('hover'); if (isHoverStale()) return Future.value(); - final value = - await group.toObservatoryInstanceRef(diagnosticLocal.valueRef); + final value = await group.toObservatoryInstanceRef( + diagnosticLocal.valueRef, + ); final variable = DartObjectNode.fromValue( value: value, @@ -237,11 +238,7 @@ class DiagnosticsNodeDescription extends StatelessWidget { return HoverCardData( title: diagnosticLocal.toStringShort(), - contents: Material( - child: ExpandableVariable( - variable: variable, - ), - ), + contents: Material(child: ExpandableVariable(variable: variable)), ); }, child: DescriptionDisplay( @@ -264,9 +261,10 @@ class DiagnosticsNodeDescription extends StatelessWidget { final theme = Theme.of(context); final colorScheme = theme.colorScheme; - final icon = customIconName != null - ? RemoteDiagnosticsNode.iconMaker.fromWidgetName(customIconName) - : diagnosticLocal.icon; + final icon = + customIconName != null + ? RemoteDiagnosticsNode.iconMaker.fromWidgetName(customIconName) + : diagnosticLocal.icon; final children = []; @@ -291,7 +289,7 @@ class DiagnosticsNodeDescription extends StatelessWidget { final showDefaultValueLabel = diagnosticLocal.level == DiagnosticLevel.fine && - diagnosticLocal.hasDefaultValue; + diagnosticLocal.hasDefaultValue; // Show the "default" value label at the start if the property name isn't // included: @@ -306,10 +304,7 @@ class DiagnosticsNodeDescription extends StatelessWidget { if (includeName && name?.isNotEmpty == true && diagnosticLocal.showName) { children.add( - Text( - '$name${diagnosticLocal.separator} ', - style: textStyle, - ), + Text('$name${diagnosticLocal.separator} ', style: textStyle), ); // provide some contrast between the name and description if both are // present. @@ -330,9 +325,10 @@ class DiagnosticsNodeDescription extends StatelessWidget { final green = JsonUtils.getIntMember(properties, 'green'); final blue = JsonUtils.getIntMember(properties, 'blue'); String radix(int chan) => chan.toRadixString(16).padLeft(2, '0'); - description = alpha == 255 - ? '#${radix(red)}${radix(green)}${radix(blue)}' - : '#${radix(alpha)}${radix(red)}${radix(green)}${radix(blue)}'; + description = + alpha == 255 + ? '#${radix(red)}${radix(green)}${radix(blue)}' + : '#${radix(alpha)}${radix(red)}${radix(green)}${radix(blue)}'; final color = Color.fromARGB(alpha, red, green, blue); children.add(_paddedIcon(_colorIconMaker.getCustomIcon(color))); @@ -391,29 +387,16 @@ class DiagnosticsNodeDescription extends StatelessWidget { name != 'child') { if (name.startsWith('child ')) { children.add( - Text( - name, - style: DiagnosticsTextStyles.unimportant(colorScheme), - ), + Text(name, style: DiagnosticsTextStyles.unimportant(colorScheme)), ); } else { children.add(Text(name, style: textStyle)); } if (diagnosticLocal.showSeparator) { - children.add( - Text( - diagnosticLocal.separator, - style: textStyle, - ), - ); + children.add(Text(diagnosticLocal.separator, style: textStyle)); if (diagnosticLocal.separator != ' ' && descriptionText.isNotEmpty) { - children.add( - Text( - ' ', - style: textStyle, - ), - ); + children.add(Text(' ', style: textStyle)); } } } @@ -451,20 +434,14 @@ class DiagnosticsNodeDescription extends StatelessWidget { // the nested row. diagnosticDescription = Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - diagnosticDescription, - _buildErrorText(colorScheme), - ], + children: [diagnosticDescription, _buildErrorText(colorScheme)], ); } else if (multiline && diagnosticLocal.hasCreationLocation && !diagnosticLocal.isProperty) { diagnosticDescription = Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - diagnosticDescription, - _buildLocation(context), - ], + children: [diagnosticDescription, _buildLocation(context)], ); } @@ -498,9 +475,10 @@ class DiagnosticsNodeDescription extends StatelessWidget { text: errorText, // When the node is selected, the background will be an error // color so don't render the text the same color. - style: isSelected - ? DiagnosticsTextStyles.regular(colorScheme) - : DiagnosticsTextStyles.error(colorScheme), + style: + isSelected + ? DiagnosticsTextStyles.regular(colorScheme) + : DiagnosticsTextStyles.error(colorScheme), ), ), ); @@ -513,25 +491,16 @@ class DiagnosticsNodeDescription extends StatelessWidget { TextStyle highlightTextStyle, ) { if (searchValue == null || searchValue.isEmpty) { - return TextSpan( - text: '"$textPreview"', - style: textStyle, - ); + return TextSpan(text: '"$textPreview"', style: textStyle); } if (textPreview.caseInsensitiveEquals(searchValue)) { - return TextSpan( - text: '"$textPreview"', - style: highlightTextStyle, - ); + return TextSpan(text: '"$textPreview"', style: highlightTextStyle); } final matches = searchValue.caseInsensitiveAllMatches(textPreview); if (matches.isEmpty) { - return TextSpan( - text: '"$textPreview"', - style: textStyle, - ); + return TextSpan(text: '"$textPreview"', style: textStyle); } final quoteSpan = TextSpan(text: '"', style: textStyle); @@ -602,14 +571,14 @@ class DescriptionDisplay extends StatelessWidget { this.actionLabel, this.actionCallback, this.overflow = TextOverflow.ellipsis, - }) : assert( - multiline ? actionLabel == null : true, - 'Action labels are not supported for multiline descriptions', - ), - assert( - (actionLabel == null) == (actionCallback == null), - 'Actions require both a label and a callback', - ); + }) : assert( + multiline ? actionLabel == null : true, + 'Action labels are not supported for multiline descriptions', + ), + assert( + (actionLabel == null) == (actionCallback == null), + 'Actions require both a label and a callback', + ); final TextSpan text; final bool multiline; @@ -627,10 +596,7 @@ class DescriptionDisplay extends StatelessWidget { return Row( children: [ Flexible( - child: RichText( - overflow: TextOverflow.ellipsis, - text: text, - ), + child: RichText(overflow: TextOverflow.ellipsis, text: text), ), Flexible( child: TextButton( @@ -638,18 +604,13 @@ class DescriptionDisplay extends StatelessWidget { textStyle: Theme.of(context).regularTextStyle, ), onPressed: actionCallback, - child: Text( - actionLabel!, - ), + child: Text(actionLabel!), ), ), ], ); } - return RichText( - overflow: overflow, - text: text, - ); + return RichText(overflow: overflow, text: text); } } 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 7cd3de7eb07..3e6c80ed70b 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 @@ -78,9 +78,7 @@ class _DisplayProviderState extends State { final displayValue = originalDisplayValue.replaceAll('\n', '\\n'); final contents = InteractivityWrapper( onTap: widget.onTap, - menuButtons: _getMenuButtons( - context, - ), + menuButtons: _getMenuButtons(context), child: DevToolsTooltip( message: originalDisplayValue, child: Container( @@ -93,22 +91,21 @@ class _DisplayProviderState extends State { overflow: TextOverflow.ellipsis, TextSpan( text: hasName ? widget.variable.name : null, - style: widget.variable.artificialName - ? theme.subtleFixedFontStyle - : theme.fixedFontStyle.apply( - color: theme.colorScheme.controlFlowSyntaxColor, - ), + style: + widget.variable.artificialName + ? theme.subtleFixedFontStyle + : theme.fixedFontStyle.apply( + color: theme.colorScheme.controlFlowSyntaxColor, + ), children: [ if (hasName) - TextSpan( - text: ': ', - style: theme.fixedFontStyle, - ), + TextSpan(text: ': ', style: theme.fixedFontStyle), TextSpan( text: displayValue, - style: widget.variable.artificialValue - ? theme.subtleFixedFontStyle - : _variableDisplayStyle(theme, widget.variable), + style: + widget.variable.artificialValue + ? theme.subtleFixedFontStyle + : _variableDisplayStyle(theme, widget.variable), ), ], ), @@ -146,9 +143,7 @@ class _DisplayProviderState extends State { return contents; } - List _getMenuButtons( - BuildContext context, - ) { + List _getMenuButtons(BuildContext context) { return [ if (widget.variable.isRerootable) ContextMenuButtonItem( @@ -176,9 +171,7 @@ class _DisplayProviderState extends State { ]; } - void _handleInspect( - BuildContext context, - ) async { + void _handleInspect(BuildContext context) async { final router = DevToolsRouterDelegate.of(context); final inspectorService = serviceConnection.inspectorService; if (await widget.variable.inspectWidget()) { @@ -222,19 +215,13 @@ class _DisplayProviderState extends State { } switch (kind) { case InstanceKind.kString: - return style.apply( - color: theme.colorScheme.stringSyntaxColor, - ); + return style.apply(color: theme.colorScheme.stringSyntaxColor); case InstanceKind.kInt: case InstanceKind.kDouble: - return style.apply( - color: theme.colorScheme.numericConstantSyntaxColor, - ); + return style.apply(color: theme.colorScheme.numericConstantSyntaxColor); case InstanceKind.kBool: case InstanceKind.kNull: - return style.apply( - color: theme.colorScheme.modifierSyntaxColor, - ); + return style.apply(color: theme.colorScheme.modifierSyntaxColor); default: return style; } @@ -270,16 +257,10 @@ class DapDisplayProvider extends StatelessWidget { color: theme.colorScheme.controlFlowSyntaxColor, ), children: [ - TextSpan( - text: ': ', - style: theme.fixedFontStyle, - ), + TextSpan(text: ': ', style: theme.fixedFontStyle), // TODO(https://github.com/flutter/devtools/issues/6056): Change text // style based on variable type. - TextSpan( - text: value, - style: theme.subtleFixedFontStyle, - ), + TextSpan(text: value, style: theme.subtleFixedFontStyle), ], ), ); 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 0f41f479a10..94c1561afe5 100644 --- a/packages/devtools_app/lib/src/shared/console/widgets/evaluate.dart +++ b/packages/devtools_app/lib/src/shared/console/widgets/evaluate.dart @@ -23,17 +23,15 @@ import '../primitives/assignment.dart'; import '../primitives/eval_history.dart'; import 'help_dialog.dart'; -typedef AutoCompleteResultsFunction = Future> Function( - EditingParts parts, - EvalService evalService, -); +typedef AutoCompleteResultsFunction = + Future> Function(EditingParts parts, EvalService evalService); class ExpressionEvalField extends StatefulWidget { const ExpressionEvalField({ super.key, AutoCompleteResultsFunction? getAutoCompleteResults, }) : getAutoCompleteResults = - getAutoCompleteResults ?? autoCompleteResultsFor; + getAutoCompleteResults ?? autoCompleteResultsFor; final AutoCompleteResultsFunction getAutoCompleteResults; @@ -181,13 +179,11 @@ class ExpressionEvalFieldState extends State ..clearSearchAutoComplete() ..clearCurrentSuggestion(); } else { - final results = matches - .sublist( - 0, - min(defaultTopMatchesLimit, matches.length), - ) - .map((match) => AutoCompleteMatch(match)) - .toList(); + final results = + matches + .sublist(0, min(defaultTopMatchesLimit, matches.length)) + .map((match) => AutoCompleteMatch(match)) + .toList(); _autoCompleteController ..searchAutoComplete.value = results @@ -233,33 +229,33 @@ class ExpressionEvalFieldState extends State decoration: InputDecoration( contentPadding: const EdgeInsets.all(denseSpacing), border: const OutlineInputBorder(), - focusedBorder: - const OutlineInputBorder(borderSide: BorderSide.none), - enabledBorder: - const OutlineInputBorder(borderSide: BorderSide.none), + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide.none, + ), + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide.none, + ), labelText: 'Eval. Enter "?" for help.', labelStyle: Theme.of(context).subtleTextStyle, ), - overlayXPositionBuilder: - (String inputValue, TextStyle? inputStyle) { + overlayXPositionBuilder: ( + String inputValue, + TextStyle? inputStyle, + ) { // X-coordinate is equivalent to the width of the input text // up to the last "." or the insertion point (cursor): final indexOfDot = inputValue.lastIndexOf('.'); - final textSegment = indexOfDot != -1 - ? inputValue.substring(0, indexOfDot + 1) - : inputValue; + final textSegment = + indexOfDot != -1 + ? inputValue.substring(0, indexOfDot + 1) + : inputValue; return calculateTextSpanWidth( - TextSpan( - text: textSegment, - style: inputStyle, - ), + TextSpan(text: textSegment, style: inputStyle), ); }, // Disable ligatures, so the suggestions of the auto complete work correcly. style: Theme.of(context).fixedFontStyle.copyWith( - fontFeatures: [ - const FontFeature.disable('liga'), - ], + fontFeatures: [const FontFeature.disable('liga')], ), ), ), @@ -306,10 +302,7 @@ class ExpressionEvalFieldState extends State ); } - List _filterMatches( - List previousMatches, - String activeWord, - ) { + List _filterMatches(List previousMatches, String activeWord) { return previousMatches .where((match) => match.startsWith(activeWord)) .toList(); @@ -358,8 +351,10 @@ class ExpressionEvalFieldState extends State ); return; } - response = - await evalService.evalInRunningApp(isolateRef, expressionText); + response = await evalService.evalInRunningApp( + isolateRef, + expressionText, + ); } // Display the response to the user. @@ -445,8 +440,9 @@ class ExpressionEvalFieldState extends State if (assignment == null) return false; const kSuccess = true; - final variable = serviceConnection.consoleService - .itemAt(assignment.consoleItemIndex + 1); + final variable = serviceConnection.consoleService.itemAt( + assignment.consoleItemIndex + 1, + ); final value = variable?.value; if (value is! InstanceRef) { _emitToConsole( @@ -455,15 +451,23 @@ class ExpressionEvalFieldState extends State return kSuccess; } - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value?.id; - final isolateName = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value?.name; + final isolateId = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value + ?.id; + final isolateName = + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value + ?.name; if (isolateId == null || isolateName == null) { - _emitToConsole( - 'Selected isolate cannot be detected.', - ); + _emitToConsole('Selected isolate cannot be detected.'); return kSuccess; } diff --git a/packages/devtools_app/lib/src/shared/console/widgets/expandable_variable.dart b/packages/devtools_app/lib/src/shared/console/widgets/expandable_variable.dart index 3e43d90f5fd..1dd9acc468a 100644 --- a/packages/devtools_app/lib/src/shared/console/widgets/expandable_variable.dart +++ b/packages/devtools_app/lib/src/shared/console/widgets/expandable_variable.dart @@ -39,22 +39,22 @@ class ExpandableVariable extends StatelessWidget { // TODO(kenz): preserve expanded state of tree on switching frames and // on stepping. return TreeView( - dataRootsListenable: - FixedValueListenable>([variable]), - dataDisplayProvider: dataDisplayProvider ?? + dataRootsListenable: FixedValueListenable>([ + variable, + ]), + dataDisplayProvider: + dataDisplayProvider ?? (variable, onPressed) => DisplayProvider( - variable: variable, - onTap: onPressed, - onCopy: onCopy, - ), + variable: variable, + onTap: onPressed, + onCopy: onCopy, + ), onItemSelected: onItemPressed, isSelectable: isSelectable, ); } - Future onItemPressed( - DartObjectNode v, - ) async { + Future onItemPressed(DartObjectNode v) async { // On expansion, lazily build the variables tree for performance reasons. if (v.isExpanded) { await Future.wait(v.children.map(buildVariablesTree)); diff --git a/packages/devtools_app/lib/src/shared/console/widgets/help_dialog.dart b/packages/devtools_app/lib/src/shared/console/widgets/help_dialog.dart index 5b9d102cfe4..b564cb4582e 100644 --- a/packages/devtools_app/lib/src/shared/console/widgets/help_dialog.dart +++ b/packages/devtools_app/lib/src/shared/console/widgets/help_dialog.dart @@ -40,10 +40,7 @@ Use debug console to: Assign previously evaluated objects to variable using $0, $1 … $5. Example: ''', ), - TextSpan( - text: r'var x = $0', - style: theme.fixedFontStyle, - ), + TextSpan(text: r'var x = $0', style: theme.fixedFontStyle), ], ), ), @@ -51,14 +48,13 @@ Example: ''', // TODO(polina-c): create content and change url. url: 'https://docs.flutter.dev/tools/devtools/console', gaScreenName: gac.console, - gaSelectedItemDescription: - gac.topicDocumentationLink(_documentationTopic), + gaSelectedItemDescription: gac.topicDocumentationLink( + _documentationTopic, + ), ), ], ), - actions: const [ - DialogCloseButton(), - ], + actions: const [DialogCloseButton()], ); } } diff --git a/packages/devtools_app/lib/src/shared/development_helpers.dart b/packages/devtools_app/lib/src/shared/development_helpers.dart index 15af867dd12..e054a049ba5 100644 --- a/packages/devtools_app/lib/src/shared/development_helpers.dart +++ b/packages/devtools_app/lib/src/shared/development_helpers.dart @@ -59,8 +59,7 @@ const _debugDevToolsExtensions = false; List debugHandleRefreshAvailableExtensions({ bool includeRuntime = true, -}) => - StubDevToolsExtensions.extensions(includeRuntime: includeRuntime); +}) => StubDevToolsExtensions.extensions(includeRuntime: includeRuntime); ExtensionEnabledState debugHandleExtensionEnabledState({ required String extensionName, @@ -195,18 +194,13 @@ abstract class StubDevToolsExtensions { /// connection. static List extensions({ bool includeRuntime = true, - }) => - [ - if (includeRuntime) ...[ - fooExtension, - providerExtension, - someToolExtension, - ], - barExtension, - newerBarExtension, - bazExtension, - duplicateFooExtension, - ]; + }) => [ + if (includeRuntime) ...[fooExtension, providerExtension, someToolExtension], + barExtension, + newerBarExtension, + bazExtension, + duplicateFooExtension, + ]; } /// Enable this flag to debug the DevTools survey logic. @@ -219,24 +213,22 @@ bool debugSurvey = false; /// The survey metadata that will be used instead of the live data from /// 'https://storage.googleapis.com/flutter-uxr/surveys/devtools-survey-metadata.json' /// when [debugSurvey] is true. -final debugSurveyMetadata = DevToolsSurvey.fromJson( - { - '_comments': [ - 'uniqueId must be updated with each new survey so DevTools knows to re-prompt users.', - 'title should not exceed 45 characters.', - 'startDate and endDate should follow ISO 8601 standard with a timezone offset.', - ], - 'uniqueId': '2024-Q2', - 'title': 'Take our survey to help us improve DevTools!', - 'url': 'https://google.qualtrics.com/jfe/form/SV_2l4XcyscF8mQtDM', - 'startDate': '2024-06-18T09:00:00-07:00', - 'endDate': '2024-07-02T09:00:00-07:00', - 'minDevToolsVersion': '2.35.0', - // This list is optional and can be used to limit the survey to a specific - // set of users based on their development environment. - 'devEnvironments': ['Android-Studio', 'IntelliJ-IDEA', 'VSCode', 'CLI'], - }, -); +final debugSurveyMetadata = DevToolsSurvey.fromJson({ + '_comments': [ + 'uniqueId must be updated with each new survey so DevTools knows to re-prompt users.', + 'title should not exceed 45 characters.', + 'startDate and endDate should follow ISO 8601 standard with a timezone offset.', + ], + 'uniqueId': '2024-Q2', + 'title': 'Take our survey to help us improve DevTools!', + 'url': 'https://google.qualtrics.com/jfe/form/SV_2l4XcyscF8mQtDM', + 'startDate': '2024-06-18T09:00:00-07:00', + 'endDate': '2024-07-02T09:00:00-07:00', + 'minDevToolsVersion': '2.35.0', + // This list is optional and can be used to limit the survey to a specific + // set of users based on their development environment. + 'devEnvironments': ['Android-Studio', 'IntelliJ-IDEA', 'VSCode', 'CLI'], +}); /// Enable this flag to debug Perfetto trace processing in the Performance /// screen. @@ -264,10 +256,7 @@ const debugTimers = !kReleaseMode && false; /// run to stdout. /// /// This will only time the operation when [debugTimers] is true. -void debugTimeSync( - void Function() callback, { - required String debugName, -}) { +void debugTimeSync(void Function() callback, {required String debugName}) { if (!debugTimers) { callback(); return; diff --git a/packages/devtools_app/lib/src/shared/diagnostics/dap_object_node.dart b/packages/devtools_app/lib/src/shared/diagnostics/dap_object_node.dart index 0427229ee64..0342e6eb8e6 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/dap_object_node.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/dap_object_node.dart @@ -11,7 +11,7 @@ import '../primitives/trees.dart'; class DapObjectNode extends TreeNode { DapObjectNode({required this.variable, required VmServiceWrapper service}) - : _service = service; + : _service = service; final dap.Variable variable; final VmServiceWrapper _service; @@ -27,18 +27,11 @@ class DapObjectNode extends TreeNode { if (!hasChildren) return; final variablesResponse = await _service.dapVariablesRequest( - dap.VariablesArguments( - variablesReference: variable.variablesReference, - ), + dap.VariablesArguments(variablesReference: variable.variablesReference), ); final children = variablesResponse?.variables ?? []; for (final child in children) { - addChild( - DapObjectNode( - variable: child, - service: _service, - ), - ); + addChild(DapObjectNode(variable: child, service: _service)); } } 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 78d80c02c80..c0d491019b6 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 @@ -29,8 +29,8 @@ class DartObjectNode extends TreeNode { this.artificialName = false, this.artificialValue = false, this.isRerootable = false, - }) : _offset = offset, - _childCount = childCount { + }) : _offset = offset, + _childCount = childCount { indentChildren = ref?.diagnostic?.style != DiagnosticsTreeStyle.flat; } @@ -130,18 +130,18 @@ class DartObjectNode extends TreeNode { artificialValue: true, childCount: list?.length ?? 0, )..addAllChildren([ - if (list != null) - for (int i = 0; i < list.length; ++i) - DartObjectNode.fromValue( - name: '[$i]', - value: displayNameBuilder?.call(list[i]) ?? list[i], - isolateRef: isolateRef, - artificialName: true, - artificialValue: artificialChildValues, - )..addAllChildren([ - if (childBuilder != null) ...childBuilder(list[i]), - ]), - ]); + if (list != null) + for (int i = 0; i < list.length; ++i) + DartObjectNode.fromValue( + name: '[$i]', + value: displayNameBuilder?.call(list[i]) ?? list[i], + isolateRef: isolateRef, + artificialName: true, + artificialValue: artificialChildValues, + )..addAllChildren([ + if (childBuilder != null) ...childBuilder(list[i]), + ]), + ]); } factory DartObjectNode.create( @@ -151,18 +151,12 @@ class DartObjectNode extends TreeNode { final value = variable.value; return DartObjectNode._( name: variable.name, - ref: GenericInstanceRef( - isolateRef: isolateRef, - value: value, - ), + ref: GenericInstanceRef(isolateRef: isolateRef, value: value), ); } factory DartObjectNode.text(String text) { - return DartObjectNode._( - text: text, - artificialName: true, - ); + return DartObjectNode._(text: text, artificialName: true); } factory DartObjectNode.grouping( @@ -316,9 +310,10 @@ class DartObjectNode extends TreeNode { // to `children.length` if it's not provide (this means we don't get // the count until the record is expanded): final count = value.length ?? children.length; - valueStr = count == 0 - ? 'Record' - : 'Record ($count ${pluralize('field', count)})'; + valueStr = + count == 0 + ? 'Record' + : 'Record ($count ${pluralize('field', count)})'; } else if (value.valueAsString == null) { valueStr = value.classRef?.name ?? ''; } else { 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 6a850531738..9e723e0937c 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/diagnostics_node.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/diagnostics_node.dart @@ -20,8 +20,9 @@ import 'primitives/source_location.dart'; final diagnosticLevelUtils = EnumUtils(DiagnosticLevel.values); -final treeStyleUtils = - EnumUtils(DiagnosticsTreeStyle.values); +final treeStyleUtils = EnumUtils( + DiagnosticsTreeStyle.values, +); /// Defines diagnostics data for a [value]. /// @@ -79,10 +80,7 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { final width = json['width'] as String?; final height = json['height'] as String?; if (width == null || height == null) return null; - return Size( - double.parse(width), - double.parse(height), - ); + return Size(double.parse(width), double.parse(height)); } static FlexFit deserializeFlexFit(String? flexFit) { @@ -147,8 +145,8 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { RemoteDiagnosticsNode? _parentRenderElement; BoxConstraints get constraints => deserializeConstraints( - json['constraints'] as Map? ?? {}, - ); + json['constraints'] as Map? ?? {}, + ); BoxParentData get parentData => deserializeParentData(json['parentData'] as Map? ?? {}); @@ -252,8 +250,10 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { /// Description to show if the node has no displayed properties or children. String? getEmptyBodyDescription() => getStringMember('emptyBodyDescription'); - late DiagnosticsTreeStyle style = - getStyleMember('style', DiagnosticsTreeStyle.sparse); + late DiagnosticsTreeStyle style = getStyleMember( + 'style', + DiagnosticsTreeStyle.sparse, + ); /// Dart class defining the diagnostic node. /// For example, DiagnosticProperty, IntProperty, StringProperty, etc. @@ -559,8 +559,10 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { default: return _valueProperties = Future.value(); } - _valueProperties = - objectGroupApi?.getDartObjectProperties(valueRef, propertyNames); + _valueProperties = objectGroupApi?.getDartObjectProperties( + valueRef, + propertyNames, + ); } return _valueProperties; } @@ -662,8 +664,9 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { final newHiddenValue = !_groupIsHidden; _groupIsHidden = newHiddenValue; if (isHideableGroupLeader) { - _hideableGroupSubordinates - ?.forEach((node) => node.groupIsHidden = newHiddenValue); + _hideableGroupSubordinates?.forEach( + (node) => node.groupIsHidden = newHiddenValue, + ); } } @@ -697,11 +700,7 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { } Future> _getChildrenHelper() { - return objectGroupApi!.getChildren( - valueRef, - isSummaryTree, - this, - ); + return objectGroupApi!.getChildren(valueRef, isSummaryTree, this); } void _maybePopulateChildren() { @@ -713,8 +712,12 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { if (jsonArray?.isNotEmpty == true) { final nodes = []; for (final element in jsonArray!.cast>()) { - final child = - RemoteDiagnosticsNode(element, objectGroupApi, false, parent); + final child = RemoteDiagnosticsNode( + element, + objectGroupApi, + false, + parent, + ); child.parent = this; nodes.add(child); } diff --git a/packages/devtools_app/lib/src/shared/diagnostics/generic_instance_reference.dart b/packages/devtools_app/lib/src/shared/diagnostics/generic_instance_reference.dart index 04df29b800a..847dea152f1 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/generic_instance_reference.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/generic_instance_reference.dart @@ -73,12 +73,12 @@ class ObjectReferences extends GenericInstanceRef { ObjectReferences ref, { RefNodeType? refNodeType, HeapObject? heapSelection, - }) : refNodeType = refNodeType ?? ref.refNodeType, - super( - isolateRef: ref.isolateRef, - value: ref.value, - heapSelection: heapSelection ?? ref.heapSelection, - ); + }) : refNodeType = refNodeType ?? ref.refNodeType, + super( + isolateRef: ref.isolateRef, + value: ref.value, + heapSelection: heapSelection ?? ref.heapSelection, + ); final RefNodeType refNodeType; @@ -119,8 +119,7 @@ enum RefNodeType { liveInRefs(RefDirection.inbound), /// Subitem of [liveRefRoot] for outbound live references. - liveOutRefs(RefDirection.outbound), - ; + liveOutRefs(RefDirection.outbound); const RefNodeType([this.direction]); diff --git a/packages/devtools_app/lib/src/shared/diagnostics/inspector_service.dart b/packages/devtools_app/lib/src/shared/diagnostics/inspector_service.dart index ce3488cf84a..dfa4d67d200 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/inspector_service.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/inspector_service.dart @@ -38,15 +38,15 @@ abstract class InspectorServiceBase extends DisposableController required this.serviceExtensionPrefix, required String inspectorLibraryUri, ValueListenable? evalIsolate, - }) : assert(serviceConnection.serviceManager.connectedAppInitialized), - assert(serviceConnection.serviceManager.service != null), - clients = {}, - inspectorLibrary = EvalOnDartLibrary( - inspectorLibraryUri, - serviceConnection.serviceManager.service!, - serviceManager: serviceConnection.serviceManager, - isolate: evalIsolate, - ) { + }) : assert(serviceConnection.serviceManager.connectedAppInitialized), + assert(serviceConnection.serviceManager.service != null), + clients = {}, + inspectorLibrary = EvalOnDartLibrary( + inspectorLibraryUri, + serviceConnection.serviceManager.service!, + serviceManager: serviceConnection.serviceManager, + isolate: evalIsolate, + ) { _lastMainIsolate = serviceConnection.serviceManager.isolateManager.mainIsolate.value; addAutoDisposeListener( @@ -124,8 +124,9 @@ abstract class InspectorServiceBase extends DisposableController Future invokeBoolServiceMethodNoArgs(String methodName) async { return useDaemonApi ? await invokeServiceMethodDaemonNoGroupArgs(methodName) == true - : (await invokeServiceMethodObservatoryNoGroup(methodName)) - ?.valueAsString == + : (await invokeServiceMethodObservatoryNoGroup( + methodName, + ))?.valueAsString == 'true'; } @@ -159,17 +160,18 @@ abstract class InspectorServiceBase extends DisposableController if (!serviceConnection.serviceManager.serviceExtensionManager .isServiceExtensionAvailable(callMethodName)) { final available = await serviceConnection - .serviceManager.serviceExtensionManager + .serviceManager + .serviceExtensionManager .waitForServiceExtensionAvailable(callMethodName); if (!available) return {'result': null}; } - final r = - await serviceConnection.serviceManager.service!.callServiceExtension( - callMethodName, - isolateId: isolateRef!.id, - args: args, - ); + final r = await serviceConnection.serviceManager.service! + .callServiceExtension( + callMethodName, + isolateId: isolateRef!.id, + args: args, + ); final json = r.json!; if (json['errorMessage'] != null) { throw Exception('$methodName -- ${json['errorMessage']}'); @@ -182,22 +184,24 @@ abstract class InspectorServiceBase extends DisposableController /// the inspector. class InspectorService extends InspectorServiceBase { InspectorService() - : super( - clientInspectorName: 'WidgetInspectorService', - serviceExtensionPrefix: inspectorExtensionPrefix, - inspectorLibraryUri: _inspectorLibraryUri, - evalIsolate: - serviceConnection.serviceManager.isolateManager.mainIsolate, - ) { + : super( + clientInspectorName: 'WidgetInspectorService', + serviceExtensionPrefix: inspectorExtensionPrefix, + inspectorLibraryUri: _inspectorLibraryUri, + evalIsolate: + serviceConnection.serviceManager.isolateManager.mainIsolate, + ) { // Note: We do not need to listen to event history here because the // inspector uses a separate API to get the current inspector selection. autoDisposeStreamSubscription( - serviceConnection.serviceManager.service!.onExtensionEvent - .listen(onExtensionVmServiceReceived), + serviceConnection.serviceManager.service!.onExtensionEvent.listen( + onExtensionVmServiceReceived, + ), ); autoDisposeStreamSubscription( - serviceConnection.serviceManager.service!.onDebugEvent - .listen(onDebugVmServiceReceived), + serviceConnection.serviceManager.service!.onDebugEvent.listen( + onDebugVmServiceReceived, + ), ); } @@ -418,8 +422,10 @@ class InspectorService extends InspectorServiceBase { RemoteDiagnosticsNode? _currentSelection; InspectorObjectGroupManager get _selectionGroups { - return _cachedSelectionGroups ??= - InspectorObjectGroupManager(this, 'selection'); + return _cachedSelectionGroups ??= InspectorObjectGroupManager( + this, + 'selection', + ); } InspectorObjectGroupManager? _cachedSelectionGroups; @@ -464,9 +470,8 @@ class InspectorService extends InspectorServiceBase { /// This class has additional descenders in Google3. abstract class InspectorObjectGroupBase extends InspectorObjectGroupApi { - InspectorObjectGroupBase( - String debugName, - ) : groupName = '${debugName}_${InspectorServiceBase.nextGroupId}' { + InspectorObjectGroupBase(String debugName) + : groupName = '${debugName}_${InspectorServiceBase.nextGroupId}' { InspectorServiceBase.nextGroupId++; } @@ -492,12 +497,13 @@ abstract class InspectorObjectGroupBase @override Future dispose() { // No need to dispose the group if the isolate is already gone. - final disposeComplete = inspectorService.isolateRef != null - ? invokeVoidServiceMethod( - WidgetInspectorServiceExtensions.disposeGroup.name, - groupName, - ) - : Future.value(); + final disposeComplete = + inspectorService.isolateRef != null + ? invokeVoidServiceMethod( + WidgetInspectorServiceExtensions.disposeGroup.name, + groupName, + ) + : Future.value(); disposed = true; return disposeComplete; } @@ -509,11 +515,11 @@ abstract class InspectorObjectGroupBase if (disposed) return null; return useDaemonApi ? parseDiagnosticsNodeDaemon( - invokeServiceMethodDaemonInspectorRef(methodName, ref), - ) + invokeServiceMethodDaemonInspectorRef(methodName, ref), + ) : parseDiagnosticsNodeObservatory( - invokeServiceMethodObservatoryInspectorRef(methodName, ref), - ); + invokeServiceMethodObservatoryInspectorRef(methodName, ref), + ); } Future invokeServiceMethodWithArgReturningNode( @@ -523,11 +529,11 @@ abstract class InspectorObjectGroupBase if (disposed) return null; return useDaemonApi ? parseDiagnosticsNodeDaemon( - invokeServiceMethodDaemonArg(methodName, arg, groupName), - ) + invokeServiceMethodDaemonArg(methodName, arg, groupName), + ) : parseDiagnosticsNodeObservatory( - invokeServiceMethodObservatoryWithGroupName1(methodName, arg), - ); + invokeServiceMethodObservatoryWithGroupName1(methodName, arg), + ); } Future invokeServiceMethodDaemonArg( @@ -572,10 +578,9 @@ abstract class InspectorObjectGroupBase String methodName, [ String? objectGroup, ]) { - return invokeServiceMethodDaemonParams( - methodName, - {'objectGroup': objectGroup ?? groupName}, - ); + return invokeServiceMethodDaemonParams(methodName, { + 'objectGroup': objectGroup ?? groupName, + }); } Future invokeServiceMethodObservatory1( @@ -608,7 +613,8 @@ abstract class InspectorObjectGroupBase if (!serviceConnection.serviceManager.serviceExtensionManager .isServiceExtensionAvailable(callMethodName)) { final available = await serviceConnection - .serviceManager.serviceExtensionManager + .serviceManager + .serviceExtensionManager .waitForServiceExtensionAvailable(callMethodName); if (!available) return null; } @@ -625,12 +631,12 @@ abstract class InspectorObjectGroupBase } return inspectorLibrary.addRequest(this, () async { - final r = - await serviceConnection.serviceManager.service!.callServiceExtension( - extension, - isolateId: inspectorService.isolateRef!.id, - args: args, - ); + final r = await serviceConnection.serviceManager.service! + .callServiceExtension( + extension, + isolateId: inspectorService.isolateRef!.id, + args: args, + ); if (disposed) return null; final json = r.json!; if (json['errorMessage'] != null) { @@ -844,15 +850,15 @@ abstract class InspectorObjectGroupBase if (disposed) return const []; return useDaemonApi ? parseDiagnosticsNodesDaemon( - invokeServiceMethodDaemonInspectorRef(methodName, instanceRef), - parent, - isProperty, - ) + invokeServiceMethodDaemonInspectorRef(methodName, instanceRef), + parent, + isProperty, + ) : parseDiagnosticsNodesObservatory( - invokeServiceMethodObservatoryInspectorRef(methodName, instanceRef), - parent, - isProperty, - ); + invokeServiceMethodObservatoryInspectorRef(methodName, instanceRef), + parent, + isProperty, + ); } /// Evaluate an expression where `object` references the [inspectorRef] or @@ -937,10 +943,7 @@ abstract class InspectorObjectGroupBase /// will be skipped. This means that clients should not have to write any /// special logic to handle orphaned requests. class ObjectGroup extends InspectorObjectGroupBase { - ObjectGroup( - super.debugName, - this.inspectorService, - ); + ObjectGroup(super.debugName, this.inspectorService); @override final InspectorService inspectorService; @@ -981,7 +984,7 @@ class ObjectGroup extends InspectorObjectGroupBase { ); } -// TODO these ones could be not needed. + // TODO these ones could be not needed. /* TODO(jacobr): this probably isn't needed. Future> getParentChain(DiagnosticsNode target) async { if (disposed) return null; @@ -1059,19 +1062,19 @@ class ObjectGroup extends InspectorObjectGroupBase { } return useDaemonApi ? handleSetSelectionDaemon( - invokeServiceMethodDaemonInspectorRef( - WidgetInspectorServiceExtensions.setSelectionById.name, - selection, - ), - uiAlreadyUpdated, - ) + invokeServiceMethodDaemonInspectorRef( + WidgetInspectorServiceExtensions.setSelectionById.name, + selection, + ), + uiAlreadyUpdated, + ) : handleSetSelectionObservatory( - invokeServiceMethodObservatoryInspectorRef( - WidgetInspectorServiceExtensions.setSelectionById.name, - selection, - ), - uiAlreadyUpdated, - ); + invokeServiceMethodObservatoryInspectorRef( + WidgetInspectorServiceExtensions.setSelectionById.name, + selection, + ), + uiAlreadyUpdated, + ); } Future setSelection(GenericInstanceRef selection) async { diff --git a/packages/devtools_app/lib/src/shared/diagnostics/object_group_api.dart b/packages/devtools_app/lib/src/shared/diagnostics/object_group_api.dart index a0630e8b620..216797e9610 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/object_group_api.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/object_group_api.dart @@ -15,8 +15,7 @@ abstract class InspectorObjectGroupApi Future setSelectionInspector( InspectorInstanceRef selection, bool uiAlreadyUpdated, - ) => - throw UnimplementedError(); + ) => throw UnimplementedError(); Future?> getEnumPropertyValues( InspectorInstanceRef ref, diff --git a/packages/devtools_app/lib/src/shared/diagnostics/primitives/source_location.dart b/packages/devtools_app/lib/src/shared/diagnostics/primitives/source_location.dart index 246848ce6cd..1db0d0c4a24 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/primitives/source_location.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/primitives/source_location.dart @@ -18,10 +18,7 @@ class InspectorSourceLocation { final Map json; final InspectorSourceLocation? parent; - String? get path => JsonUtils.getStringMember( - json, - _JsonFields.file, - ); + String? get path => JsonUtils.getStringMember(json, _JsonFields.file); String? getFile() { final fileName = path; diff --git a/packages/devtools_app/lib/src/shared/diagnostics/references.dart b/packages/devtools_app/lib/src/shared/diagnostics/references.dart index ab772375eb2..7c01c4ede94 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/references.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/references.dart @@ -44,15 +44,10 @@ HeapObject _refreshStaticSelection( final index = selection.heap.indexByCode[code]; if (index == null) return selection; - return HeapObject( - selection.heap, - index: index, - ); + return HeapObject(selection.heap, index: index); } -Future addChildReferences( - DartObjectNode variable, -) async { +Future addChildReferences(DartObjectNode variable) async { final ref = variable.ref!; if (ref is! ObjectReferences) { throw StateError('Wrong type: ${ref.runtimeType}'); @@ -62,8 +57,10 @@ Future addChildReferences( switch (refNodeType) { case RefNodeType.refRoot: - final selection = - _refreshStaticSelection(ref.heapSelection, ref.instanceRef); + final selection = _refreshStaticSelection( + ref.heapSelection, + ref.instanceRef, + ); variable.addAllChildren([ if (ref.instanceRef != null) @@ -104,41 +101,43 @@ Future addChildReferences( return; case RefNodeType.staticInRefs: - final children = ref.heapSelection - .references(ref.refNodeType.direction!) - .where((s) => !s.className!.isNull) - .map( - (s) => DartObjectNode.references( - s.className!.className, - ObjectReferences( - refNodeType: RefNodeType.staticInRefs, - heapSelection: s, - isolateRef: ref.isolateRef, - value: null, - ), - isRerootable: true, - ), - ) - .toList(); + final children = + ref.heapSelection + .references(ref.refNodeType.direction!) + .where((s) => !s.className!.isNull) + .map( + (s) => DartObjectNode.references( + s.className!.className, + ObjectReferences( + refNodeType: RefNodeType.staticInRefs, + heapSelection: s, + isolateRef: ref.isolateRef, + value: null, + ), + isRerootable: true, + ), + ) + .toList(); variable.addAllChildren(children); return; case RefNodeType.staticOutRefs: - final children = ref.heapSelection - .references(ref.refNodeType.direction!) - .where((s) => !s.className!.isNull) - .map( - (s) => DartObjectNode.references( - '${s.className!.className}, ${prettyPrintRetainedSize(s.retainedSize)}', - ObjectReferences( - refNodeType: RefNodeType.staticOutRefs, - heapSelection: s, - isolateRef: ref.isolateRef, - value: null, - ), - isRerootable: true, - ), - ) - .toList(); + final children = + ref.heapSelection + .references(ref.refNodeType.direction!) + .where((s) => !s.className!.isNull) + .map( + (s) => DartObjectNode.references( + '${s.className!.className}, ${prettyPrintRetainedSize(s.retainedSize)}', + ObjectReferences( + refNodeType: RefNodeType.staticOutRefs, + heapSelection: s, + isolateRef: ref.isolateRef, + value: null, + ), + isRerootable: true, + ), + ) + .toList(); variable.addAllChildren(children); return; case RefNodeType.liveRefRoot: @@ -162,12 +161,11 @@ Future addChildReferences( final limit = preferences.memory.refLimit.value; final refs = (await serviceConnection.serviceManager.service!.getInboundReferences( - ref.isolateRef.id!, - value.id!, - limit + 1, - )) - .references ?? - []; + ref.isolateRef.id!, + value.id!, + limit + 1, + )).references ?? + []; final refsToShow = min(limit, refs.length); final children = []; diff --git a/packages/devtools_app/lib/src/shared/diagnostics/tree_builder.dart b/packages/devtools_app/lib/src/shared/diagnostics/tree_builder.dart index 4dc184d5a14..95673a79018 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/tree_builder.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/tree_builder.dart @@ -54,11 +54,7 @@ Future _addDiagnosticsIfNeeded( if (properties == null || service == null || isolateRef == null) return; await _addExpandableChildren( variable, - await createVariablesForDiagnostics( - service, - properties, - isolateRef, - ), + await createVariablesForDiagnostics(service, properties, isolateRef), expandAll: true, ); } @@ -186,12 +182,7 @@ void _addChildrenToInstanceVariable({ }) { switch (value.kind) { case InstanceKind.kMap: - variable.addAllChildren( - createVariablesForMap( - value, - isolateRef, - ), - ); + variable.addAllChildren(createVariablesForMap(value, isolateRef)); break; case InstanceKind.kList: variable.addAllChildren( @@ -199,9 +190,7 @@ void _addChildrenToInstanceVariable({ ); break; case InstanceKind.kRecord: - variable.addAllChildren( - createVariablesForRecords(value, isolateRef), - ); + variable.addAllChildren(createVariablesForRecords(value, isolateRef)); break; case InstanceKind.kUint8ClampedList: case InstanceKind.kUint8List: @@ -217,29 +206,19 @@ void _addChildrenToInstanceVariable({ case InstanceKind.kInt32x4List: case InstanceKind.kFloat32x4List: case InstanceKind.kFloat64x2List: - variable.addAllChildren( - createVariablesForBytes(value, isolateRef), - ); + variable.addAllChildren(createVariablesForBytes(value, isolateRef)); break; case InstanceKind.kRegExp: - variable.addAllChildren( - createVariablesForRegExp(value, isolateRef), - ); + variable.addAllChildren(createVariablesForRegExp(value, isolateRef)); break; case InstanceKind.kClosure: - variable.addAllChildren( - createVariablesForClosure(value, isolateRef), - ); + variable.addAllChildren(createVariablesForClosure(value, isolateRef)); break; case InstanceKind.kReceivePort: - variable.addAllChildren( - createVariablesForReceivePort(value, isolateRef), - ); + variable.addAllChildren(createVariablesForReceivePort(value, isolateRef)); break; case InstanceKind.kType: - variable.addAllChildren( - createVariablesForType(value, isolateRef), - ); + variable.addAllChildren(createVariablesForType(value, isolateRef)); break; case InstanceKind.kTypeParameter: variable.addAllChildren( @@ -257,9 +236,7 @@ void _addChildrenToInstanceVariable({ ); break; case InstanceKind.kStackTrace: - variable.addAllChildren( - createVariablesForStackTrace(value, isolateRef), - ); + variable.addAllChildren(createVariablesForStackTrace(value, isolateRef)); break; case InstanceKind.kMirrorReference: variable.addAllChildren( @@ -267,9 +244,7 @@ void _addChildrenToInstanceVariable({ ); break; case InstanceKind.kUserTag: - variable.addAllChildren( - createVariablesForUserTag(value, isolateRef), - ); + variable.addAllChildren(createVariablesForUserTag(value, isolateRef)); break; default: break; @@ -281,11 +256,7 @@ void _addChildrenToInstanceVariable({ if (value.fields != null && value.kind != InstanceKind.kRecord) { variable.addAllChildren( - createVariablesForFields( - value, - isolateRef, - existingNames: existingNames, - ), + createVariablesForFields(value, isolateRef, existingNames: existingNames), ); } } @@ -300,15 +271,11 @@ Future _addValueItems( switch (value.runtimeType) { case const (Func): final function = value as Func; - variable.addAllChildren( - createVariablesForFunc(function, isolateRef), - ); + variable.addAllChildren(createVariablesForFunc(function, isolateRef)); break; case const (Context): final context = value as Context; - variable.addAllChildren( - createVariablesForContext(context, isolateRef), - ); + variable.addAllChildren(createVariablesForContext(context, isolateRef)); break; } } else if (value is! String && value is! num && value is! bool) { @@ -359,9 +326,7 @@ Future _addInspectorItems( ); } catch (e) { if (e is! SentinelException) { - _log.warning( - 'Caught $e accessing the value of an object', - ); + _log.warning('Caught $e accessing the value of an object'); } } } @@ -399,11 +364,7 @@ Future buildVariablesTree( final diagnostic = ref.diagnostic; final value = variable.value; - await _addDiagnosticsIfNeeded( - diagnostic, - isolateRef, - variable, - ); + await _addDiagnosticsIfNeeded(diagnostic, isolateRef, variable); try { if (ref is ObjectReferences) { @@ -437,10 +398,7 @@ Future buildVariablesTree( expandAll, ); - await _addInspectorItems( - variable, - isolateRef, - ); + await _addInspectorItems(variable, isolateRef); variable.treeInitializeComplete = true; } diff --git a/packages/devtools_app/lib/src/shared/diagnostics/variable_factory.dart b/packages/devtools_app/lib/src/shared/diagnostics/variable_factory.dart index b69ede4bd8e..da86fce9fc1 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/variable_factory.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/variable_factory.dart @@ -305,8 +305,9 @@ Future _buildVariable( InspectorObjectGroupApi objectGroup, IsolateRef? isolateRef, ) async { - final instanceRef = - await objectGroup.toObservatoryInstanceRef(diagnostic.valueRef); + final instanceRef = await objectGroup.toObservatoryInstanceRef( + diagnostic.valueRef, + ); return DartObjectNode.fromValue( name: diagnostic.name, value: instanceRef, @@ -469,10 +470,7 @@ List createVariablesForSets( ) { final elements = instance.elements ?? []; return elements.map((element) { - return DartObjectNode.fromValue( - value: element, - isolateRef: isolateRef, - ); + return DartObjectNode.fromValue(value: element, isolateRef: isolateRef); }).toList(); } @@ -555,10 +553,7 @@ List createVariablesForFields( final name = field.name; if (name is! String) { result.add( - DartObjectNode.fromValue( - value: field.value, - isolateRef: isolateRef, - ), + DartObjectNode.fromValue(value: field.value, isolateRef: isolateRef), ); } else { if (existingNames != null && existingNames.contains(name)) continue; diff --git a/packages/devtools_app/lib/src/shared/diagnostics_text_styles.dart b/packages/devtools_app/lib/src/shared/diagnostics_text_styles.dart index 983bfb95ea0..9031d3c9354 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics_text_styles.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics_text_styles.dart @@ -9,37 +9,31 @@ import 'package:flutter/material.dart'; // ignore: avoid_classes_with_only_static_members class DiagnosticsTextStyles { static TextStyle unimportant(ColorScheme colorScheme) => TextStyle( - color: - colorScheme.isLight ? Colors.grey.shade500 : Colors.grey.shade600, - ); + color: colorScheme.isLight ? Colors.grey.shade500 : Colors.grey.shade600, + ); static TextStyle regular(ColorScheme colorScheme) => TextStyle( - // The font size when not specified seems to be 14, but specify here since we - // are scaling based on this font size in [IdeTheme]. - fontSize: defaultFontSize, - color: colorScheme.onSurface, - ); + // The font size when not specified seems to be 14, but specify here since we + // are scaling based on this font size in [IdeTheme]. + fontSize: defaultFontSize, + color: colorScheme.onSurface, + ); static TextStyle warning(ColorScheme colorScheme) => TextStyle( - color: colorScheme.isLight - ? Colors.orange.shade900 - : Colors.orange.shade400, - ); + color: + colorScheme.isLight ? Colors.orange.shade900 : Colors.orange.shade400, + ); - static TextStyle error(ColorScheme colorScheme) => TextStyle( - color: colorScheme.error, - ); + static TextStyle error(ColorScheme colorScheme) => + TextStyle(color: colorScheme.error); static TextStyle link(ColorScheme colorScheme) => TextStyle( - color: - colorScheme.isLight ? Colors.blue.shade700 : Colors.blue.shade300, - decoration: TextDecoration.underline, - ); - - static const regularBold = TextStyle( - fontWeight: FontWeight.w700, + color: colorScheme.isLight ? Colors.blue.shade700 : Colors.blue.shade300, + decoration: TextDecoration.underline, ); + static const regularBold = TextStyle(fontWeight: FontWeight.w700); + static TextStyle textStyleForLevel( DiagnosticLevel level, ColorScheme colorScheme, diff --git a/packages/devtools_app/lib/src/shared/dialogs.dart b/packages/devtools_app/lib/src/shared/dialogs.dart index af3e5e28538..417c4aaa076 100644 --- a/packages/devtools_app/lib/src/shared/dialogs.dart +++ b/packages/devtools_app/lib/src/shared/dialogs.dart @@ -13,10 +13,7 @@ import 'utils.dart'; /// A dialog, that reports unexpected error and allows to copy details and create issue. class UnexpectedErrorDialog extends StatelessWidget { - const UnexpectedErrorDialog({ - super.key, - required this.additionalInfo, - }); + const UnexpectedErrorDialog({super.key, required this.additionalInfo}); final String additionalInfo; @@ -26,29 +23,28 @@ class UnexpectedErrorDialog extends StatelessWidget { return DevToolsDialog( title: const Text('Unexpected Error'), - content: Text( - additionalInfo, - style: theme.fixedFontStyle, - ), + content: Text(additionalInfo, style: theme.fixedFontStyle), actions: [ DialogTextButton( child: const Text('Copy details'), - onPressed: () => unawaited( - copyToClipboard( - additionalInfo, - successMessage: 'Error details copied to clipboard', - ), - ), + onPressed: + () => unawaited( + copyToClipboard( + additionalInfo, + successMessage: 'Error details copied to clipboard', + ), + ), ), DialogTextButton( child: const Text('Create issue'), - onPressed: () => unawaited( - launchUrlWithErrorHandling( - devToolsEnvironmentParameters - .issueTrackerLink(additionalInfo: additionalInfo) - .url, - ), - ), + onPressed: + () => unawaited( + launchUrlWithErrorHandling( + devToolsEnvironmentParameters + .issueTrackerLink(additionalInfo: additionalInfo) + .url, + ), + ), ), const DialogCloseButton(), ], diff --git a/packages/devtools_app/lib/src/shared/dtd_manager_extensions.dart b/packages/devtools_app/lib/src/shared/dtd_manager_extensions.dart index 4060d4d7eb6..0a41055fe70 100644 --- a/packages/devtools_app/lib/src/shared/dtd_manager_extensions.dart +++ b/packages/devtools_app/lib/src/shared/dtd_manager_extensions.dart @@ -27,8 +27,9 @@ extension DevToolsDTDExtension on DTDManager { Future analyticsConsentMessage() async { if (!hasConnection) return ''; try { - final response = - await _dtd.analyticsGetConsentMessage(ua.DashTool.devtools); + final response = await _dtd.analyticsGetConsentMessage( + ua.DashTool.devtools, + ); _log.finer('DTDManager.analyticsConsentMessage success'); return response.value!; } catch (e) { @@ -42,8 +43,9 @@ extension DevToolsDTDExtension on DTDManager { Future shouldShowAnalyticsConsentMessage() async { if (!hasConnection) return false; try { - final response = - await _dtd.analyticsShouldShowConsentMessage(ua.DashTool.devtools); + final response = await _dtd.analyticsShouldShowConsentMessage( + ua.DashTool.devtools, + ); final shouldShow = response.value!; _log.finer( 'DTDManager.shouldShowAnalyticsConsentMessage result: $shouldShow', @@ -70,8 +72,9 @@ extension DevToolsDTDExtension on DTDManager { Future analyticsTelemetryEnabled() async { if (!hasConnection) return false; try { - final response = - await _dtd.analyticsTelemetryEnabled(ua.DashTool.devtools); + final response = await _dtd.analyticsTelemetryEnabled( + ua.DashTool.devtools, + ); final enabled = response.value!; _log.finer('DTDManager.analyticsTelemetryEnabled result: $enabled'); return enabled; diff --git a/packages/devtools_app/lib/src/shared/editable_list.dart b/packages/devtools_app/lib/src/shared/editable_list.dart index 18c3ab89890..a42836f09d5 100644 --- a/packages/devtools_app/lib/src/shared/editable_list.dart +++ b/packages/devtools_app/lib/src/shared/editable_list.dart @@ -27,8 +27,8 @@ class EditableList extends StatefulWidget { this.onRefreshTriggered, void Function(String)? onEntryAdded, void Function(String)? onEntryRemoved, - }) : onEntryAdded = onEntryAdded ?? ((entry) => entries.add(entry)), - onEntryRemoved = onEntryRemoved ?? ((entry) => entries.remove(entry)); + }) : onEntryAdded = onEntryAdded ?? ((entry) => entries.add(entry)), + onEntryRemoved = onEntryRemoved ?? ((entry) => entries.remove(entry)); /// The values that will be displayed in the editable list. /// @@ -179,19 +179,19 @@ class EditableListActionBar extends StatelessWidget { const SizedBox(width: densePadding), isRefreshing?.value ?? false ? SizedBox( - width: defaultTextFieldHeight, - height: defaultTextFieldHeight, - child: const Padding( - padding: EdgeInsets.all(densePadding), - child: CircularProgressIndicator(), - ), - ) - : RefreshButton( - gaScreen: gaScreen, - gaSelection: gaRefreshSelection, - onPressed: onRefresh, - minScreenWidthForTextBeforeScaling: double.maxFinite, + width: defaultTextFieldHeight, + height: defaultTextFieldHeight, + child: const Padding( + padding: EdgeInsets.all(densePadding), + child: CircularProgressIndicator(), ), + ) + : RefreshButton( + gaScreen: gaScreen, + gaSelection: gaRefreshSelection, + onPressed: onRefresh, + minScreenWidthForTextBeforeScaling: double.maxFinite, + ), ], ), ); @@ -242,18 +242,12 @@ class EditableListRow extends StatelessWidget { Widget build(BuildContext context) { return Row( children: [ - Expanded( - child: Text(entry), - ), - EditableListCopyDirectoryButton( - value: entry, - ), + Expanded(child: Text(entry)), + EditableListCopyDirectoryButton(value: entry), const SizedBox(width: denseSpacing), EditableListRemoveDirectoryButton( onPressed: () { - onEntryRemoved( - entry, - ); + onEntryRemoved(entry); }, ), ], @@ -263,10 +257,7 @@ class EditableListRow extends StatelessWidget { @visibleForTesting class EditableListCopyDirectoryButton extends StatelessWidget { - const EditableListCopyDirectoryButton({ - super.key, - required this.value, - }); + const EditableListCopyDirectoryButton({super.key, required this.value}); final String value; diff --git a/packages/devtools_app/lib/src/shared/environment_parameters/environment_parameters_external.dart b/packages/devtools_app/lib/src/shared/environment_parameters/environment_parameters_external.dart index b6e25bd2966..e4006bd3525 100644 --- a/packages/devtools_app/lib/src/shared/environment_parameters/environment_parameters_external.dart +++ b/packages/devtools_app/lib/src/shared/environment_parameters/environment_parameters_external.dart @@ -22,11 +22,12 @@ class ExternalDevToolsEnvironmentParameters GaLink issueTrackerLink({String? additionalInfo, String? issueTitle}) { return GaLink( display: _newDevToolsIssueUriDisplay, - url: newDevToolsGitHubIssueUriLengthSafe( - additionalInfo: additionalInfo, - issueTitle: issueTitle, - environment: issueLinkDetails(), - ).toString(), + url: + newDevToolsGitHubIssueUriLengthSafe( + additionalInfo: additionalInfo, + issueTitle: issueTitle, + environment: issueLinkDetails(), + ).toString(), gaScreenName: gac.devToolsMain, gaSelectedItemDescription: gac.feedbackLink, ); @@ -115,8 +116,10 @@ Uri newDevToolsGitHubIssueUriLengthSafe({ } // Truncate the additional info if the URL is too long: - final truncatedInfo = - additionalInfo.substring(0, additionalInfo.length - lengthToCut); + final truncatedInfo = additionalInfo.substring( + 0, + additionalInfo.length - lengthToCut, + ); final truncatedUri = _newDevToolsGitHubIssueUri( additionalInfo: truncatedInfo, @@ -137,10 +140,7 @@ Uri _newDevToolsGitHubIssueUri({ ...environment, ].join('\n'); - return Uri.parse('https://$_newDevToolsIssueUriDisplay').replace( - queryParameters: { - 'title': issueTitle, - 'body': issueBody, - }, - ); + return Uri.parse( + 'https://$_newDevToolsIssueUriDisplay', + ).replace(queryParameters: {'title': issueTitle, 'body': issueBody}); } diff --git a/packages/devtools_app/lib/src/shared/error_badge_manager.dart b/packages/devtools_app/lib/src/shared/error_badge_manager.dart index 9d71a82b323..85b117f63c0 100644 --- a/packages/devtools_app/lib/src/shared/error_badge_manager.dart +++ b/packages/devtools_app/lib/src/shared/error_badge_manager.dart @@ -31,20 +31,20 @@ class ErrorBadgeManager extends DisposableController }; final _activeErrors = >>{ - InspectorScreen.id: ValueNotifier>( - LinkedHashMap(), - ), - }; + InspectorScreen.id: ValueNotifier>( + LinkedHashMap(), + ), + }; void vmServiceOpened(VmServiceWrapper service) { // Ensure structured errors are enabled. unawaited( serviceConnection.serviceManager.serviceExtensionManager .setServiceExtensionState( - extensions.structuredErrors.extension, - enabled: true, - value: true, - ), + extensions.structuredErrors.extension, + enabled: true, + value: true, + ), ); // Log Flutter extension events. @@ -73,11 +73,16 @@ class ErrorBadgeManager extends DisposableController InspectableWidgetError? _extractInspectableError(Event error) { // TODO(dantup): Switch to using the inspectorService from the serviceManager // once Jacob's change to add it lands. - final node = - RemoteDiagnosticsNode(error.extensionData!.data, null, false, null); + final node = RemoteDiagnosticsNode( + error.extensionData!.data, + null, + false, + null, + ); - final errorSummaryNode = - node.inlineProperties.firstWhereOrNull((p) => p.type == 'ErrorSummary'); + final errorSummaryNode = node.inlineProperties.firstWhereOrNull( + (p) => p.type == 'ErrorSummary', + ); final errorMessage = errorSummaryNode?.description; if (errorMessage == null) { return null; @@ -92,8 +97,9 @@ class ErrorBadgeManager extends DisposableController return null; } - final queryParams = - DevToolsQueryParams.fromUrl(devToolsUrlNode.getStringMember('value')!); + final queryParams = DevToolsQueryParams.fromUrl( + devToolsUrlNode.getStringMember('value')!, + ); final inspectorRef = queryParams.inspectorRef ?? ''; return InspectableWidgetError(errorMessage, inspectorRef); @@ -149,8 +155,9 @@ class ErrorBadgeManager extends DisposableController if (errors == null) return; final oldCount = errors.value.length; - final newValue = - Map.fromEntries(errors.value.entries.where((e) => isValid(e.key))); + final newValue = Map.fromEntries( + errors.value.entries.where((e) => isValid(e.key)), + ); if (newValue.length != oldCount) { errors.value = newValue as LinkedHashMap; } diff --git a/packages/devtools_app/lib/src/shared/feature_flags.dart b/packages/devtools_app/lib/src/shared/feature_flags.dart index 73bf7dbdc8a..360145f5c25 100644 --- a/packages/devtools_app/lib/src/shared/feature_flags.dart +++ b/packages/devtools_app/lib/src/shared/feature_flags.dart @@ -23,8 +23,9 @@ bool get enableExperiments => /// "args": [ /// "--dart-define=enable_experiments=true" /// ] -const _experimentsEnabledByEnvironment = - bool.fromEnvironment('enable_experiments'); +const _experimentsEnabledByEnvironment = bool.fromEnvironment( + 'enable_experiments', +); bool _experimentsEnabledFromMain = false; @@ -35,8 +36,10 @@ void setEnableExperiments() { @visibleForTesting bool get enableBeta => enableExperiments || !isExternalBuild; -const _kMemoryDisconnectExperience = - bool.fromEnvironment('memory_disconnect_experience', defaultValue: true); +const _kMemoryDisconnectExperience = bool.fromEnvironment( + 'memory_disconnect_experience', + defaultValue: true, +); // It is ok to have enum-like static only classes. // ignore: avoid_classes_with_only_static_members diff --git a/packages/devtools_app/lib/src/shared/file_import.dart b/packages/devtools_app/lib/src/shared/file_import.dart index 79b36cbc329..ebdc1d6e987 100644 --- a/packages/devtools_app/lib/src/shared/file_import.dart +++ b/packages/devtools_app/lib/src/shared/file_import.dart @@ -37,12 +37,15 @@ class OpenSaveButtonGroup extends StatelessWidget { tooltip: 'Open a file that was previously saved from DevTools', onPressed: () async { ga.select(screenId, gac.openFile); - final importedFile = - await importFileFromPicker(acceptedTypes: const ['json']); + final importedFile = await importFileFromPicker( + acceptedTypes: const ['json'], + ); if (importedFile != null) { - // ignore: use_build_context_synchronously, intentional use. - Provider.of(context, listen: false) - .importData(importedFile, expectedScreenId: screenId); + Provider.of( + // ignore: use_build_context_synchronously, intentional use. + context, + listen: false, + ).importData(importedFile, expectedScreenId: screenId); } else { notificationService.push( 'Something went wrong. Could not open selected file.', @@ -53,12 +56,13 @@ class OpenSaveButtonGroup extends StatelessWidget { ButtonGroupItemData( icon: Icons.file_download, tooltip: 'Save this screen\'s data for offline viewing', - onPressed: onSave != null - ? () { - ga.select(screenId, gac.saveFile); - onSave!.call(); - } - : null, + onPressed: + onSave != null + ? () { + ga.select(screenId, gac.saveFile); + onSave!.call(); + } + : null, ), ], ); @@ -122,10 +126,7 @@ class _FileImportContainerState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ if (title != null) ...[ - Text( - title, - style: TextStyle(fontSize: scaleByFontFactor(18.0)), - ), + Text(title, style: TextStyle(fontSize: scaleByFontFactor(18.0))), const SizedBox(height: extraLargeSpacing), ], CenteredMessage(message: widget.instructions), @@ -156,10 +157,7 @@ class _FileImportContainerState extends State { children: [ Expanded( // TODO(kenz): improve drag over highlight. - child: DragAndDrop( - handleDrop: _handleImportedFile, - child: child, - ), + child: DragAndDrop(handleDrop: _handleImportedFile, child: child), ), ], ); @@ -226,9 +224,10 @@ class _FileImportContainerState extends State { gaSelection: widget.gaSelectionAction!, label: widget.actionText!, elevated: true, - onPressed: importedFile != null - ? () => widget.onAction!(importedFile!) - : null, + onPressed: + importedFile != null + ? () => widget.onAction!(importedFile!) + : null, ), ], ), @@ -237,8 +236,9 @@ class _FileImportContainerState extends State { } Future _importFile() async { - final importedFile = - await importFileFromPicker(acceptedTypes: widget.extensions); + final importedFile = await importFileFromPicker( + acceptedTypes: widget.extensions, + ); if (importedFile != null) { _handleImportedFile(importedFile); } @@ -357,7 +357,8 @@ class DualFileImportContainer extends StatefulWidget { DevToolsJsonFile firstImportedFile, DevToolsJsonFile secondImportedFile, void Function(String error) onError, - ) onAction; + ) + onAction; @override State createState() => @@ -450,13 +451,14 @@ class _DualFileImportContainerState extends State { label: widget.actionText, icon: Icons.highlight, elevated: true, - onPressed: firstImportedFile != null && secondImportedFile != null - ? () => widget.onAction( + onPressed: + firstImportedFile != null && secondImportedFile != null + ? () => widget.onAction( firstImportedFile!, secondImportedFile!, (error) => notificationService.push(error), ) - : null, + : null, ), ], ), diff --git a/packages/devtools_app/lib/src/shared/framework_controller.dart b/packages/devtools_app/lib/src/shared/framework_controller.dart index 2c8569c27cc..d1a6dbd3d0d 100644 --- a/packages/devtools_app/lib/src/shared/framework_controller.dart +++ b/packages/devtools_app/lib/src/shared/framework_controller.dart @@ -36,10 +36,7 @@ class FrameworkController { /// Notify the controller of a connect to VM event. void notifyConnectToVmEvent(Uri serviceProtocolUri, {bool notify = false}) { _connectVmController.add( - ConnectVmEvent( - serviceProtocolUri: serviceProtocolUri, - notify: notify, - ), + ConnectVmEvent(serviceProtocolUri: serviceProtocolUri, notify: notify), ); } diff --git a/packages/devtools_app/lib/src/shared/history_viewport.dart b/packages/devtools_app/lib/src/shared/history_viewport.dart index 53a803f8077..b0b30c318ef 100644 --- a/packages/devtools_app/lib/src/shared/history_viewport.dart +++ b/packages/devtools_app/lib/src/shared/history_viewport.dart @@ -62,24 +62,26 @@ class _HistoryViewportState extends State> { @override Widget build(BuildContext context) { - final titleIcon = widget.titleIcon != null - ? Padding( - padding: const EdgeInsets.only(right: densePadding), - child: Icon( - widget.titleIcon, - size: defaultIconSize, - color: _iconColor, - ), - ) - : const SizedBox.shrink(); + final titleIcon = + widget.titleIcon != null + ? Padding( + padding: const EdgeInsets.only(right: densePadding), + child: Icon( + widget.titleIcon, + size: defaultIconSize, + color: _iconColor, + ), + ) + : const SizedBox.shrink(); return ValueListenableBuilder( valueListenable: widget.history.current, builder: (context, T? current, _) { final theme = Theme.of(context); - final title = widget.generateTitle == null - ? ' ' - : widget.generateTitle!(current); + final title = + widget.generateTitle == null + ? ' ' + : widget.generateTitle!(current); final defaultTitleStyle = theme.textTheme.titleMedium!; final titleWidget = debuggerSectionTitle( theme, @@ -88,76 +90,77 @@ class _HistoryViewportState extends State> { if (widget.historyEnabled) ...[ ToolbarAction( icon: Icons.chevron_left, - onPressed: widget.history.hasPrevious - ? () { - widget.history.moveBack(); - if (widget.onChange != null) { - widget.onChange!( - widget.history.current.value, - widget.history.peekNext(), - ); + onPressed: + widget.history.hasPrevious + ? () { + widget.history.moveBack(); + if (widget.onChange != null) { + widget.onChange!( + widget.history.current.value, + widget.history.peekNext(), + ); + } } - } - : null, + : null, ), ToolbarAction( icon: Icons.chevron_right, - onPressed: widget.history.hasNext - ? () { - final current = widget.history.current.value as T; - widget.history.moveForward(); - if (widget.onChange != null) { - widget.onChange!( - widget.history.current.value, - current, - ); + onPressed: + widget.history.hasNext + ? () { + final current = widget.history.current.value as T; + widget.history.moveForward(); + if (widget.onChange != null) { + widget.onChange!( + widget.history.current.value, + current, + ); + } } - } - : null, + : null, ), const SizedBox(width: denseSpacing), const VerticalDivider(thickness: 1.0), const SizedBox(width: defaultSpacing), ], Expanded( - child: widget.onTitleTap == null - ? Row( - children: [ - titleIcon, - Text( - title, - style: defaultTitleStyle, - ), - ], - ) - : MouseRegion( - cursor: SystemMouseCursors.click, - onExit: (_) { - _updateTitleStyle(defaultTitleStyle); - }, - onEnter: (_) { - _updateTitleStyle( - defaultTitleStyle.copyWith( - color: theme.colorScheme.primary, - ), - ); - }, - child: GestureDetector( - onTap: widget.onTitleTap, - child: Row( - children: [ - titleIcon, - Expanded( - child: Text( - title, - style: _titleStyle ?? - theme.textTheme.titleMedium, - ), + child: + widget.onTitleTap == null + ? Row( + children: [ + titleIcon, + Text(title, style: defaultTitleStyle), + ], + ) + : MouseRegion( + cursor: SystemMouseCursors.click, + onExit: (_) { + _updateTitleStyle(defaultTitleStyle); + }, + onEnter: (_) { + _updateTitleStyle( + defaultTitleStyle.copyWith( + color: theme.colorScheme.primary, ), - ], + ); + }, + child: GestureDetector( + onTap: widget.onTitleTap, + child: Row( + children: [ + titleIcon, + Expanded( + child: Text( + title, + style: + _titleStyle ?? + theme.textTheme.titleMedium, + ), + ), + ], + ), ), ), - ), ), if (widget.controls != null) ...[ const SizedBox(width: denseSpacing), @@ -171,10 +174,7 @@ class _HistoryViewportState extends State> { ); return RoundedOutlinedBorder( child: Column( - children: [ - titleWidget, - widget.contentBuilder(context, current), - ], + children: [titleWidget, widget.contentBuilder(context, current)], ), ); }, diff --git a/packages/devtools_app/lib/src/shared/http/_http_exception.dart b/packages/devtools_app/lib/src/shared/http/_http_exception.dart index 9dcb02941f8..8cde8848a5f 100644 --- a/packages/devtools_app/lib/src/shared/http/_http_exception.dart +++ b/packages/devtools_app/lib/src/shared/http/_http_exception.dart @@ -11,9 +11,10 @@ class HttpException { @override String toString() { - final b = StringBuffer() - ..write('HttpException: ') - ..write(message); + final b = + StringBuffer() + ..write('HttpException: ') + ..write(message); if (uri != null) { b.write(', uri = $uri'); } diff --git a/packages/devtools_app/lib/src/shared/http/curl_command.dart b/packages/devtools_app/lib/src/shared/http/curl_command.dart index 1176ef38f27..af35257baf0 100644 --- a/packages/devtools_app/lib/src/shared/http/curl_command.dart +++ b/packages/devtools_app/lib/src/shared/http/curl_command.dart @@ -29,9 +29,7 @@ class CurlCommand { ); } - CurlCommand._({ - required this.commandParts, - }); + CurlCommand._({required this.commandParts}); static const _lineBreak = '\\\n'; 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 67bcc5b006f..18bb4386313 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 @@ -52,9 +52,9 @@ class DartIOHttpRequestData extends NetworkRequest { Map? responseContent, ) { return DartIOHttpRequestData( - HttpProfileRequestRef.parse(modifiedRequestData)!, - requestFullDataFromVmService: false, - ) + HttpProfileRequestRef.parse(modifiedRequestData)!, + requestFullDataFromVmService: false, + ) .._responseBody = responseContent?['text'].toString() .._requestBody = requestPostData?['text'].toString(); } @@ -73,9 +73,9 @@ class DartIOHttpRequestData extends NetworkRequest { isFetchingFullData = true; final updated = await serviceConnection.serviceManager.service! .getHttpProfileRequestWrapper( - _request.isolateId, - _request.id.toString(), - ); + _request.isolateId, + _request.id.toString(), + ); _request = updated; final fullRequest = _request as HttpProfileRequest; _responseBody = utf8.decode(fullRequest.responseBody!); @@ -211,9 +211,10 @@ class DartIOHttpRequestData extends NetworkRequest { requestCookies.isNotEmpty || responseCookies.isNotEmpty; /// A list of all cookies contained within the request headers. - List get requestCookies => _hasError - ? [] - : DartIOHttpRequestData._parseCookies(_request.request?.cookies); + List get requestCookies => + _hasError + ? [] + : DartIOHttpRequestData._parseCookies(_request.request?.cookies); /// A list of all cookies contained within the response headers. List get responseCookies => @@ -313,9 +314,10 @@ class DartIOHttpRequestData extends NetworkRequest { DateTime lastTime = _request.startTime; for (final instant in instantEvents) { final instantTime = instant.timestamp; - instant._timeRange = TimeRange() - ..start = Duration(microseconds: lastTime.microsecondsSinceEpoch) - ..end = Duration(microseconds: instantTime.microsecondsSinceEpoch); + instant._timeRange = + TimeRange() + ..start = Duration(microseconds: lastTime.microsecondsSinceEpoch) + ..end = Duration(microseconds: instantTime.microsecondsSinceEpoch); lastTime = instantTime; } } @@ -326,13 +328,6 @@ class DartIOHttpRequestData extends NetworkRequest { } @override - int get hashCode => Object.hash( - id, - method, - uri, - contentType, - type, - port, - startTimestamp, - ); + int get hashCode => + Object.hash(id, method, uri, contentType, type, port, startTimestamp); } diff --git a/packages/devtools_app/lib/src/shared/http/http_service.dart b/packages/devtools_app/lib/src/shared/http/http_service.dart index a6f207b5d53..89dbdf3283d 100644 --- a/packages/devtools_app/lib/src/shared/http/http_service.dart +++ b/packages/devtools_app/lib/src/shared/http/http_service.dart @@ -13,16 +13,14 @@ import '../primitives/utils.dart'; /// Enables or disables HTTP logging for all isolates. Future toggleHttpRequestLogging(bool state) async { - await serviceConnection.serviceManager.service! - .forEachIsolate((isolate) async { + await serviceConnection.serviceManager.service!.forEachIsolate(( + isolate, + ) async { final httpLoggingAvailable = await serviceConnection.serviceManager.service! .isHttpTimelineLoggingAvailableWrapper(isolate.id!); if (httpLoggingAvailable) { final future = serviceConnection.serviceManager.service! - .httpEnableTimelineLoggingWrapper( - isolate.id!, - state, - ); + .httpEnableTimelineLoggingWrapper(isolate.id!, state); // The above call won't complete immediately if the isolate is paused, so // give up waiting after 500ms. However, the call will complete eventually // if the isolate is eventually resumed. @@ -35,8 +33,7 @@ Future toggleHttpRequestLogging(bool state) async { bool get httpLoggingEnabled => httpLoggingState.value.enabled; -ValueListenable get httpLoggingState => - serviceConnection.serviceManager.serviceExtensionManager - .getServiceExtensionState( - extensions.httpEnableTimelineLogging.extension, - ); +ValueListenable get httpLoggingState => serviceConnection + .serviceManager + .serviceExtensionManager + .getServiceExtensionState(extensions.httpEnableTimelineLogging.extension); 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 8794f718628..53743340472 100644 --- a/packages/devtools_app/lib/src/shared/memory/class_name.dart +++ b/packages/devtools_app/lib/src/shared/memory/class_name.dart @@ -38,8 +38,7 @@ enum ClassType { alias: '\$project', aliasDescription: 'classes of the project', classTooltip: 'project class', - ), - ; + ); const ClassType({ required this.color, @@ -83,7 +82,7 @@ class _Json { class HeapClassName with Serializable { @visibleForTesting HeapClassName({required String? library, required this.className}) - : library = _normalizeLibrary(library); + : library = _normalizeLibrary(library); factory HeapClassName.fromJson(Map json) { return HeapClassName( @@ -94,10 +93,7 @@ class HeapClassName with Serializable { @override Map toJson() { - return { - _Json.className: className, - _Json.library: library, - }; + return {_Json.className: className, _Json.library: library}; } static final _instances = {}; @@ -116,12 +112,9 @@ class HeapClassName with Serializable { } static HeapClassName fromClassRef(ClassRef? classRef) => fromPath( - library: _library( - classRef?.library?.name, - classRef?.library?.uri, - ), - className: classRef?.name ?? '', - ); + library: _library(classRef?.library?.name, classRef?.library?.uri), + className: classRef?.name ?? '', + ); static HeapClassName fromHeapSnapshotClass(HeapSnapshotClass? theClass) => fromPath( @@ -203,7 +196,8 @@ class HeapClassName with Serializable { /// `dart:` or `package:`. /// Examples of such classes: Code, Function, Class, Field, /// number_symbols/NumberSymbols, vector_math_64/Matrix4. - late final isPackageless = library.isEmpty || + late final isPackageless = + library.isEmpty || (!library.startsWith(PackagePrefixes.dart) && !library.startsWith(PackagePrefixes.genericDartPackage)); @@ -240,9 +234,9 @@ class HeapClassName with Serializable { static String _normalizeLibrary(String? library) => (library ?? '').trim().replaceFirst( - RegExp('^${PackagePrefixes.dartInSnapshot}'), - PackagePrefixes.dart, - ); + RegExp('^${PackagePrefixes.dartInSnapshot}'), + PackagePrefixes.dart, + ); bool matches(ClassRef ref) { return HeapClassName.fromClassRef(ref) == this; diff --git a/packages/devtools_app/lib/src/shared/memory/classes.dart b/packages/devtools_app/lib/src/shared/memory/classes.dart index ea5c04ee2c3..5dc0c498eab 100644 --- a/packages/devtools_app/lib/src/shared/memory/classes.dart +++ b/packages/devtools_app/lib/src/shared/memory/classes.dart @@ -19,10 +19,11 @@ class ObjectSetStats { from ??= _empty; subtract ??= _empty; - final result = ObjectSetStats() - ..instanceCount = from.instanceCount - subtract.instanceCount - ..shallowSize = from.shallowSize - subtract.shallowSize - ..retainedSize = from.retainedSize - subtract.retainedSize; + final result = + ObjectSetStats() + ..instanceCount = from.instanceCount - subtract.instanceCount + ..shallowSize = from.shallowSize - subtract.shallowSize + ..retainedSize = from.retainedSize - subtract.retainedSize; if (result.isZero) return null; return result; @@ -111,22 +112,21 @@ class ObjectSet extends ObjectSetStats { } @immutable - /// List of classes with filtering support. /// /// Is used to provide a list of classes to widgets. class ClassDataList { const ClassDataList(this._originalList) - : _appliedFilter = null, - _filtered = null; + : _appliedFilter = null, + _filtered = null; const ClassDataList._filtered({ required List original, required ClassFilter appliedFilter, required List filtered, - }) : _originalList = original, - _appliedFilter = appliedFilter, - _filtered = filtered; + }) : _originalList = original, + _appliedFilter = appliedFilter, + _filtered = filtered; /// The list of classes after filtering. List get list => _filtered ?? _originalList; @@ -135,8 +135,9 @@ class ClassDataList { final ClassFilter? _appliedFilter; final List? _filtered; - Map asMap() => - {for (final c in _originalList) c.className: c}; + Map asMap() => { + for (final c in _originalList) c.className: c, + }; ClassDataList filtered(ClassFilter newFilter, String? rootPackage) { final filtered = ClassFilter.filter( @@ -193,7 +194,8 @@ class SingleClassData extends ClassData { @override // ignore: avoid-explicit-type-declaration, required to override base class. - final ObjectSet objects = ObjectSet(); + final ObjectSet + objects = ObjectSet(); @override final byPath = {}; @@ -204,15 +206,17 @@ class SingleClassData extends ClassData { required List? retainers, required List? retainedSizes, }) { - final path = retainers == null - ? null - : PathFromRoot.forObject( - graph, - shortestRetainers: retainers, - index: index, - ); - - final excludeFromRetained = path != null && + final path = + retainers == null + ? null + : PathFromRoot.forObject( + graph, + shortestRetainers: retainers, + index: index, + ); + + final excludeFromRetained = + path != null && retainedSizes != null && path.classes.contains(className); @@ -224,10 +228,7 @@ class SingleClassData extends ClassData { ); if (path != null) { - byPath.putIfAbsent( - path, - () => ObjectSetStats(), - ); + byPath.putIfAbsent(path, () => ObjectSetStats()); byPath[path]!.countInstance( graph, index, diff --git a/packages/devtools_app/lib/src/shared/memory/gc_stats.dart b/packages/devtools_app/lib/src/shared/memory/gc_stats.dart index 6de639e41c9..80a83a2a9fd 100644 --- a/packages/devtools_app/lib/src/shared/memory/gc_stats.dart +++ b/packages/devtools_app/lib/src/shared/memory/gc_stats.dart @@ -47,12 +47,12 @@ class GCStats with Serializable { @override Map toJson() => { - _Json.heap: heap, - _Json.usage: usage, - _Json.capacity: capacity, - _Json.collections: collections, - _Json.averageCollectionTime: averageCollectionTime, - }; + _Json.heap: heap, + _Json.usage: usage, + _Json.capacity: capacity, + _Json.collections: collections, + _Json.averageCollectionTime: averageCollectionTime, + }; static const usedKey = 'used'; static const capacityKey = 'capacity'; 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 0b10c3be20f..1f6fb631e6a 100644 --- a/packages/devtools_app/lib/src/shared/memory/heap_data.dart +++ b/packages/devtools_app/lib/src/shared/memory/heap_data.dart @@ -93,8 +93,9 @@ class HeapData { continue; } - final className = - HeapClassName.fromHeapSnapshotClass(graph.classes[object.classId]); + final className = HeapClassName.fromHeapSnapshotClass( + graph.classes[object.classId], + ); // Ignore sentinels, because their size is not known. if (className.isSentinel) { @@ -105,10 +106,7 @@ class HeapData { reachableSize += object.shallowSize; nameToClass - .putIfAbsent( - className, - () => SingleClassData(className: className), - ) + .putIfAbsent(className, () => SingleClassData(className: className)) .countInstance( graph, index: i, diff --git a/packages/devtools_app/lib/src/shared/memory/retainers.dart b/packages/devtools_app/lib/src/shared/memory/retainers.dart index c6fbf7e9b28..5b2b984a1fd 100644 --- a/packages/devtools_app/lib/src/shared/memory/retainers.dart +++ b/packages/devtools_app/lib/src/shared/memory/retainers.dart @@ -13,19 +13,20 @@ typedef References = List Function(int index); /// Shallow size of the given object. typedef ShallowSize = int Function(int index); -typedef ShortestRetainersResult = ({ - /// Retainer for each object in the graph. - /// - /// When a value at index i is 0, it means the object at index i - /// has no retainers. - /// Null is not used for no-retainer to save memory footprint. - List retainers, +typedef ShortestRetainersResult = + ({ + /// Retainer for each object in the graph. + /// + /// When a value at index i is 0, it means the object at index i + /// has no retainers. + /// Null is not used for no-retainer to save memory footprint. + List retainers, - /// Retained size for each object in the graph. - /// - /// If an object is unreachable, its retained size is 0. - List? retainedSizes, -}); + /// Retained size for each object in the graph. + /// + /// If an object is unreachable, its retained size is 0. + List? retainedSizes, + }); /// Index of the sentinel object. const _sentinelIndex = 0; 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 9577c61e850..8949c0f9290 100644 --- a/packages/devtools_app/lib/src/shared/memory/retaining_path.dart +++ b/packages/devtools_app/lib/src/shared/memory/retaining_path.dart @@ -42,18 +42,18 @@ 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(); + }) : assert(() { + debugUsage.constructed++; + return true; + }()), + hashCode = path.isEmpty ? _hashOfEmptyPath : Object.hashAll(path), + classes = debugOmitClassesInRetainingPath ? const {} : path.toSet(); /// For objects directly referenced from root. const PathFromRoot._empty() - : path = const [], - classes = const {}, - hashCode = _hashOfEmptyPath; + : path = const [], + classes = const {}, + hashCode = _hashOfEmptyPath; factory PathFromRoot.forObject( HeapSnapshotGraph graph, { diff --git a/packages/devtools_app/lib/src/shared/memory/simple_items.dart b/packages/devtools_app/lib/src/shared/memory/simple_items.dart index aa7114172ba..6ea861c66b2 100644 --- a/packages/devtools_app/lib/src/shared/memory/simple_items.dart +++ b/packages/devtools_app/lib/src/shared/memory/simple_items.dart @@ -8,16 +8,10 @@ import 'package:file_selector/file_selector.dart'; import 'package:vm_service/vm_service.dart'; /// Direction of reference between objects in memory. -enum RefDirection { - inbound, - outbound, -} +enum RefDirection { inbound, outbound } class MemoryFootprint { - MemoryFootprint({ - required this.dart, - required this.reachable, - }); + MemoryFootprint({required this.dart, required this.reachable}); /// Reachable and unreachable total dart heap size. final int dart; diff --git a/packages/devtools_app/lib/src/shared/notifications.dart b/packages/devtools_app/lib/src/shared/notifications.dart index 943e1b93471..97609e7d0d1 100644 --- a/packages/devtools_app/lib/src/shared/notifications.dart +++ b/packages/devtools_app/lib/src/shared/notifications.dart @@ -48,16 +48,9 @@ class NotificationService { /// Includes a button to close the notification if [isDismissible] is true, /// otherwise the notification will be automatically dismissed after /// [NotificationMessage.defaultDuration]. - bool push( - String message, { - bool isDismissible = false, - }) => - pushNotification( - NotificationMessage( - message, - isDismissible: isDismissible, - ), - ); + bool push(String message, {bool isDismissible = false}) => pushNotification( + NotificationMessage(message, isDismissible: isDismissible), + ); /// Pushes an error notification with [errorMessage] as the text. /// @@ -80,9 +73,10 @@ class NotificationService { if (reportExplanation != null) 'Explanation:\n$reportExplanation', if (stackTrace != null) 'Stack trace:\n$stackTrace', ]; - final additionalInfo = additionalInfoParts.isNotEmpty - ? additionalInfoParts.join('\n\n') - : null; + final additionalInfo = + additionalInfoParts.isNotEmpty + ? additionalInfoParts.join('\n\n') + : null; unawaited( launchUrlWithErrorHandling( devToolsEnvironmentParameters @@ -102,9 +96,10 @@ class NotificationService { isDismissible: isDismissible, actions: [if (isReportable) reportErrorAction], // Double the duration so that the user has time to report the error: - duration: isReportable - ? NotificationMessage.defaultDuration * 2 - : NotificationMessage.defaultDuration, + duration: + isReportable + ? NotificationMessage.defaultDuration * 2 + : NotificationMessage.defaultDuration, ), allowDuplicates: allowDuplicates, ); @@ -168,9 +163,10 @@ class NotificationAction extends StatelessWidget { final theme = Theme.of(context); return DevToolsButton( label: label, - color: isPrimary - ? theme.colorScheme.onPrimary - : theme.colorScheme.onSecondaryContainer, + color: + isPrimary + ? theme.colorScheme.onPrimary + : theme.colorScheme.onSecondaryContainer, elevated: isPrimary, outlined: !isPrimary, onPressed: onPressed, diff --git a/packages/devtools_app/lib/src/shared/offline_data.dart b/packages/devtools_app/lib/src/shared/offline_data.dart index ddb20ec54b0..9c214d8a1a9 100644 --- a/packages/devtools_app/lib/src/shared/offline_data.dart +++ b/packages/devtools_app/lib/src/shared/offline_data.dart @@ -179,8 +179,9 @@ mixin OfflineScreenControllerMixin on AutoDisposeControllerMixin { /// Exports the current screen data to a .json file and downloads the file to /// the user's Downloads directory. void exportData() { - final encodedData = - _exportController.encode(prepareOfflineScreenData().toJson()); + final encodedData = _exportController.encode( + prepareOfflineScreenData().toJson(), + ); _exportController.downloadFile(encodedData); } @@ -233,7 +234,7 @@ class OfflineScreenData { final Map data; Map toJson() => { - DevToolsExportKeys.activeScreenId.name: screenId, - screenId: data, - }; + DevToolsExportKeys.activeScreenId.name: screenId, + screenId: data, + }; } diff --git a/packages/devtools_app/lib/src/shared/preferences/_extension_preferences.dart b/packages/devtools_app/lib/src/shared/preferences/_extension_preferences.dart index 89c73cfa329..66ac283cb38 100644 --- a/packages/devtools_app/lib/src/shared/preferences/_extension_preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences/_extension_preferences.dart @@ -13,20 +13,17 @@ class ExtensionsPreferencesController extends DisposableController '${gac.DevToolsExtensionEvents.showOnlyEnabledExtensionsSetting.name}'; Future init() async { - addAutoDisposeListener( - showOnlyEnabledExtensions, - () { - storage.setValue( - _showOnlyEnabledExtensionsId, - showOnlyEnabledExtensions.value.toString(), - ); - ga.select( - gac.DevToolsExtensionEvents.extensionScreenId.name, - gac.DevToolsExtensionEvents.showOnlyEnabledExtensionsSetting.name, - value: showOnlyEnabledExtensions.value ? 1 : 0, - ); - }, - ); + addAutoDisposeListener(showOnlyEnabledExtensions, () { + storage.setValue( + _showOnlyEnabledExtensionsId, + showOnlyEnabledExtensions.value.toString(), + ); + ga.select( + gac.DevToolsExtensionEvents.extensionScreenId.name, + gac.DevToolsExtensionEvents.showOnlyEnabledExtensionsSetting.name, + value: showOnlyEnabledExtensions.value ? 1 : 0, + ); + }); showOnlyEnabledExtensions.value = await boolValueFromStorage( _showOnlyEnabledExtensionsId, defaultsTo: false, diff --git a/packages/devtools_app/lib/src/shared/preferences/_inspector_preferences.dart b/packages/devtools_app/lib/src/shared/preferences/_inspector_preferences.dart index c3cb21ed421..bbe89bf3833 100644 --- a/packages/devtools_app/lib/src/shared/preferences/_inspector_preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences/_inspector_preferences.dart @@ -9,7 +9,7 @@ enum InspectorDetailsViewType { widgetDetailsTree(nameOverride: 'Widget Details Tree'); const InspectorDetailsViewType({String? nameOverride}) - : _nameOverride = nameOverride; + : _nameOverride = nameOverride; final String? _nameOverride; @@ -56,8 +56,10 @@ class InspectorPreferencesController extends DisposableController (await serviceConnection.serviceManager.tryToDetectMainRootInfo()) ?.library; final rootLibUri = Uri.parse(rootLibUriString ?? ''); - final directorySegments = - rootLibUri.pathSegments.sublist(0, rootLibUri.pathSegments.length - 1); + final directorySegments = rootLibUri.pathSegments.sublist( + 0, + rootLibUri.pathSegments.length - 1, + ); final rootLibDirectory = rootLibUri.replace( pathSegments: directorySegments, ); @@ -157,12 +159,14 @@ class InspectorPreferencesController extends DisposableController } Future _updateInspectorDetailsViewSelection() async { - final inspectorDetailsView = - await storage.getValue(_defaultDetailsViewStorageId); + final inspectorDetailsView = await storage.getValue( + _defaultDetailsViewStorageId, + ); if (inspectorDetailsView != null) { - _defaultDetailsView.value = InspectorDetailsViewType.values - .firstWhere((e) => e.name.toString() == inspectorDetailsView); + _defaultDetailsView.value = InspectorDetailsViewType.values.firstWhere( + (e) => e.name.toString() == inspectorDetailsView, + ); } } @@ -244,8 +248,9 @@ class InspectorPreferencesController extends DisposableController @visibleForTesting Future> readCachedPubRootDirectories() async { - final cachedDirectoriesJson = - await storage.getValue(_customPubRootStorageId()); + final cachedDirectoriesJson = await storage.getValue( + _customPubRootStorageId(), + ); if (cachedDirectoriesJson == null) return []; final cachedDirectories = List.from( jsonDecode(cachedDirectoriesJson), @@ -275,8 +280,9 @@ class InspectorPreferencesController extends DisposableController /// directories are for the current project so we make a best guess based on /// the root library for the main isolate. Future _inferPubRootDirectory() async { - final fileUriString = await serviceConnection.serviceManager - .mainIsolateRootLibraryUriAsString(); + final fileUriString = + await serviceConnection.serviceManager + .mainIsolateRootLibraryUriAsString(); if (fileUriString == null) { return null; } @@ -312,9 +318,10 @@ class InspectorPreferencesController extends DisposableController pubRootDirectory ??= (parts..removeLast()).join('/'); // Make sure the root directory ends with /, otherwise we will patch with // other directories that start the same. - pubRootDirectory = pubRootDirectory.endsWith('/') - ? pubRootDirectory - : '$pubRootDirectory/'; + pubRootDirectory = + pubRootDirectory.endsWith('/') + ? pubRootDirectory + : '$pubRootDirectory/'; return pubRootDirectory; } @@ -331,25 +338,21 @@ class InspectorPreferencesController extends DisposableController } } - Future _cachePubRootDirectories( - List pubRootDirectories, - ) async { + Future _cachePubRootDirectories(List pubRootDirectories) async { final cachedDirectories = await readCachedPubRootDirectories(); await storage.setValue( _customPubRootStorageId(), - jsonEncode([ - ...cachedDirectories, - ...pubRootDirectories, - ]), + jsonEncode([...cachedDirectories, ...pubRootDirectories]), ); } Future _uncachePubRootDirectories( List pubRootDirectories, ) async { - final directoriesToCache = (await readCachedPubRootDirectories()) - .where((dir) => !pubRootDirectories.contains(dir)) - .toList(); + final directoriesToCache = + (await readCachedPubRootDirectories()) + .where((dir) => !pubRootDirectories.contains(dir)) + .toList(); await storage.setValue( _customPubRootStorageId(), jsonEncode(directoriesToCache), @@ -382,9 +385,7 @@ class InspectorPreferencesController extends DisposableController }); } - Future removePubRootDirectories( - List pubRootDirectories, - ) async { + Future removePubRootDirectories(List pubRootDirectories) async { if (!serviceConnection.serviceManager.connectedState.value.connected) { return; } 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 268737ef601..f451a1047cd 100644 --- a/packages/devtools_app/lib/src/shared/preferences/_logging_preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences/_logging_preferences.dart @@ -13,8 +13,9 @@ class LoggingPreferencesController extends DisposableController /// The [LoggingDetailsFormat] to use when displaying a log in the log details /// view. - final detailsFormat = - ValueNotifier(_defaultDetailsFormat); + final detailsFormat = ValueNotifier( + _defaultDetailsFormat, + ); /// The active filter tag for the logging screen. /// @@ -35,39 +36,35 @@ class LoggingPreferencesController extends DisposableController Future init() async { retentionLimit.value = int.tryParse(await storage.getValue(_retentionLimitStorageId) ?? '') ?? - _defaultRetentionLimit; - addAutoDisposeListener( - retentionLimit, - () { - storage.setValue( - _retentionLimitStorageId, - retentionLimit.value.toString(), - ); - ga.select( - gac.logging, - gac.LoggingEvents.changeRetentionLimit.name, - value: retentionLimit.value, - ); - }, - ); + _defaultRetentionLimit; + addAutoDisposeListener(retentionLimit, () { + storage.setValue( + _retentionLimitStorageId, + retentionLimit.value.toString(), + ); + ga.select( + gac.logging, + gac.LoggingEvents.changeRetentionLimit.name, + value: retentionLimit.value, + ); + }); - final detailsFormatValueFromStorage = - await storage.getValue(detailsFormatStorageId); - detailsFormat.value = LoggingDetailsFormat.values.firstWhereOrNull( + final detailsFormatValueFromStorage = await storage.getValue( + detailsFormatStorageId, + ); + detailsFormat.value = + LoggingDetailsFormat.values.firstWhereOrNull( (value) => detailsFormatValueFromStorage == value.name, ) ?? _defaultDetailsFormat; - addAutoDisposeListener( - detailsFormat, - () { - storage.setValue(detailsFormatStorageId, detailsFormat.value.name); - ga.select( - gac.logging, - gac.LoggingEvents.changeDetailsFormat.name, - value: detailsFormat.value.index, - ); - }, - ); + addAutoDisposeListener(detailsFormat, () { + storage.setValue(detailsFormatStorageId, detailsFormat.value.name); + ga.select( + gac.logging, + gac.LoggingEvents.changeDetailsFormat.name, + value: detailsFormat.value.index, + ); + }); filterTag.value = await storage.getValue(filterStorageId) ?? ''; addAutoDisposeListener( diff --git a/packages/devtools_app/lib/src/shared/preferences/_memory_preferences.dart b/packages/devtools_app/lib/src/shared/preferences/_memory_preferences.dart index 3449d8a4fbb..cbc0016b79b 100644 --- a/packages/devtools_app/lib/src/shared/preferences/_memory_preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences/_memory_preferences.dart @@ -24,63 +24,42 @@ class MemoryPreferencesController extends DisposableController static const _refLimitStorageId = 'memory.refLimit'; Future init() async { - addAutoDisposeListener( - androidCollectionEnabled, - () { - storage.setValue( - _androidCollectionEnabledStorageId, - androidCollectionEnabled.value.toString(), - ); - if (androidCollectionEnabled.value) { - ga.select( - gac.memory, - gac.MemoryEvents.androidChart.name, - ); - } - }, - ); + addAutoDisposeListener(androidCollectionEnabled, () { + storage.setValue( + _androidCollectionEnabledStorageId, + androidCollectionEnabled.value.toString(), + ); + if (androidCollectionEnabled.value) { + ga.select(gac.memory, gac.MemoryEvents.androidChart.name); + } + }); androidCollectionEnabled.value = await boolValueFromStorage( _androidCollectionEnabledStorageId, defaultsTo: false, ); - addAutoDisposeListener( - showChart, - () { - storage.setValue( - _showChartStorageId, - showChart.value.toString(), - ); + addAutoDisposeListener(showChart, () { + storage.setValue(_showChartStorageId, showChart.value.toString()); - ga.select( - gac.memory, - showChart.value - ? gac.MemoryEvents.showChart.name - : gac.MemoryEvents.hideChart.name, - ); - }, - ); + ga.select( + gac.memory, + showChart.value + ? gac.MemoryEvents.showChart.name + : gac.MemoryEvents.hideChart.name, + ); + }); showChart.value = await boolValueFromStorage( _showChartStorageId, defaultsTo: true, ); - addAutoDisposeListener( - refLimit, - () { - storage.setValue( - _refLimitStorageId, - refLimit.value.toString(), - ); + addAutoDisposeListener(refLimit, () { + storage.setValue(_refLimitStorageId, refLimit.value.toString()); - ga.select( - gac.memory, - gac.MemoryEvents.browseRefLimit.name, - ); - }, - ); + ga.select(gac.memory, gac.MemoryEvents.browseRefLimit.name); + }); refLimit.value = int.tryParse(await storage.getValue(_refLimitStorageId) ?? '') ?? - _defaultRefLimit; + _defaultRefLimit; } } diff --git a/packages/devtools_app/lib/src/shared/preferences/_performance_preferences.dart b/packages/devtools_app/lib/src/shared/preferences/_performance_preferences.dart index 177f5c15152..0e6df8155f6 100644 --- a/packages/devtools_app/lib/src/shared/preferences/_performance_preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences/_performance_preferences.dart @@ -20,39 +20,33 @@ class PerformancePreferencesController extends DisposableController '${gac.performance}.${gac.PerformanceEvents.includeCpuSamplesInTimeline.name}'; Future init() async { - addAutoDisposeListener( - showFlutterFramesChart, - () { - storage.setValue( - _showFlutterFramesChartId, - showFlutterFramesChart.value.toString(), - ); - ga.select( - gac.performance, - gac.PerformanceEvents.framesChartVisibility.name, - value: showFlutterFramesChart.value ? 1 : 0, - ); - }, - ); + addAutoDisposeListener(showFlutterFramesChart, () { + storage.setValue( + _showFlutterFramesChartId, + showFlutterFramesChart.value.toString(), + ); + ga.select( + gac.performance, + gac.PerformanceEvents.framesChartVisibility.name, + value: showFlutterFramesChart.value ? 1 : 0, + ); + }); showFlutterFramesChart.value = await boolValueFromStorage( _showFlutterFramesChartId, defaultsTo: true, ); - addAutoDisposeListener( - includeCpuSamplesInTimeline, - () { - storage.setValue( - _includeCpuSamplesInTimelineId, - includeCpuSamplesInTimeline.value.toString(), - ); - ga.select( - gac.performance, - gac.PerformanceEvents.includeCpuSamplesInTimeline.name, - value: includeCpuSamplesInTimeline.value ? 1 : 0, - ); - }, - ); + addAutoDisposeListener(includeCpuSamplesInTimeline, () { + storage.setValue( + _includeCpuSamplesInTimelineId, + includeCpuSamplesInTimeline.value.toString(), + ); + ga.select( + gac.performance, + gac.PerformanceEvents.includeCpuSamplesInTimeline.name, + value: includeCpuSamplesInTimeline.value ? 1 : 0, + ); + }); includeCpuSamplesInTimeline.value = await boolValueFromStorage( _includeCpuSamplesInTimelineId, defaultsTo: false, diff --git a/packages/devtools_app/lib/src/shared/preferences/preferences.dart b/packages/devtools_app/lib/src/shared/preferences/preferences.dart index 5499f635aaa..1df6dd8013c 100644 --- a/packages/devtools_app/lib/src/shared/preferences/preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences/preferences.dart @@ -56,9 +56,7 @@ enum _UiPreferences { /// DevTools preferences for general settings. /// /// These values are not stored in the DevTools storage file with a prefix. -enum _GeneralPreferences { - verboseLogging, -} +enum _GeneralPreferences { verboseLogging } /// A controller for global application preferences. class PreferencesController extends DisposableController @@ -79,8 +77,9 @@ class PreferencesController extends DisposableController /// dart2js + canvaskit final wasmEnabled = ValueNotifier(false); - final verboseLoggingEnabled = - ValueNotifier(Logger.root.level == verboseLoggingLevel); + final verboseLoggingEnabled = ValueNotifier( + Logger.root.level == verboseLoggingLevel, + ); CpuProfilerPreferencesController get cpuProfiler => _cpuProfiler; final _cpuProfiler = CpuProfilerPreferencesController(); @@ -126,9 +125,11 @@ class PreferencesController extends DisposableController } Future _initDarkMode() async { - final darkModeValue = - await storage.getValue(_UiPreferences.darkMode.storageKey); - final useDarkMode = (darkModeValue == null && useDarkThemeAsDefault) || + final darkModeValue = await storage.getValue( + _UiPreferences.darkMode.storageKey, + ); + final useDarkMode = + (darkModeValue == null && useDarkThemeAsDefault) || darkModeValue == 'true'; ga.impression(gac.devToolsMain, gac.startingTheme(darkMode: useDarkMode)); toggleDarkModeTheme(useDarkMode); diff --git a/packages/devtools_app/lib/src/shared/primitives/byte_utils.dart b/packages/devtools_app/lib/src/shared/primitives/byte_utils.dart index 31a40bbff2c..08dd4c564c6 100644 --- a/packages/devtools_app/lib/src/shared/primitives/byte_utils.dart +++ b/packages/devtools_app/lib/src/shared/primitives/byte_utils.dart @@ -72,8 +72,10 @@ String printBytes( // TODO(peterdjlee): Round up to the respective digit when fractionDigits > 0. bytes = fractionDigits == 0 ? bytes + 511 : bytes; } - final bytesDisplay = - convertBytes(bytes, to: unit).toStringAsFixed(fractionDigits); + final bytesDisplay = convertBytes( + bytes, + to: unit, + ).toStringAsFixed(fractionDigits); final unitSuffix = includeUnit ? ' ${unit.display}' : ''; return '$bytesDisplay$unitSuffix'; } @@ -106,7 +108,7 @@ enum ByteUnit { gb(multiplierCount: 3); const ByteUnit({required this.multiplierCount, String? display}) - : _display = display; + : _display = display; static const unitMultiplier = 1024.0; 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 d730fbdc7c5..df01e12c338 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 @@ -35,8 +35,9 @@ abstract class CustomPointerScrollView extends BoxScrollView { super.semanticChildCount, super.dragStartBehavior, this.customPointerSignalHandler, - }) : _primary = primary ?? - controller == null && identical(scrollDirection, Axis.vertical); + }) : _primary = + primary ?? + controller == null && identical(scrollDirection, Axis.vertical); final void Function(PointerSignalEvent event)? customPointerSignalHandler; @@ -266,8 +267,9 @@ class CustomPointerScrollable extends StatefulWidget { }) { final List> futures = >[]; - CustomPointerScrollableState? scrollable = - CustomPointerScrollable.of(context); + CustomPointerScrollableState? scrollable = CustomPointerScrollable.of( + context, + ); while (scrollable != null) { futures.add( scrollable.position!.ensureVisible( @@ -333,11 +335,11 @@ class CustomPointerScrollableState extends State _position = controller?.createScrollPosition(_physics!, this, oldPosition) ?? - ScrollPositionWithSingleContext( - physics: _physics!, - context: this, - oldPosition: oldPosition, - ); + ScrollPositionWithSingleContext( + physics: _physics!, + context: this, + oldPosition: oldPosition, + ); assert(position != null); controller?.attach(position!); } @@ -350,7 +352,8 @@ class CustomPointerScrollableState extends State @override void didChangeDependencies() { - _devicePixelRatio = MediaQuery.maybeDevicePixelRatioOf(context) ?? + _devicePixelRatio = + MediaQuery.maybeDevicePixelRatioOf(context) ?? View.of(context).devicePixelRatio; _updatePosition(); super.didChangeDependencies(); @@ -427,42 +430,42 @@ class CustomPointerScrollableState extends State case Axis.vertical: _gestureRecognizers = { VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers< - VerticalDragGestureRecognizer>( - () => VerticalDragGestureRecognizer(), - (VerticalDragGestureRecognizer instance) { - instance - ..onDown = _handleDragDown - ..onStart = _handleDragStart - ..onUpdate = _handleDragUpdate - ..onEnd = _handleDragEnd - ..onCancel = _handleDragCancel - ..minFlingDistance = _physics?.minFlingDistance - ..minFlingVelocity = _physics?.minFlingVelocity - ..maxFlingVelocity = _physics?.maxFlingVelocity - ..dragStartBehavior = widget.dragStartBehavior; - }, - ), + VerticalDragGestureRecognizer + >(() => VerticalDragGestureRecognizer(), ( + VerticalDragGestureRecognizer instance, + ) { + instance + ..onDown = _handleDragDown + ..onStart = _handleDragStart + ..onUpdate = _handleDragUpdate + ..onEnd = _handleDragEnd + ..onCancel = _handleDragCancel + ..minFlingDistance = _physics?.minFlingDistance + ..minFlingVelocity = _physics?.minFlingVelocity + ..maxFlingVelocity = _physics?.maxFlingVelocity + ..dragStartBehavior = widget.dragStartBehavior; + }), }; break; case Axis.horizontal: _gestureRecognizers = { HorizontalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers< - HorizontalDragGestureRecognizer>( - () => HorizontalDragGestureRecognizer(), - (HorizontalDragGestureRecognizer instance) { - instance - ..onDown = _handleDragDown - ..onStart = _handleDragStart - ..onUpdate = _handleDragUpdate - ..onEnd = _handleDragEnd - ..onCancel = _handleDragCancel - ..minFlingDistance = _physics?.minFlingDistance - ..minFlingVelocity = _physics?.minFlingVelocity - ..maxFlingVelocity = _physics?.maxFlingVelocity - ..dragStartBehavior = widget.dragStartBehavior; - }, - ), + HorizontalDragGestureRecognizer + >(() => HorizontalDragGestureRecognizer(), ( + HorizontalDragGestureRecognizer instance, + ) { + instance + ..onDown = _handleDragDown + ..onStart = _handleDragStart + ..onUpdate = _handleDragUpdate + ..onEnd = _handleDragEnd + ..onCancel = _handleDragCancel + ..minFlingDistance = _physics?.minFlingDistance + ..minFlingVelocity = _physics?.minFlingVelocity + ..maxFlingVelocity = _physics?.maxFlingVelocity + ..dragStartBehavior = widget.dragStartBehavior; + }), }; break; } @@ -470,8 +473,9 @@ class CustomPointerScrollableState extends State _lastCanDrag = canDrag; _lastAxisDirection = widget.axis; if (_gestureDetectorKey.currentState != null) { - _gestureDetectorKey.currentState! - .replaceGestureRecognizers(_gestureRecognizers); + _gestureDetectorKey.currentState!.replaceGestureRecognizers( + _gestureRecognizers, + ); } } @@ -484,8 +488,9 @@ class CustomPointerScrollableState extends State if (_shouldIgnorePointer == value) return; _shouldIgnorePointer = value; if (_ignorePointerKey.currentContext != null) { - final RenderIgnorePointer renderBox = _ignorePointerKey.currentContext! - .findRenderObject() as RenderIgnorePointer; + final RenderIgnorePointer renderBox = + _ignorePointerKey.currentContext!.findRenderObject() + as RenderIgnorePointer; renderBox.ignoring = _shouldIgnorePointer; } } @@ -553,9 +558,10 @@ class CustomPointerScrollableState extends State // Returns the offset that should result from applying [event] to the current // position, taking min/max scroll extent into account. double _targetScrollOffsetForPointerScroll(PointerScrollEvent event) { - double delta = widget.axis == Axis.horizontal - ? event.scrollDelta.dx - : event.scrollDelta.dy; + double delta = + widget.axis == Axis.horizontal + ? event.scrollDelta.dx + : event.scrollDelta.dy; if (axisDirectionIsReversed(widget.axisDirection)) { delta *= -1; @@ -569,12 +575,15 @@ class CustomPointerScrollableState extends State void _receivedPointerSignal(PointerSignalEvent event) { if (event is PointerScrollEvent && position != null) { - final double targetScrollOffset = - _targetScrollOffsetForPointerScroll(event); + final double targetScrollOffset = _targetScrollOffsetForPointerScroll( + event, + ); // Only express interest in the event if it would actually result in a scroll. if (targetScrollOffset != position!.pixels) { - GestureBinding.instance.pointerSignalResolver - .register(event, _handlePointerScroll); + GestureBinding.instance.pointerSignalResolver.register( + event, + _handlePointerScroll, + ); } } } @@ -584,8 +593,9 @@ class CustomPointerScrollableState extends State if (_physics != null && !_physics!.shouldAcceptUserOffset(position!)) { return; } - final double targetScrollOffset = - _targetScrollOffsetForPointerScroll(event as PointerScrollEvent); + final double targetScrollOffset = _targetScrollOffsetForPointerScroll( + event as PointerScrollEvent, + ); if (targetScrollOffset != position!.pixels) { position!.jumpTo(targetScrollOffset); } @@ -633,7 +643,8 @@ class CustomPointerScrollableState extends State result = _ScrollSemantics( key: _scrollSemanticsKey, position: position!, - allowImplicitScrolling: widget.physics?.allowImplicitScrolling ?? + allowImplicitScrolling: + widget.physics?.allowImplicitScrolling ?? _physics!.allowImplicitScrolling, semanticChildCount: widget.semanticChildCount, child: result, @@ -736,10 +747,10 @@ class _RenderScrollSemantics extends RenderProxyBox { required bool allowImplicitScrolling, required int? semanticChildCount, RenderBox? child, - }) : _position = position, - _allowImplicitScrolling = allowImplicitScrolling, - _semanticChildCount = semanticChildCount, - super(child) { + }) : _position = position, + _allowImplicitScrolling = allowImplicitScrolling, + _semanticChildCount = semanticChildCount, + super(child) { position.addListener(markNeedsSemanticsUpdate); } @@ -817,8 +828,10 @@ class _RenderScrollSemantics extends RenderProxyBox { } config.scrollIndex = firstVisibleIndex; node.updateWith(config: null, childrenInInversePaintOrder: excluded); - _innerNode! - .updateWith(config: config, childrenInInversePaintOrder: included); + _innerNode!.updateWith( + config: config, + childrenInInversePaintOrder: included, + ); } @override diff --git a/packages/devtools_app/lib/src/shared/primitives/encoding.dart b/packages/devtools_app/lib/src/shared/primitives/encoding.dart index 259fc596b61..52d077b57fd 100644 --- a/packages/devtools_app/lib/src/shared/primitives/encoding.dart +++ b/packages/devtools_app/lib/src/shared/primitives/encoding.dart @@ -124,12 +124,13 @@ class ClassRefEncodeDecode extends EncodeDecode { Object? toEncodable(Object? value) { return switch (value) { null => null, - final HeapSnapshotGraph value => - HeapSnapshotGraphEncodeDecode.instance.toEncodable(value), + final HeapSnapshotGraph value => HeapSnapshotGraphEncodeDecode.instance + .toEncodable(value), final ByteData value => ByteDataEncodeDecode.instance.toEncodable(value), final DateTime value => DateTimeEncodeDecode.instance.toEncodable(value), - final IsolateRef value => - IsolateRefEncodeDecode.instance.toEncodable(value), + final IsolateRef value => IsolateRefEncodeDecode.instance.toEncodable( + value, + ), final ClassRef value => ClassRefEncodeDecode.instance.toEncodable(value), final Serializable value => value.toJson(), _ => diff --git a/packages/devtools_app/lib/src/shared/primitives/extent_delegate_list.dart b/packages/devtools_app/lib/src/shared/primitives/extent_delegate_list.dart index ee40bc6a840..5a6859dc61c 100644 --- a/packages/devtools_app/lib/src/shared/primitives/extent_delegate_list.dart +++ b/packages/devtools_app/lib/src/shared/primitives/extent_delegate_list.dart @@ -130,8 +130,8 @@ class FixedExtentDelegate extends FixedExtentDelegateBase { FixedExtentDelegate({ required double Function(int index) computeExtent, required int Function() computeLength, - }) : _computeExtent = computeExtent, - _computeLength = computeLength { + }) : _computeExtent = computeExtent, + _computeLength = computeLength { recompute(); } @@ -331,11 +331,15 @@ class RenderSliverExtentDelegateBoxAdaptor extends RenderSliverMultiBoxAdaptor { assert(remainingExtent >= 0.0); final targetEndScrollOffset = scrollOffset + remainingExtent; - final firstIndex = - _extentDelegate!.minChildIndexForScrollOffset(scrollOffset); - final targetLastIndex = targetEndScrollOffset.isFinite - ? _extentDelegate!.maxChildIndexForScrollOffset(targetEndScrollOffset) - : null; + final firstIndex = _extentDelegate!.minChildIndexForScrollOffset( + scrollOffset, + ); + final targetLastIndex = + targetEndScrollOffset.isFinite + ? _extentDelegate!.maxChildIndexForScrollOffset( + targetEndScrollOffset, + ) + : null; if (firstChild != null) { final leadingGarbage = _calculateLeadingGarbage(firstIndex); @@ -391,11 +395,14 @@ class RenderSliverExtentDelegateBoxAdaptor extends RenderSliverMultiBoxAdaptor { trailingChildWithLayout = firstChild; } - double estimatedMaxScrollOffset = - _extentDelegate!.layoutOffset(_extentDelegate!.length); - for (int index = indexOf(trailingChildWithLayout!) + 1; - targetLastIndex == null || index <= targetLastIndex; - ++index) { + double estimatedMaxScrollOffset = _extentDelegate!.layoutOffset( + _extentDelegate!.length, + ); + for ( + int index = indexOf(trailingChildWithLayout!) + 1; + targetLastIndex == null || index <= targetLastIndex; + ++index + ) { RenderBox? child = childAfter(trailingChildWithLayout!); if (child == null || indexOf(child) != index) { child = insertAndLayoutChild( @@ -414,8 +421,9 @@ class RenderSliverExtentDelegateBoxAdaptor extends RenderSliverMultiBoxAdaptor { final childParentData = child.parentData as SliverMultiBoxAdaptorParentData; assert(childParentData.index == index); - childParentData.layoutOffset = - _extentDelegate!.layoutOffset(childParentData.index); + childParentData.layoutOffset = _extentDelegate!.layoutOffset( + childParentData.index, + ); } final lastIndex = indexOf(lastChild!); @@ -456,10 +464,12 @@ class RenderSliverExtentDelegateBoxAdaptor extends RenderSliverMultiBoxAdaptor { final targetEndScrollOffsetForPaint = constraints.scrollOffset + constraints.remainingPaintExtent; - final targetLastIndexForPaint = targetEndScrollOffsetForPaint.isFinite - ? _extentDelegate! - .maxChildIndexForScrollOffset(targetEndScrollOffsetForPaint) - : null; + final targetLastIndexForPaint = + targetEndScrollOffsetForPaint.isFinite + ? _extentDelegate!.maxChildIndexForScrollOffset( + targetEndScrollOffsetForPaint, + ) + : null; assert(paintExtent <= estimatedMaxScrollOffset); geometry = SliverGeometry( scrollExtent: _extentDelegate!.layoutOffset(_extentDelegate!.length), @@ -467,7 +477,8 @@ class RenderSliverExtentDelegateBoxAdaptor extends RenderSliverMultiBoxAdaptor { cacheExtent: cacheExtent, maxPaintExtent: estimatedMaxScrollOffset, // Conservative to avoid flickering away the clip during scroll. - hasVisualOverflow: (targetLastIndexForPaint != null && + hasVisualOverflow: + (targetLastIndexForPaint != null && lastIndex >= targetLastIndexForPaint) || constraints.scrollOffset > 0.0, ); 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 8b1e719bee6..74520043b47 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 @@ -54,11 +54,14 @@ class LinkedScrollControllerGroup { /// Creates a new controller that is linked to any existing ones. ScrollController addAndGet() { - final initialScrollOffset = _attachedControllers.isEmpty - ? 0.0 - : _attachedControllers.first.position.pixels; - final controller = - _LinkedScrollController(this, initialScrollOffset: initialScrollOffset); + final initialScrollOffset = + _attachedControllers.isEmpty + ? 0.0 + : _attachedControllers.first.position.pixels; + final controller = _LinkedScrollController( + this, + initialScrollOffset: initialScrollOffset, + ); _allControllers.add(controller); controller.addListener(_offsetNotifier.notifyListeners); return controller; 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 fd975e177ee..c5f76c61f6a 100644 --- a/packages/devtools_app/lib/src/shared/primitives/trace_event.dart +++ b/packages/devtools_app/lib/src/shared/primitives/trace_event.dart @@ -9,14 +9,14 @@ class ChromeTraceEvent { /// Creates a timeline event given JSON-encoded event data. ChromeTraceEvent(this.json) - : name = json[nameKey] as String?, - category = json[categoryKey] as String?, - phase = json[phaseKey] as String?, - processId = json[processIdKey] as int?, - threadId = json[threadIdKey] as int?, - duration = json[durationKey] as int?, - timestampMicros = json[timestampKey] as int?, - args = json[argsKey] as Map?; + : name = json[nameKey] as String?, + category = json[categoryKey] as String?, + phase = json[phaseKey] as String?, + processId = json[processIdKey] as int?, + threadId = json[threadIdKey] as int?, + duration = json[durationKey] as int?, + timestampMicros = json[timestampKey] as int?, + args = json[argsKey] as Map?; static const nameKey = 'name'; static const categoryKey = 'cat'; @@ -120,6 +120,7 @@ class ChromeTraceEvent { } @override - String toString() => '[$idKey: $id] [$phaseKey: $phase] ' + String toString() => + '[$idKey: $id] [$phaseKey: $phase] ' '$name - [$timestampKey: $timestampMicros] [$durationKey: $duration]'; } diff --git a/packages/devtools_app/lib/src/shared/primitives/trees.dart b/packages/devtools_app/lib/src/shared/primitives/trees.dart index 82ad74ca4f7..574c433391b 100644 --- a/packages/devtools_app/lib/src/shared/primitives/trees.dart +++ b/packages/devtools_app/lib/src/shared/primitives/trees.dart @@ -201,10 +201,7 @@ abstract class TreeNode> { } T? firstChildWithCondition(bool Function(T node) condition) { - return breadthFirstTraversal( - this as T, - returnCondition: condition, - ); + return breadthFirstTraversal(this as T, returnCondition: condition); } /// Locates the first sub-node in the tree at level [level]. @@ -228,8 +225,9 @@ abstract class TreeNode> { // When this condition is called, we have already ensured that // [level] < [depth], so at least one child is guaranteed to meet the // firstWhere condition. - (currentNode, levelWithOffset) => currentNode.children - .firstWhere((n) => n.depth + n.level > levelWithOffset), + (currentNode, levelWithOffset) => currentNode.children.firstWhere( + (n) => n.depth + n.level > levelWithOffset, + ), ); } @@ -254,8 +252,9 @@ abstract class TreeNode> { // When this condition is called, we have already ensured that // [level] < [depth], so at least one child is guaranteed to meet the // lastWhere condition. - (currentNode, levelWithOffset) => currentNode.children - .lastWhere((n) => n.depth + n.level > levelWithOffset), + (currentNode, levelWithOffset) => currentNode.children.lastWhere( + (n) => n.depth + n.level > levelWithOffset, + ), ); } @@ -337,11 +336,7 @@ T? breadthFirstTraversal>( bool Function(T node)? returnCondition, void Function(T node)? action, }) { - return _treeTraversal( - root, - returnCondition: returnCondition, - action: action, - ); + return _treeTraversal(root, returnCondition: returnCondition, action: action); } /// Traverses a tree in depth-first preorder order. @@ -409,10 +404,7 @@ List buildFlatList>( return flatList; } -void _traverse>( - T node, - bool Function(T) callback, -) { +void _traverse>(T node, bool Function(T) callback) { final shouldContinue = callback(node); if (shouldContinue) { for (final child in node.children) { diff --git a/packages/devtools_app/lib/src/shared/primitives/utils.dart b/packages/devtools_app/lib/src/shared/primitives/utils.dart index 1ff4f601e46..ff47546c271 100644 --- a/packages/devtools_app/lib/src/shared/primitives/utils.dart +++ b/packages/devtools_app/lib/src/shared/primitives/utils.dart @@ -168,7 +168,7 @@ Future delayToReleaseUiThread({int micros = 0}) async { /// Use in long calculations, to release UI thread after each N steps. class UiReleaser { UiReleaser({this.stepsBetweenDelays = 100000, this.delayLength = 0}) - : assert(stepsBetweenDelays > 0); + : assert(stepsBetweenDelays > 0); final int stepsBetweenDelays; final int delayLength; @@ -365,7 +365,7 @@ typedef RateLimiterCallback = Future Function(); /// specified rate and that at most one async [callback] is running at a time. class RateLimiter { RateLimiter(double requestsPerSecond, this.callback) - : delayBetweenRequests = 1000 ~/ requestsPerSecond; + : delayBetweenRequests = 1000 ~/ requestsPerSecond; final RateLimiterCallback callback; Completer? _pendingRequest; @@ -446,10 +446,7 @@ class RateLimiter { /// remaining time units supported by [Duration] - (seconds, minutes, etc.). If /// you add a unit of time to this enum, modify the toString() method in /// [TimeRange] to handle the new case. -enum TimeUnit { - microseconds, - milliseconds, -} +enum TimeUnit { microseconds, milliseconds } class TimeRange { TimeRange({this.singleAssignment = true}); @@ -675,10 +672,7 @@ class Range { int get hashCode => Object.hash(begin, end); } -enum SortDirection { - ascending, - descending, -} +enum SortDirection { ascending, descending } /// A Range-like class that works for inclusive ranges of lines in source code. class LineRange { @@ -827,17 +821,21 @@ List processAnsiTerminalCodes(String? input, TextStyle defaultStyle) { .map( (entry) => TextSpan( text: entry.text, - style: entry.style.isEmpty - ? defaultStyle - : TextStyle( - color: entry.fgColor != null - ? colorFromAnsi(entry.fgColor!) - : null, - backgroundColor: entry.bgColor != null - ? colorFromAnsi(entry.bgColor!) - : null, - fontWeight: entry.bold ? FontWeight.bold : FontWeight.normal, - ), + style: + entry.style.isEmpty + ? defaultStyle + : TextStyle( + color: + entry.fgColor != null + ? colorFromAnsi(entry.fgColor!) + : null, + backgroundColor: + entry.bgColor != null + ? colorFromAnsi(entry.bgColor!) + : null, + fontWeight: + entry.bold ? FontWeight.bold : FontWeight.normal, + ), ), ) .toList(); @@ -869,17 +867,17 @@ extension LogicalKeySetExtension on LogicalKeySet { String describeKeys({bool isMacOS = false}) { // Put the modifiers first. If it has a synonym, then it's something like // shiftLeft, altRight, etc. - final sortedKeys = keys.toList() - ..sort((a, b) { - final aIsModifier = a.synonyms.isNotEmpty || _modifiers.contains(a); - final bIsModifier = b.synonyms.isNotEmpty || _modifiers.contains(b); - if (aIsModifier && !bIsModifier) { - return -1; - } else if (bIsModifier && !aIsModifier) { - return 1; - } - return a.keyLabel.compareTo(b.keyLabel); - }); + final sortedKeys = + keys.toList()..sort((a, b) { + final aIsModifier = a.synonyms.isNotEmpty || _modifiers.contains(a); + final bIsModifier = b.synonyms.isNotEmpty || _modifiers.contains(b); + if (aIsModifier && !bIsModifier) { + return -1; + } else if (bIsModifier && !aIsModifier) { + return 1; + } + return a.keyLabel.compareTo(b.keyLabel); + }); return sortedKeys.map((key) { if (_modifiers.contains(key)) { @@ -939,8 +937,10 @@ extension StringExtension on String { return contains(pattern); } else if (pattern is String) { final lowerCase = _lowercaseLookup.putIfAbsent(this, () => toLowerCase()); - final strLowerCase = - _lowercaseLookup.putIfAbsent(pattern, () => pattern.toLowerCase()); + final strLowerCase = _lowercaseLookup.putIfAbsent( + pattern, + () => pattern.toLowerCase(), + ); return lowerCase.contains(strLowerCase); } throw Exception( @@ -1052,10 +1052,7 @@ double safePositiveDouble(double value) { /// @param isUTC - if true for testing, the UTC locale is used (instead of /// the user's locale). Tests will then pass when run in any timezone. All /// formatted timestamps are displayed using the UTC locale. -String prettyTimestamp( - int? timestamp, { - bool isUtc = false, -}) { +String prettyTimestamp(int? timestamp, {bool isUtc = false}) { if (timestamp == null) return ''; final timestampDT = DateTime.fromMillisecondsSinceEpoch( timestamp, diff --git a/packages/devtools_app/lib/src/shared/profiler_utils.dart b/packages/devtools_app/lib/src/shared/profiler_utils.dart index d7bb1bfcb1e..3216e5933c3 100644 --- a/packages/devtools_app/lib/src/shared/profiler_utils.dart +++ b/packages/devtools_app/lib/src/shared/profiler_utils.dart @@ -34,8 +34,10 @@ mixin ProfilableDataMixin> on TreeNode { set inclusiveSampleCount(int? count) => _inclusiveSampleCount = count; - late double totalTimeRatio = - safeDivide(inclusiveSampleCount, profileMetaData.sampleCount); + late double totalTimeRatio = safeDivide( + inclusiveSampleCount, + profileMetaData.sampleCount, + ); late Duration totalTime = Duration( microseconds: @@ -43,23 +45,21 @@ mixin ProfilableDataMixin> on TreeNode { .round(), ); - late double selfTimeRatio = - safeDivide(exclusiveSampleCount, profileMetaData.sampleCount); + late double selfTimeRatio = safeDivide( + exclusiveSampleCount, + profileMetaData.sampleCount, + ); late Duration selfTime = Duration( microseconds: (selfTimeRatio * profileMetaData.time!.duration.inMicroseconds).round(), ); - double get inclusiveSampleRatio => safeDivide( - inclusiveSampleCount, - profileMetaData.sampleCount, - ); + double get inclusiveSampleRatio => + safeDivide(inclusiveSampleCount, profileMetaData.sampleCount); - double get exclusiveSampleRatio => safeDivide( - exclusiveSampleCount, - profileMetaData.sampleCount, - ); + double get exclusiveSampleRatio => + safeDivide(exclusiveSampleCount, profileMetaData.sampleCount); /// Returns the number of samples this data node is a part of. /// @@ -96,10 +96,7 @@ mixin ProfilableDataMixin> on TreeNode { } class ProfileMetaData { - const ProfileMetaData({ - required this.sampleCount, - required this.time, - }); + const ProfileMetaData({required this.sampleCount, required this.time}); final int sampleCount; @@ -297,12 +294,7 @@ class MethodAndSourceDisplay extends StatelessWidget { ).buildTextSpan(context), ); } else { - sourceTextSpans.add( - TextSpan( - text: sourceDisplay, - style: fontStyle, - ), - ); + sourceTextSpans.add(TextSpan(text: sourceDisplay, style: fontStyle)); } } final richText = RichText( @@ -319,9 +311,7 @@ class MethodAndSourceDisplay extends StatelessWidget { // does not extend all the way to the end of the row. return Row( mainAxisSize: MainAxisSize.min, - children: [ - Flexible(child: richText), - ], + children: [Flexible(child: richText)], ); } return richText; diff --git a/packages/devtools_app/lib/src/shared/routing.dart b/packages/devtools_app/lib/src/shared/routing.dart index 01e4293be8a..c32ef3d025e 100644 --- a/packages/devtools_app/lib/src/shared/routing.dart +++ b/packages/devtools_app/lib/src/shared/routing.dart @@ -100,13 +100,13 @@ class DevToolsRouterDelegate extends RouterDelegate ChangeNotifier, PopNavigatorRouterDelegateMixin { DevToolsRouterDelegate(this._getPage, [GlobalKey? key]) - : navigatorKey = key ?? GlobalKey(), - _isTestMode = false; + : navigatorKey = key ?? GlobalKey(), + _isTestMode = false; @visibleForTesting DevToolsRouterDelegate.test(this._getPage, [GlobalKey? key]) - : navigatorKey = key ?? GlobalKey(), - _isTestMode = true; + : navigatorKey = key ?? GlobalKey(), + _isTestMode = true; static DevToolsRouterDelegate of(BuildContext context) => Router.of(context).routerDelegate as DevToolsRouterDelegate; @@ -128,7 +128,8 @@ class DevToolsRouterDelegate extends RouterDelegate String?, DevToolsQueryParams, DevToolsNavigationState?, - ) _getPage; + ) + _getPage; /// A list of any routes/pages on the stack. /// @@ -196,13 +197,12 @@ class DevToolsRouterDelegate extends RouterDelegate Map? argUpdates, DevToolsNavigationState? state, ]) { - final newParams = currentConfiguration?.params.withUpdates(argUpdates) ?? + final newParams = + currentConfiguration?.params.withUpdates(argUpdates) ?? DevToolsQueryParams.empty(); unawaited( - _replaceStack( - DevToolsRouteConfiguration(page, newParams, state), - ), + _replaceStack(DevToolsRouteConfiguration(page, newParams, state)), ); notifyListeners(); } @@ -211,13 +211,10 @@ class DevToolsRouterDelegate extends RouterDelegate bool clearUriParam = false, required bool clearScreenParam, }) { - navigate( - homeScreenId, - { - if (clearUriParam) 'uri': null, - if (clearScreenParam) 'screen': null, - }, - ); + navigate(homeScreenId, { + if (clearUriParam) 'uri': null, + if (clearScreenParam) 'screen': null, + }); } /// Replaces the navigation stack with a new route. @@ -264,11 +261,7 @@ class DevToolsRouterDelegate extends RouterDelegate final newArgs = currentConfig.params.withUpdates(argUpdates); await _replaceStack( - DevToolsRouteConfiguration( - currentPage, - newArgs, - currentConfig.state, - ), + DevToolsRouteConfiguration(currentPage, newArgs, currentConfig.state), ); notifyListeners(); } @@ -356,10 +349,7 @@ class DevToolsNavigationState { DevToolsNavigationState({ required this.kind, required Map state, - }) : _state = { - _kKind: kind, - ...state, - }; + }) : _state = {_kKind: kind, ...state}; DevToolsNavigationState._(this._state) : kind = _state[_kKind]!; @@ -371,10 +361,7 @@ class DevToolsNavigationState { final Map _state; bool hasChanges(DevToolsNavigationState? other) { - return !mapEquals( - {...state, ...?other?.state}, - state, - ); + return !mapEquals({...state, ...?other?.state}, state); } /// Creates a new [DevToolsNavigationState] by merging this instance with @@ -384,10 +371,7 @@ class DevToolsNavigationState { /// this instance (e.g., if both instances have state with the same key, the /// state in [other] will be used). DevToolsNavigationState merge(DevToolsNavigationState other) { - final newState = { - ..._state, - ...other._state, - }; + final newState = {..._state, ...other._state}; return DevToolsNavigationState(kind: kind, state: newState); } diff --git a/packages/devtools_app/lib/src/shared/screen.dart b/packages/devtools_app/lib/src/shared/screen.dart index 74c89719f98..c9857feeaf5 100644 --- a/packages/devtools_app/lib/src/shared/screen.dart +++ b/packages/devtools_app/lib/src/shared/screen.dart @@ -127,9 +127,9 @@ enum ScreenMetaData { this.requiresLibrary, this.tutorialVideoTimestamp, }) : assert( - icon == null || iconAsset == null, - 'Only one of icon or iconAsset may be specified.', - ); + icon == null || iconAsset == null, + 'Only one of icon or iconAsset may be specified.', + ); final String id; final String? title; @@ -193,14 +193,14 @@ abstract class Screen { this.requiresVmDeveloperMode = false, this.worksWithOfflineData = false, this.showFloatingDebuggerControls = true, - }) : assert( - title == null || titleGenerator == null, - 'Only one of title or titleGenerator may be specified.', - ), - assert( - icon == null || iconAsset == null, - 'Only one of icon or iconAsset may be specified.', - ); + }) : assert( + title == null || titleGenerator == null, + 'Only one of title or titleGenerator may be specified.', + ), + assert( + icon == null || iconAsset == null, + 'Only one of icon or iconAsset may be specified.', + ); const Screen.conditional({ required String id, @@ -219,21 +219,21 @@ abstract class Screen { String? iconAsset, Key? tabKey, }) : this( - id, - requiresLibrary: requiresLibrary, - requiresConnection: requiresConnection, - requiresDartVm: requiresDartVm, - requiresFlutter: requiresFlutter, - requiresDebugBuild: requiresDebugBuild, - requiresVmDeveloperMode: requiresVmDeveloperMode, - worksWithOfflineData: worksWithOfflineData, - showFloatingDebuggerControls: showFloatingDebuggerControls, - title: title, - titleGenerator: titleGenerator, - icon: icon, - iconAsset: iconAsset, - tabKey: tabKey, - ); + id, + requiresLibrary: requiresLibrary, + requiresConnection: requiresConnection, + requiresDartVm: requiresDartVm, + requiresFlutter: requiresFlutter, + requiresDebugBuild: requiresDebugBuild, + requiresVmDeveloperMode: requiresVmDeveloperMode, + worksWithOfflineData: worksWithOfflineData, + showFloatingDebuggerControls: showFloatingDebuggerControls, + title: title, + titleGenerator: titleGenerator, + icon: icon, + iconAsset: iconAsset, + tabKey: tabKey, + ); Screen.fromMetaData( ScreenMetaData metadata, { @@ -242,22 +242,22 @@ abstract class Screen { String Function()? titleGenerator, Key? tabKey, }) : this.conditional( - id: metadata.id, - requiresLibrary: metadata.requiresLibrary, - requiresConnection: metadata.requiresConnection, - requiresDartVm: metadata.requiresDartVm, - requiresFlutter: metadata.requiresFlutter, - requiresDebugBuild: metadata.requiresDebugBuild, - requiresVmDeveloperMode: metadata.requiresVmDeveloperMode, - worksWithOfflineData: metadata.worksWithOfflineData, - shouldShowForFlutterVersion: shouldShowForFlutterVersion, - showFloatingDebuggerControls: showFloatingDebuggerControls, - title: titleGenerator == null ? metadata.title : null, - titleGenerator: titleGenerator, - icon: metadata.icon, - iconAsset: metadata.iconAsset, - tabKey: tabKey, - ); + id: metadata.id, + requiresLibrary: metadata.requiresLibrary, + requiresConnection: metadata.requiresConnection, + requiresDartVm: metadata.requiresDartVm, + requiresFlutter: metadata.requiresFlutter, + requiresDebugBuild: metadata.requiresDebugBuild, + requiresVmDeveloperMode: metadata.requiresVmDeveloperMode, + worksWithOfflineData: metadata.worksWithOfflineData, + shouldShowForFlutterVersion: shouldShowForFlutterVersion, + showFloatingDebuggerControls: showFloatingDebuggerControls, + title: titleGenerator == null ? metadata.title : null, + titleGenerator: titleGenerator, + icon: metadata.icon, + iconAsset: metadata.iconAsset, + tabKey: tabKey, + ); /// Whether to show floating debugger controls if the app is paused. /// @@ -378,8 +378,9 @@ abstract class Screen { Widget buildTab(BuildContext context) { final title = _userFacingTitle; return ValueListenableBuilder( - valueListenable: - serviceConnection.errorBadgeManager.errorCountNotifier(screenId), + valueListenable: serviceConnection.errorBadgeManager.errorCountNotifier( + screenId, + ), builder: (context, count, _) { final tab = Tab( key: tabKey, @@ -389,18 +390,16 @@ abstract class Screen { DevToolsIcon( icon: icon, iconAsset: iconAsset, - size: iconAsset != null - // Add 1.0 to adjust for margins on the screen icon assets. - ? scaleByFontFactor(defaultIconSizeBeforeScaling + 1.0) - : defaultIconSize, + size: + iconAsset != null + // Add 1.0 to adjust for margins on the screen icon assets. + ? scaleByFontFactor(defaultIconSizeBeforeScaling + 1.0) + : defaultIconSize, ), if (title.isNotEmpty) Padding( padding: const EdgeInsets.only(left: denseSpacing), - child: Text( - title, - style: Theme.of(context).regularTextStyle, - ), + child: Text(title, style: Theme.of(context).regularTextStyle), ), ], ), @@ -450,7 +449,7 @@ abstract class Screen { if (!requiresConnection) { final connected = serviceConnection.serviceManager.connectedState.value.connected && - serviceConnection.serviceManager.connectedAppInitialized; + serviceConnection.serviceManager.connectedAppInitialized; // Do not use the disconnected body in offline mode, because the default // [buildScreenBody] should be used for offline states. if (!connected && !offlineDataController.showingOfflineData.value) { @@ -490,13 +489,15 @@ abstract class Screen { _log.finest('for offline mode: returning ${screen.worksWithOfflineData}'); return ( show: screen.worksWithOfflineData, - disabledReason: screen.worksWithOfflineData - ? null - : ScreenDisabledReason.offlineDataNotSupported, + disabledReason: + screen.worksWithOfflineData + ? null + : ScreenDisabledReason.offlineDataNotSupported, ); } - final serviceReady = serviceConnection.serviceManager.isServiceAvailable && + final serviceReady = + serviceConnection.serviceManager.isServiceAvailable && serviceConnection.serviceManager.connectedApp!.connectedAppInitialized; if (!serviceReady) { if (!screen.requiresConnection) { @@ -517,8 +518,9 @@ abstract class Screen { if (screen.requiresLibrary != null) { if (serviceConnection.serviceManager.isolateManager.mainIsolate.value == null || - !serviceConnection.serviceManager - .libraryUriAvailableNow(screen.requiresLibrary)) { + !serviceConnection.serviceManager.libraryUriAvailableNow( + screen.requiresLibrary, + )) { _log.finest( 'screen requires library ${screen.requiresLibrary}: returning false', ); @@ -572,9 +574,10 @@ class BadgePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - final paint = Paint() - ..color = colorScheme.errorContainer - ..style = PaintingStyle.fill; + final paint = + Paint() + ..color = colorScheme.errorContainer + ..style = PaintingStyle.fill; final countPainter = TextPainter( text: TextSpan( @@ -612,10 +615,8 @@ class BadgePainter extends CustomPainter { } class ShortcutsConfiguration { - const ShortcutsConfiguration({ - required this.shortcuts, - required this.actions, - }) : assert(shortcuts.length == actions.length); + const ShortcutsConfiguration({required this.shortcuts, required this.actions}) + : assert(shortcuts.length == actions.length); factory ShortcutsConfiguration.empty() { return ShortcutsConfiguration(shortcuts: {}, actions: {}); diff --git a/packages/devtools_app/lib/src/shared/server/_deep_links_api.dart b/packages/devtools_app/lib/src/shared/server/_deep_links_api.dart index 3cfb382d1bc..8313ad9d92b 100644 --- a/packages/devtools_app/lib/src/shared/server/_deep_links_api.dart +++ b/packages/devtools_app/lib/src/shared/server/_deep_links_api.dart @@ -8,9 +8,7 @@ Future> requestAndroidBuildVariants(String path) async { if (isDevToolsServerAvailable) { final uri = Uri( path: DeeplinkApi.androidBuildVariants, - queryParameters: { - DeeplinkApi.deeplinkRootPathPropertyName: path, - }, + queryParameters: {DeeplinkApi.deeplinkRootPathPropertyName: path}, ); final resp = await request(uri.toString()); if (resp?.statusOk ?? false) { @@ -51,9 +49,7 @@ Future requestIosBuildOptions(String path) async { if (isDevToolsServerAvailable) { final uri = Uri( path: DeeplinkApi.iosBuildOptions, - queryParameters: { - DeeplinkApi.deeplinkRootPathPropertyName: path, - }, + queryParameters: {DeeplinkApi.deeplinkRootPathPropertyName: path}, ); final resp = await request(uri.toString()); if (resp?.statusOk ?? false) { diff --git a/packages/devtools_app/lib/src/shared/server/_preferences_api.dart b/packages/devtools_app/lib/src/shared/server/_preferences_api.dart index a75381eb122..374388d1831 100644 --- a/packages/devtools_app/lib/src/shared/server/_preferences_api.dart +++ b/packages/devtools_app/lib/src/shared/server/_preferences_api.dart @@ -12,9 +12,7 @@ Future getPreferenceValue(String key) async { final uri = Uri( path: PreferencesApi.getPreferenceValue, - queryParameters: { - PreferencesApi.preferenceKeyProperty: key, - }, + queryParameters: {PreferencesApi.preferenceKeyProperty: key}, ); final resp = await request(uri.toString()); if (resp?.statusOk ?? false) { diff --git a/packages/devtools_app/lib/src/shared/server/server.dart b/packages/devtools_app/lib/src/shared/server/server.dart index 583996a9c38..e8e7d12d4b5 100644 --- a/packages/devtools_app/lib/src/shared/server/server.dart +++ b/packages/devtools_app/lib/src/shared/server/server.dart @@ -82,10 +82,7 @@ Future notifyForVmServiceConnection({ } } -DevToolsJsonFile _devToolsJsonFileFromResponse( - Response resp, - String filePath, -) { +DevToolsJsonFile _devToolsJsonFileFromResponse(Response resp, String filePath) { final data = json.decode(resp.body) as Map; final lastModified = data['lastModifiedTime']; final lastModifiedTime = diff --git a/packages/devtools_app/lib/src/shared/server/server_api_client.dart b/packages/devtools_app/lib/src/shared/server/server_api_client.dart index bd637354315..1674272a405 100644 --- a/packages/devtools_app/lib/src/shared/server/server_api_client.dart +++ b/packages/devtools_app/lib/src/shared/server/server_api_client.dart @@ -40,17 +40,19 @@ class DevToolsServerConnection { /// /// - http://foo/devtools => http://foo/devtools/api @visibleForTesting - static Uri apiUriFor(Uri baseUri) => baseUri.path.endsWith('devtools') - ? baseUri.resolve('devtools/api/') - : baseUri.resolve('api/'); + static Uri apiUriFor(Uri baseUri) => + baseUri.path.endsWith('devtools') + ? baseUri.resolve('devtools/api/') + : baseUri.resolve('api/'); static Future connect() async { final apiUri = apiUriFor(Uri.base); final pingUri = apiUri.resolve('ping'); try { - final response = - await http.get(pingUri).timeout(const Duration(seconds: 5)); + final response = await http + .get(pingUri) + .timeout(const Duration(seconds: 5)); // When running with the local dev server Flutter may serve its index page // for missing files to support the hashless url strategy. Check the response // content to confirm it came from our server. @@ -187,16 +189,13 @@ class DevToolsServerConnection { void _notifyCurrentPage(PageChangeEvent page) { unawaited( - _callMethod( - 'currentPage', - { - 'id': page.id, - // TODO(kenz): see if we need to change the client code on the - // DevTools server to be aware of the type of embedded mode (many vs. - // one). - 'embedded': page.embedMode.embedded, - }, - ), + _callMethod('currentPage', { + 'id': page.id, + // TODO(kenz): see if we need to change the client code on the + // DevTools server to be aware of the type of embedded mode (many vs. + // one). + 'embedded': page.embedMode.embedded, + }), ); } diff --git a/packages/devtools_app/lib/src/shared/side_panel.dart b/packages/devtools_app/lib/src/shared/side_panel.dart index 570c8f4117c..778c0ee8e83 100644 --- a/packages/devtools_app/lib/src/shared/side_panel.dart +++ b/packages/devtools_app/lib/src/shared/side_panel.dart @@ -51,8 +51,10 @@ class SidePanelViewerState extends State super.initState(); visibilityController = longAnimationController(this); - visibilityAnimation = - Tween(begin: 1.0, end: 0).animate(visibilityController); + visibilityAnimation = Tween( + begin: 1.0, + end: 0, + ).animate(visibilityController); _initListeners(); } @@ -160,9 +162,7 @@ class SidePanel extends AnimatedWidget { clipBehavior: Clip.hardEdge, shape: RoundedRectangleBorder( borderRadius: defaultBorderRadius, - side: BorderSide( - color: theme.focusColor, - ), + side: BorderSide(color: theme.focusColor), ), child: Column( children: [ @@ -180,12 +180,13 @@ class SidePanel extends AnimatedWidget { markdownData.isNullOrEmpty ? Text(textIfMarkdownDataEmpty ?? '') : Expanded( - child: Markdown( - data: markdownData!, - onTapLink: (text, url, title) => - unawaited(launchUrlWithErrorHandling(url!)), - ), + child: Markdown( + data: markdownData!, + onTapLink: + (text, url, title) => + unawaited(launchUrlWithErrorHandling(url!)), ), + ), ], ), ), diff --git a/packages/devtools_app/lib/src/shared/survey.dart b/packages/devtools_app/lib/src/shared/survey.dart index 3c3dde75f03..53501ef16ed 100644 --- a/packages/devtools_app/lib/src/shared/survey.dart +++ b/packages/devtools_app/lib/src/shared/survey.dart @@ -74,16 +74,15 @@ class SurveyService { final actions = [ NotificationAction( label: _noThanksLabel, - onPressed: () => _noThanksPressed( - message: message, - ), + onPressed: () => _noThanksPressed(message: message), ), NotificationAction( label: _takeSurveyLabel, - onPressed: () => _takeSurveyPressed( - surveyUrl: _generateSurveyUrl(survey.url!), - message: message, - ), + onPressed: + () => _takeSurveyPressed( + surveyUrl: _generateSurveyUrl(survey.url!), + message: message, + ), isPrimary: true, ), ]; @@ -143,9 +142,7 @@ class SurveyService { return null; } - void _noThanksPressed({ - required String message, - }) async { + void _noThanksPressed({required String message}) async { await server.setSurveyActionTaken(); notificationService.dismiss(message); } @@ -183,9 +180,10 @@ class DevToolsSurvey { endDateAsString != null ? DateTime.parse(endDateAsString) : null; final title = json[_titleKey] as String?; final surveyUrl = json[_urlKey] as String?; - final minDevToolsVersion = minVersionAsString != null - ? SemanticVersion.parse(minVersionAsString) - : null; + final minDevToolsVersion = + minVersionAsString != null + ? SemanticVersion.parse(minVersionAsString) + : null; final devEnvironments = (json[_devEnvironmentsKey] as List?)?.cast().toList(); return DevToolsSurvey._( @@ -239,17 +237,19 @@ class DevToolsSurvey { } extension ShowSurveyExtension on DevToolsSurvey { - bool get meetsDateRequirement => (startDate == null || endDate == null) - ? false - : Range( - startDate!.millisecondsSinceEpoch, - endDate!.millisecondsSinceEpoch, - ).contains(clock.now().millisecondsSinceEpoch); + bool get meetsDateRequirement => + (startDate == null || endDate == null) + ? false + : Range( + startDate!.millisecondsSinceEpoch, + endDate!.millisecondsSinceEpoch, + ).contains(clock.now().millisecondsSinceEpoch); bool get meetsMinVersionRequirement => minDevToolsVersion == null || - SemanticVersion.parse(devToolsVersion) - .isSupported(minSupportedVersion: minDevToolsVersion!); + SemanticVersion.parse( + devToolsVersion, + ).isSupported(minSupportedVersion: minDevToolsVersion!); bool get meetsEnvironmentRequirement => devEnvironments == null || devEnvironments!.contains(ga.ideLaunched); diff --git a/packages/devtools_app/lib/src/shared/table/_flat_table.dart b/packages/devtools_app/lib/src/shared/table/_flat_table.dart index fad39645fb4..1a0fe904008 100644 --- a/packages/devtools_app/lib/src/shared/table/_flat_table.dart +++ b/packages/devtools_app/lib/src/shared/table/_flat_table.dart @@ -34,14 +34,15 @@ class SearchableFlatTable extends FlatTable { super.rowHeight, super.selectionNotifier, }) : super( - searchMatchesNotifier: searchController.searchMatches, - activeSearchMatchNotifier: searchController.activeSearchMatch, - onDataSorted: () => WidgetsBinding.instance.addPostFrameCallback((_) { - // This needs to be in a post frame callback so that the search - // matches are not updated in the middle of a table build. - searchController.refreshSearchMatches(); - }), - ); + searchMatchesNotifier: searchController.searchMatches, + activeSearchMatchNotifier: searchController.activeSearchMatch, + onDataSorted: + () => WidgetsBinding.instance.addPostFrameCallback((_) { + // This needs to be in a post frame callback so that the search + // matches are not updated in the middle of a table build. + searchController.refreshSearchMatches(); + }), + ); } /// A table that displays in a collection of [data], based on a collection of @@ -276,7 +277,8 @@ class FlatTableState extends State> with AutoDisposeMixin { FlatTable oldWidget, FlatTable newWidget, ) { - final columnsChanged = !collectionEquals( + final columnsChanged = + !collectionEquals( oldWidget.columns.map((c) => c.config), newWidget.columns.map((c) => c.config), ) || @@ -290,26 +292,27 @@ class FlatTableState extends State> with AutoDisposeMixin { @override Widget build(BuildContext context) { Widget buildTable(List columnWidths) => DevToolsTable( - tableController: tableController, - columnWidths: columnWidths, - autoScrollContent: widget.autoScrollContent, - startScrolledAtBottom: widget.startScrolledAtBottom, - rowBuilder: _buildRow, - activeSearchMatchNotifier: widget.activeSearchMatchNotifier, - rowItemExtent: widget.rowHeight ?? defaultRowHeight, - preserveVerticalScrollPosition: widget.preserveVerticalScrollPosition, - tallHeaders: widget.tallHeaders, - headerColor: widget.headerColor, - fillWithEmptyRows: widget.fillWithEmptyRows, - enableHoverHandling: widget.enableHoverHandling, - ); + tableController: tableController, + columnWidths: columnWidths, + autoScrollContent: widget.autoScrollContent, + startScrolledAtBottom: widget.startScrolledAtBottom, + rowBuilder: _buildRow, + activeSearchMatchNotifier: widget.activeSearchMatchNotifier, + rowItemExtent: widget.rowHeight ?? defaultRowHeight, + preserveVerticalScrollPosition: widget.preserveVerticalScrollPosition, + tallHeaders: widget.tallHeaders, + headerColor: widget.headerColor, + fillWithEmptyRows: widget.fillWithEmptyRows, + enableHoverHandling: widget.enableHoverHandling, + ); if (widget.sizeColumnsToFit || tableController.columnWidths == null) { return LayoutBuilder( - builder: (context, constraints) => buildTable( - tableController.computeColumnWidthsSizeToFit( - constraints.maxWidth, - ), - ), + builder: + (context, constraints) => buildTable( + tableController.computeColumnWidthsSizeToFit( + constraints.maxWidth, + ), + ), ); } return buildTable(tableController.columnWidths!); diff --git a/packages/devtools_app/lib/src/shared/table/_table_column.dart b/packages/devtools_app/lib/src/shared/table/_table_column.dart index da2e4f008ec..29d8a987d39 100644 --- a/packages/devtools_app/lib/src/shared/table/_table_column.dart +++ b/packages/devtools_app/lib/src/shared/table/_table_column.dart @@ -57,7 +57,8 @@ class _ColumnHeader extends StatelessWidget { ColumnData column, SortDirection direction, { ColumnData? secondarySortColumn, - })? onSortChanged; + })? + onSortChanged; @override Widget build(BuildContext context) { @@ -80,28 +81,30 @@ class _ColumnHeader extends StatelessWidget { const SizedBox(width: densePadding), ], Expanded( - child: column.titleTooltip != null - ? DevToolsTooltip( - message: column.titleTooltip, - padding: const EdgeInsets.all(denseSpacing), - child: title, - ) - : title, + child: + column.titleTooltip != null + ? DevToolsTooltip( + message: column.titleTooltip, + padding: const EdgeInsets.all(denseSpacing), + child: title, + ) + : title, ), ], ); return column.includeHeader ? InkWell( - canRequestFocus: false, - onTap: column.supportsSorting - ? () => _handleSortChange( - column, - secondarySortColumn: secondarySortColumn, - ) - : null, - child: headerContent, - ) + canRequestFocus: false, + onTap: + column.supportsSorting + ? () => _handleSortChange( + column, + secondarySortColumn: secondarySortColumn, + ) + : null, + child: headerContent, + ) : headerContent; } @@ -143,9 +146,7 @@ class _ColumnGroupHeaderRow extends StatelessWidget { return Container( padding: const EdgeInsets.symmetric(horizontal: defaultSpacing), decoration: BoxDecoration( - border: Border( - bottom: defaultBorderSide(Theme.of(context)), - ), + border: Border(bottom: defaultBorderSide(Theme.of(context))), ), child: ListView.builder( scrollDirection: Axis.horizontal, @@ -190,11 +191,7 @@ class _ColumnGroupSpacer extends StatelessWidget { width: columnGroupSpacing, decoration: BoxDecoration( gradient: LinearGradient( - colors: [ - Colors.black, - Theme.of(context).focusColor, - Colors.black, - ], + colors: [Colors.black, Theme.of(context).focusColor, Colors.black], ), ), ), diff --git a/packages/devtools_app/lib/src/shared/table/_table_row.dart b/packages/devtools_app/lib/src/shared/table/_table_row.dart index 310f01b909d..8dc287438bd 100644 --- a/packages/devtools_app/lib/src/shared/table/_table_row.dart +++ b/packages/devtools_app/lib/src/shared/table/_table_row.dart @@ -4,18 +4,9 @@ part of 'table.dart'; -enum _TableRowType { - data, - columnHeader, - columnGroupHeader, - filler, -} +enum _TableRowType { data, columnHeader, columnGroupHeader, filler } -enum _TableRowPartDisplayType { - column, - columnSpacer, - columnGroupSpacer, -} +enum _TableRowPartDisplayType { column, columnSpacer, columnGroupSpacer } /// Presents a [node] as a row in a table. /// @@ -43,12 +34,12 @@ class TableRow extends StatefulWidget { this.displayTreeGuidelines = false, this.searchMatchesNotifier, this.activeSearchMatchNotifier, - }) : sortColumn = null, - sortDirection = null, - secondarySortColumn = null, - onSortChanged = null, - _rowType = _TableRowType.data, - tall = false; + }) : sortColumn = null, + sortDirection = null, + secondarySortColumn = null, + onSortChanged = null, + _rowType = _TableRowType.data, + tall = false; /// Constructs a [TableRow] that is empty. const TableRow.filler({ @@ -58,23 +49,23 @@ class TableRow extends StatefulWidget { required this.columnWidths, this.columnGroups, this.backgroundColor, - }) : node = null, - isExpanded = false, - isExpandable = false, - isSelected = false, - onPressed = null, - expandableColumn = null, - isShown = true, - sortColumn = null, - sortDirection = null, - secondarySortColumn = null, - onSortChanged = null, - searchMatchesNotifier = null, - activeSearchMatchNotifier = null, - tall = false, - enableHoverHandling = false, - displayTreeGuidelines = false, - _rowType = _TableRowType.filler; + }) : node = null, + isExpanded = false, + isExpandable = false, + isSelected = false, + onPressed = null, + expandableColumn = null, + isShown = true, + sortColumn = null, + sortDirection = null, + secondarySortColumn = null, + onSortChanged = null, + searchMatchesNotifier = null, + activeSearchMatchNotifier = null, + tall = false, + enableHoverHandling = false, + displayTreeGuidelines = false, + _rowType = _TableRowType.filler; /// Constructs a [TableRow] that presents the column titles instead /// of any [node]. @@ -91,17 +82,17 @@ class TableRow extends StatefulWidget { this.onPressed, this.tall = false, this.backgroundColor, - }) : node = null, - isExpanded = false, - isExpandable = false, - isSelected = false, - expandableColumn = null, - isShown = true, - searchMatchesNotifier = null, - activeSearchMatchNotifier = null, - displayTreeGuidelines = false, - enableHoverHandling = false, - _rowType = _TableRowType.columnHeader; + }) : node = null, + isExpanded = false, + isExpandable = false, + isSelected = false, + expandableColumn = null, + isShown = true, + searchMatchesNotifier = null, + activeSearchMatchNotifier = null, + displayTreeGuidelines = false, + enableHoverHandling = false, + _rowType = _TableRowType.columnHeader; /// Constructs a [TableRow] that presents column group titles instead of any /// [node]. @@ -117,18 +108,18 @@ class TableRow extends StatefulWidget { this.onPressed, this.tall = false, this.backgroundColor, - }) : node = null, - isExpanded = false, - isExpandable = false, - isSelected = false, - expandableColumn = null, - columns = const [], - isShown = true, - searchMatchesNotifier = null, - activeSearchMatchNotifier = null, - displayTreeGuidelines = false, - enableHoverHandling = false, - _rowType = _TableRowType.columnGroupHeader; + }) : node = null, + isExpanded = false, + isExpandable = false, + isSelected = false, + expandableColumn = null, + columns = const [], + isShown = true, + searchMatchesNotifier = null, + activeSearchMatchNotifier = null, + displayTreeGuidelines = false, + enableHoverHandling = false, + _rowType = _TableRowType.columnGroupHeader; final LinkedScrollControllerGroup linkedScrollControllerGroup; @@ -188,7 +179,8 @@ class TableRow extends StatefulWidget { ColumnData column, SortDirection direction, { ColumnData? secondarySortColumn, - })? onSortChanged; + })? + onSortChanged; final ValueListenable>? searchMatchesNotifier; @@ -280,26 +272,25 @@ class _TableRowState extends State> onPressed = () => widgetOnPressed(node); } - final row = tableRowFor( - context, - onPressed: onPressed, - ); + final row = tableRowFor(context, onPressed: onPressed); final box = SizedBox( - height: widget._rowType == _TableRowType.data - ? defaultRowHeight - : defaultHeaderHeight + - (widget.tall ? scaleByFontFactor(densePadding) : 0.0), + height: + widget._rowType == _TableRowType.data + ? defaultRowHeight + : defaultHeaderHeight + + (widget.tall ? scaleByFontFactor(densePadding) : 0.0), child: Material( color: _searchAwareBackgroundColor(), - child: onPressed != null - ? InkWell( - canRequestFocus: false, - key: contentKey, - onTap: onPressed, - child: row, - ) - : row, + child: + onPressed != null + ? InkWell( + canRequestFocus: false, + key: contentKey, + onTap: onPressed, + child: row, + ) + : row, ), ); return box; @@ -347,14 +338,15 @@ class _TableRowState extends State> if (widget.isSelected) { return colorScheme.selectedRowBackgroundColor; } - final searchAwareBackgroundColor = isSearchMatch - ? Color.alphaBlend( - isActiveSearchMatch - ? activeSearchMatchColorOpaque - : searchMatchColorOpaque, - backgroundColor, - ) - : backgroundColor; + final searchAwareBackgroundColor = + isSearchMatch + ? Color.alphaBlend( + isActiveSearchMatch + ? activeSearchMatchColorOpaque + : searchMatchColorOpaque, + backgroundColor, + ) + : backgroundColor; return searchAwareBackgroundColor; } @@ -422,17 +414,19 @@ class _TableRowState extends State> content = const SizedBox.shrink(); } else if (widget._rowType == _TableRowType.columnHeader) { Widget defaultHeaderRenderer() => _ColumnHeader( - column: column, - isSortColumn: column == widget.sortColumn, - secondarySortColumn: widget.secondarySortColumn, - sortDirection: widget.sortDirection!, - onSortChanged: widget.onSortChanged, - ); + column: column, + isSortColumn: column == widget.sortColumn, + secondarySortColumn: widget.secondarySortColumn, + sortDirection: widget.sortDirection!, + onSortChanged: widget.onSortChanged, + ); // ignore: avoid-unrelated-type-assertions, false positive. if (column is ColumnHeaderRenderer) { - content = (column as ColumnHeaderRenderer) - .buildHeader(context, defaultHeaderRenderer); + content = (column as ColumnHeaderRenderer).buildHeader( + context, + defaultHeaderRenderer, + ); } // If ColumnHeaderRenderer.build returns null, fall back to the default // rendering. @@ -461,9 +455,7 @@ class _TableRowState extends State> if (column.getCaption(node) != null) TextSpan( text: ' ${column.getCaption(node)}', - style: const TextStyle( - fontStyle: FontStyle.italic, - ), + style: const TextStyle(fontStyle: FontStyle.italic), ), ], style: column.contentTextStyle( @@ -489,34 +481,30 @@ class _TableRowState extends State> } if (column == widget.expandableColumn) { - final expandIndicator = widget.isExpandable - ? ValueListenableBuilder( - valueListenable: expandController, - builder: (context, _, _) { - return RotationTransition( - turns: expandArrowAnimation, - child: Icon( - Icons.expand_more, - color: theme.colorScheme.onSurface, - size: defaultIconSize, - ), - ); - }, - ) - : SizedBox(width: defaultIconSize, height: defaultIconSize); + final expandIndicator = + widget.isExpandable + ? ValueListenableBuilder( + valueListenable: expandController, + builder: (context, _, _) { + return RotationTransition( + turns: expandArrowAnimation, + child: Icon( + Icons.expand_more, + color: theme.colorScheme.onSurface, + size: defaultIconSize, + ), + ); + }, + ) + : SizedBox(width: defaultIconSize, height: defaultIconSize); content = Row( mainAxisSize: MainAxisSize.min, - children: [ - expandIndicator, - Expanded(child: content), - ], + children: [expandIndicator, Expanded(child: content)], ); } content = Padding( padding: EdgeInsets.only(left: padding), - child: ClipRect( - child: content, - ), + child: ClipRect(child: content), ); } else { throw Exception( @@ -526,27 +514,18 @@ class _TableRowState extends State> content = SizedBox( width: columnWidth, - child: Align( - alignment: _alignmentFor(column), - child: content, - ), + child: Align(alignment: _alignmentFor(column), child: content), ); if (widget.displayTreeGuidelines && node != null && node is TreeNode && column is TreeColumnData) { content = CustomPaint( - painter: _RowGuidelinePainter( - node.level, - theme.colorScheme, - ), + painter: _RowGuidelinePainter(node.level, theme.colorScheme), child: content, ); } - return DefaultTextStyle( - style: theme.regularTextStyle, - child: content, - ); + return DefaultTextStyle(style: theme.regularTextStyle, child: content); } if (widget._rowType == _TableRowType.columnGroupHeader) { @@ -565,28 +544,25 @@ class _TableRowState extends State> physics: const ClampingScrollPhysics(), controller: scrollController, extentDelegate: rowExtentDelegate, - childrenDelegate: SliverChildBuilderDelegate( - (context, int i) { - final columnIndexMap = _columnIndexMapHelper(_rowDisplayParts); - final displayTypeForIndex = _rowDisplayParts[i]; - switch (displayTypeForIndex) { - case _TableRowPartDisplayType.column: - final index = columnIndexMap[i]!; - return columnFor( - widget.columns[index], - widget.columnWidths[index], - ); - case _TableRowPartDisplayType.columnSpacer: - return const SizedBox( - width: columnSpacing, - child: VerticalDivider(width: columnSpacing), - ); - case _TableRowPartDisplayType.columnGroupSpacer: - return const _ColumnGroupSpacer(); - } - }, - childCount: _rowDisplayParts.length, - ), + childrenDelegate: SliverChildBuilderDelegate((context, int i) { + final columnIndexMap = _columnIndexMapHelper(_rowDisplayParts); + final displayTypeForIndex = _rowDisplayParts[i]; + switch (displayTypeForIndex) { + case _TableRowPartDisplayType.column: + final index = columnIndexMap[i]!; + return columnFor( + widget.columns[index], + widget.columnWidths[index], + ); + case _TableRowPartDisplayType.columnSpacer: + return const SizedBox( + width: columnSpacing, + child: VerticalDivider(width: columnSpacing), + ); + case _TableRowPartDisplayType.columnGroupSpacer: + return const _ColumnGroupSpacer(); + } + }, childCount: _rowDisplayParts.length), ), ); 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 81bbc7c19c1..024a2ad3a1f 100644 --- a/packages/devtools_app/lib/src/shared/table/_tree_table.dart +++ b/packages/devtools_app/lib/src/shared/table/_tree_table.dart @@ -4,11 +4,7 @@ part of 'table.dart'; -enum TreeTableScrollKind { - up, - down, - parent, -} +enum TreeTableScrollKind { up, down, parent } /// A table that shows [TreeNode]s. /// @@ -42,10 +38,10 @@ class TreeTable> extends StatefulWidget { this.tallHeaders = false, this.headerColor, ValueNotifier>? selectionNotifier, - }) : selectionNotifier = selectionNotifier ?? - ValueNotifier>(Selection.empty()), - assert(columns.contains(treeColumn)), - assert(columns.contains(defaultSortColumn)); + }) : selectionNotifier = + selectionNotifier ?? ValueNotifier>(Selection.empty()), + assert(columns.contains(treeColumn)), + assert(columns.contains(defaultSortColumn)); /// Factory that creates keys for each row in this table. final Key Function(T) keyFactory; @@ -207,7 +203,8 @@ class TreeTableState> extends State> TreeTable oldWidget, TreeTable newWidget, ) { - final columnsChanged = !collectionEquals( + final columnsChanged = + !collectionEquals( oldWidget.columns.map((c) => c.title), newWidget.columns.map((c) => c.title), ) || @@ -336,10 +333,7 @@ class TreeTableState> extends State> // If there is no selected node, choose the first one. if (widget.selectionNotifier.value.node == null) { - widget.selectionNotifier.value = Selection( - node: _data[0], - nodeIndex: 0, - ); + widget.selectionNotifier.value = Selection(node: _data[0], nodeIndex: 0); } final selection = widget.selectionNotifier.value; @@ -397,8 +391,10 @@ class TreeTableState> extends State> // occupies space in the viewport so we must subtract 1 for that, and we // subtract 1 to account for the fact that a partial row could be displayed // at the top and bottom of the view. - final minCompleteItemsInView = - max((viewportHeight / defaultRowHeight).floor() - 2, 0); + final minCompleteItemsInView = max( + (viewportHeight / defaultRowHeight).floor() - 2, + 0, + ); final lastItemIndex = firstItemIndex + minCompleteItemsInView - 1; late int newSelectedNodeIndex; @@ -412,9 +408,10 @@ class TreeTableState> extends State> newSelectedNodeIndex = max(selectedNodeIndex! - 1, 0); break; case TreeTableScrollKind.parent: - newSelectedNodeIndex = selectionValue.node!.parent != null - ? max(_data.indexOf(selectionValue.node!.parent!), 0) - : 0; + newSelectedNodeIndex = + selectionValue.node!.parent != null + ? max(_data.indexOf(selectionValue.node!.parent!), 0) + : 0; break; } @@ -458,10 +455,7 @@ class TreeTableState> extends State> class _RowGuidelinePainter extends CustomPainter { _RowGuidelinePainter(this.level, this.colorScheme); - static const _treeGuidelineColors = [ - Color(0xFF13B9FD), - Color(0xFF5BC43B), - ]; + static const _treeGuidelineColors = [Color(0xFF13B9FD), Color(0xFF5BC43B)]; final int level; final ColorScheme colorScheme; diff --git a/packages/devtools_app/lib/src/shared/table/column_widths.dart b/packages/devtools_app/lib/src/shared/table/column_widths.dart index f52814c0279..362abde8ad2 100644 --- a/packages/devtools_app/lib/src/shared/table/column_widths.dart +++ b/packages/devtools_app/lib/src/shared/table/column_widths.dart @@ -55,15 +55,15 @@ extension FlatColumnWidthExtension on FlatTableController { maxWidth = max(0, maxWidth); double available = maxWidth; // Columns sorted by increasing minWidth. - final sortedColumns = columns.toList() - ..sort((a, b) { - if (a.minWidthPx != null && b.minWidthPx != null) { - return a.minWidthPx!.compareTo(b.minWidthPx!); - } - if (a.minWidthPx != null) return -1; - if (b.minWidthPx != null) return 1; - return 0; - }); + final sortedColumns = + columns.toList()..sort((a, b) { + if (a.minWidthPx != null && b.minWidthPx != null) { + return a.minWidthPx!.compareTo(b.minWidthPx!); + } + if (a.minWidthPx != null) return -1; + if (b.minWidthPx != null) return 1; + return 0; + }); for (final col in columns) { if (col.fixedWidthPx != null) { diff --git a/packages/devtools_app/lib/src/shared/table/table.dart b/packages/devtools_app/lib/src/shared/table/table.dart index dcac841a2ab..505a8d602a7 100644 --- a/packages/devtools_app/lib/src/shared/table/table.dart +++ b/packages/devtools_app/lib/src/shared/table/table.dart @@ -32,20 +32,22 @@ part '_tree_table.dart'; // TODO(devoncarew): We need to render the selected row with a different // background color. -typedef IndexedScrollableWidgetBuilder = Widget Function({ - required BuildContext context, - required LinkedScrollControllerGroup linkedScrollControllerGroup, - required int index, - required List columnWidths, - required bool isPinned, - required bool enableHoverHandling, -}); - -typedef TableKeyEventHandler = KeyEventResult Function( - KeyEvent event, - ScrollController scrollController, - BoxConstraints constraints, -); +typedef IndexedScrollableWidgetBuilder = + Widget Function({ + required BuildContext context, + required LinkedScrollControllerGroup linkedScrollControllerGroup, + required int index, + required List columnWidths, + required bool isPinned, + required bool enableHoverHandling, + }); + +typedef TableKeyEventHandler = + KeyEventResult Function( + KeyEvent event, + ScrollController scrollController, + BoxConstraints constraints, + ); class Selection { Selection({ @@ -56,10 +58,10 @@ class Selection { }) : assert(nodeIndex == null || nodeIndexCalculator == null); Selection.empty() - : node = null, - nodeIndex = null, - nodeIndexCalculator = null, - scrollIntoView = true; + : node = null, + nodeIndex = null, + nodeIndexCalculator = null, + scrollIntoView = true; final T? node; // TODO (carolynqu): get rid of nodeIndex and only use nodeIndexCalculator, https://github.com/flutter/devtools/issues/4266 @@ -137,9 +139,10 @@ class DevToolsTableState extends State> _linkedHorizontalScrollControllerGroup = LinkedScrollControllerGroup(); - final initialScrollOffset = widget.preserveVerticalScrollPosition - ? widget.tableController.tableUiState.scrollOffset - : 0.0; + final initialScrollOffset = + widget.preserveVerticalScrollPosition + ? widget.tableController.tableUiState.scrollOffset + : 0.0; widget.tableController.initScrollController(initialScrollOffset); scrollController = widget.tableController.verticalScrollController!; @@ -158,7 +161,8 @@ class DevToolsTableState extends State> void didUpdateWidget(covariant DevToolsTable oldWidget) { super.didUpdateWidget(oldWidget); - final notifiersChanged = widget.tableController.tableData != + final notifiersChanged = + widget.tableController.tableData != oldWidget.tableController.tableData || widget.selectionNotifier != oldWidget.selectionNotifier || widget.activeSearchMatchNotifier != oldWidget.activeSearchMatchNotifier; @@ -196,9 +200,10 @@ class DevToolsTableState extends State> final nodeIndex = selection.nodeIndex; if (selection.scrollIntoView && node != null) { - final selectedDisplayRow = nodeIndexCalculator != null - ? nodeIndexCalculator(node)! - : nodeIndex!; + final selectedDisplayRow = + nodeIndexCalculator != null + ? nodeIndexCalculator(node)! + : nodeIndex!; final newPos = selectedDisplayRow * defaultRowHeight; @@ -228,7 +233,8 @@ class DevToolsTableState extends State> if (index == -1) return; final y = index * defaultRowHeight; - final indexInView = y > scrollController.offset && + final indexInView = + y > scrollController.offset && y < scrollController.offset + scrollController.position.extentInside; if (!indexInView) { await scrollController.animateTo( @@ -344,9 +350,9 @@ class DevToolsTableState extends State> } double _pinnedDataHeight(BoxConstraints tableConstraints) => min( - widget.rowItemExtent! * pinnedData.length, - tableConstraints.maxHeight / 2, - ); + widget.rowItemExtent! * pinnedData.length, + tableConstraints.maxHeight / 2, + ); int _dataRowCount( BoxConstraints tableConstraints, @@ -358,7 +364,8 @@ class DevToolsTableState extends State> var maxHeight = tableConstraints.maxHeight; final columnHeadersCount = showColumnGroupHeader ? 2 : 1; - maxHeight -= columnHeadersCount * + maxHeight -= + columnHeadersCount * (defaultHeaderHeight + (widget.tallHeaders ? scaleByFontFactor(densePadding) : 0.0)); @@ -395,7 +402,8 @@ class DevToolsTableState extends State> final columnGroups = widget.tableController.columnGroups; final includeColumnGroupHeaders = widget.tableController.includeColumnGroupHeaders; - final showColumnGroupHeader = columnGroups != null && + final showColumnGroupHeader = + columnGroups != null && columnGroups.isNotEmpty && includeColumnGroupHeaders; final tableUiState = widget.tableController.tableUiState; @@ -456,11 +464,9 @@ class DevToolsTableState extends State> controller: pinnedScrollController, itemCount: pinnedData.length, itemExtent: widget.rowItemExtent, - itemBuilder: (context, index) => _buildItem( - context, - index, - isPinned: true, - ), + itemBuilder: + (context, index) => + _buildItem(context, index, isPinned: true), ), ), ), @@ -475,18 +481,22 @@ class DevToolsTableState extends State> onTapDown: (a) => widget.focusNode?.requestFocus(), child: Focus( autofocus: true, - onKeyEvent: (_, event) => widget.handleKeyEvent != null - ? widget.handleKeyEvent!( - event, - scrollController, - constraints, - ) - : KeyEventResult.ignored, + onKeyEvent: + (_, event) => + widget.handleKeyEvent != null + ? widget.handleKeyEvent!( + event, + scrollController, + constraints, + ) + : KeyEventResult.ignored, focusNode: widget.focusNode, child: ListView.builder( controller: scrollController, - itemCount: - _dataRowCount(constraints, showColumnGroupHeader), + itemCount: _dataRowCount( + constraints, + showColumnGroupHeader, + ), itemExtent: widget.rowItemExtent, itemBuilder: _buildItem, ), diff --git a/packages/devtools_app/lib/src/shared/table/table_controller.dart b/packages/devtools_app/lib/src/shared/table/table_controller.dart index 11e4a13652d..eb21d26fc50 100644 --- a/packages/devtools_app/lib/src/shared/table/table_controller.dart +++ b/packages/devtools_app/lib/src/shared/table/table_controller.dart @@ -19,11 +19,7 @@ import 'table_data.dart'; /// - [FlatTablePinBehavior.pinCopyToTop] creates a copy of the original item /// and inserts it into the list of pinned items, leaving the original item /// in the list of unpinned items. -enum FlatTablePinBehavior { - none, - pinOriginalToTop, - pinCopyToTop, -} +enum FlatTablePinBehavior { none, pinOriginalToTop, pinCopyToTop } class FlatTableController extends TableControllerBase { FlatTableController({ @@ -74,9 +70,7 @@ class FlatTableController extends TableControllerBase { if (sortOriginalData) { _modifiableOriginalData = data; } else { - _unmodifiableOriginalData = UnmodifiableListView( - List.of(data), - ); + _unmodifiableOriginalData = UnmodifiableListView(List.of(data)); } // Look up the UI state for [key], and sort accordingly. @@ -156,8 +150,8 @@ class TreeTableController> super.columnGroups, required this.treeColumn, this.autoExpandRoots = false, - }) : assert(columns.contains(treeColumn)), - assert(columns.contains(defaultSortColumn)); + }) : assert(columns.contains(treeColumn)), + assert(columns.contains(defaultSortColumn)); /// The column of the table to treat as expandable. final TreeColumnData treeColumn; @@ -178,7 +172,9 @@ class TreeTableController> } // TODO(kenz): instead of using the maximum tree depth, consider using the // maximum depth of expanded nodes. - maxTableDepth = dataRoots.map((root) => root.depth).fold( + maxTableDepth = dataRoots + .map((root) => root.depth) + .fold( 0, (currentMaxDepth, nextDepth) => max(currentMaxDepth, nextDepth), ); @@ -202,12 +198,12 @@ class TreeTableController> }) { pinnedData = []; int sortFunction(T a, T b) => _compareData( - a, - b, - column, - direction, - secondarySortColumn: secondarySortColumn, - ); + a, + b, + column, + direction, + secondarySortColumn: secondarySortColumn, + ); void sort(T dataObject) { dataObject.children ..sort(sortFunction) @@ -275,8 +271,9 @@ abstract class TableControllerBase extends DisposableController { ScrollController? verticalScrollController; void initScrollController([double initialScrollOffset = 0.0]) { - verticalScrollController = - ScrollController(initialScrollOffset: initialScrollOffset); + verticalScrollController = ScrollController( + initialScrollOffset: initialScrollOffset, + ); } void storeScrollPosition() { @@ -358,10 +355,8 @@ abstract class TableControllerBase extends DisposableController { } class TableData { - const TableData({ - required this.data, - String? key, - }) : key = key ?? defaultDataKey; + const TableData({required this.data, String? key}) + : key = key ?? defaultDataKey; factory TableData.empty() => TableData(data: const []); diff --git a/packages/devtools_app/lib/src/shared/table/table_data.dart b/packages/devtools_app/lib/src/shared/table/table_data.dart index e711a908dcd..fc3aa1a7c60 100644 --- a/packages/devtools_app/lib/src/shared/table/table_data.dart +++ b/packages/devtools_app/lib/src/shared/table/table_data.dart @@ -132,11 +132,7 @@ abstract class TreeColumnData> extends ColumnData { } } -enum ColumnAlignment { - left, - right, - center, -} +enum ColumnAlignment { left, right, center } mixin PinnableListEntry { /// Determines if the row should be pinned to the top of the table. @@ -157,9 +153,9 @@ class ColumnGroup { required Range range, String? tooltip, }) : this( - title: maybeWrapWithTooltip(child: Text(title), tooltip: tooltip), - range: range, - ); + title: maybeWrapWithTooltip(child: Text(title), tooltip: tooltip), + range: range, + ); final Widget title; @@ -212,10 +208,7 @@ abstract class TimeAndPercentageColumn extends ColumnData { this.percentageOnly = false, double columnWidth = _defaultTimeColumnWidth, super.titleTooltip, - }) : super( - title, - fixedWidthPx: scaleByFontFactor(columnWidth), - ); + }) : super(title, fixedWidthPx: scaleByFontFactor(columnWidth)); static const _defaultTimeColumnWidth = 120.0; @@ -244,9 +237,10 @@ abstract class TimeAndPercentageColumn extends ColumnData { } @override - double getValue(T dataObject) => percentageOnly - ? percentAsDoubleProvider(dataObject) - : timeProvider!(dataObject).inMicroseconds.toDouble(); + double getValue(T dataObject) => + percentageOnly + ? percentAsDoubleProvider(dataObject) + : timeProvider!(dataObject).inMicroseconds.toDouble(); @override String getDisplayValue(T dataObject) { @@ -295,10 +289,7 @@ abstract class SizeAndPercentageColumn extends ColumnData { this.percentageOnly = false, double columnWidth = _defaultMemoryColumnWidth, super.titleTooltip, - }) : super( - title, - fixedWidthPx: scaleByFontFactor(columnWidth), - ); + }) : super(title, fixedWidthPx: scaleByFontFactor(columnWidth)); static const _defaultMemoryColumnWidth = TimeAndPercentageColumn._defaultTimeColumnWidth; @@ -328,9 +319,10 @@ abstract class SizeAndPercentageColumn extends ColumnData { } @override - double getValue(T dataObject) => percentageOnly - ? percentAsDoubleProvider(dataObject) - : sizeProvider!(dataObject).toDouble(); + double getValue(T dataObject) => + percentageOnly + ? percentAsDoubleProvider(dataObject) + : sizeProvider!(dataObject).toDouble(); @override String getDisplayValue(T dataObject) { diff --git a/packages/devtools_app/lib/src/shared/tree.dart b/packages/devtools_app/lib/src/shared/tree.dart index 39d1af01544..21ff72cf858 100644 --- a/packages/devtools_app/lib/src/shared/tree.dart +++ b/packages/devtools_app/lib/src/shared/tree.dart @@ -87,8 +87,8 @@ class _TreeViewState> extends State> final T item = dataFlatList[index]; return _TreeViewItem( item, - buildDisplay: (onPressed) => - widget.dataDisplayProvider(item, onPressed), + buildDisplay: + (onPressed) => widget.dataDisplayProvider(item, onPressed), onItemSelected: _onItemSelected, onItemExpanded: _onItemExpanded, ); @@ -147,10 +147,7 @@ class _TreeViewState> extends State> void _updateItems() { setState(() { - dataFlatList = buildFlatList( - dataRoots, - onTraverse: widget.onTraverse, - ); + dataFlatList = buildFlatList(dataRoots, onTraverse: widget.onTraverse); }); } } @@ -180,23 +177,21 @@ class _TreeViewItemState> extends State<_TreeViewItem> Widget build(BuildContext context) { return Container( margin: EdgeInsets.only(left: nodeIndent(widget.data)), - color: widget.data.isSelected - ? Theme.of(context).colorScheme.selectedRowBackgroundColor - : null, + color: + widget.data.isSelected + ? Theme.of(context).colorScheme.selectedRowBackgroundColor + : null, child: Row( mainAxisSize: MainAxisSize.min, children: [ widget.data.isExpandable ? InkWell( - onTap: _onExpanded, - child: RotationTransition( - turns: expandArrowAnimation, - child: Icon( - Icons.keyboard_arrow_down, - size: defaultIconSize, - ), - ), - ) + onTap: _onExpanded, + child: RotationTransition( + turns: expandArrowAnimation, + child: Icon(Icons.keyboard_arrow_down, size: defaultIconSize), + ), + ) : SizedBox(width: defaultIconSize), Expanded(child: widget.buildDisplay(_onSelected)), ], diff --git a/packages/devtools_app/lib/src/shared/ui/colors.dart b/packages/devtools_app/lib/src/shared/ui/colors.dart index d25ce3dd105..2d2c697d0f0 100644 --- a/packages/devtools_app/lib/src/shared/ui/colors.dart +++ b/packages/devtools_app/lib/src/shared/ui/colors.dart @@ -21,14 +21,8 @@ final uiColorPalette = [ ]; final rasterColorPalette = [ - const ColorPair( - background: mainRasterColor, - foreground: Colors.white, - ), - const ColorPair( - background: Color(0xFF386EB6), - foreground: Colors.white, - ), + const ColorPair(background: mainRasterColor, foreground: Colors.white), + const ColorPair(background: Color(0xFF386EB6), foreground: Colors.white), ]; // TODO(jacobr): merge this with other color scheme extensions. @@ -68,44 +62,23 @@ const tableDecreaseColor = Color(0xFFEE284F); const treemapDeferredColor = Color(0xFFBDBDBD); const appCodeColor = ThemedColorPair( - background: ThemedColor( - light: Color(0xFFFA7B17), - dark: Color(0xFFFCAD70), - ), + background: ThemedColor(light: Color(0xFFFA7B17), dark: Color(0xFFFCAD70)), foreground: ThemedColor.fromSingle(Color(0xFF202124)), ); const nativeCodeColor = ThemedColorPair( - background: ThemedColor( - light: Color(0xFF007B83), - dark: Color(0xFF72B6C6), - ), - foreground: ThemedColor( - light: Color(0xFFF8F9FA), - dark: Color(0xFF202124), - ), + background: ThemedColor(light: Color(0xFF007B83), dark: Color(0xFF72B6C6)), + foreground: ThemedColor(light: Color(0xFFF8F9FA), dark: Color(0xFF202124)), ); const flutterCoreColor = ThemedColorPair( - background: ThemedColor( - light: Color(0xFF6864D3), - dark: Color(0xFF928EF9), - ), - foreground: ThemedColor( - light: Color(0xFFF8F9FA), - dark: Color(0xFF202124), - ), + background: ThemedColor(light: Color(0xFF6864D3), dark: Color(0xFF928EF9)), + foreground: ThemedColor(light: Color(0xFFF8F9FA), dark: Color(0xFF202124)), ); const dartCoreColor = ThemedColorPair( - background: ThemedColor( - light: Color(0xFF1D649C), - dark: Color(0xFF6887F7), - ), - foreground: ThemedColor( - light: Color(0xFFF8F9FA), - dark: Color(0xFF202124), - ), + background: ThemedColor(light: Color(0xFF1D649C), dark: Color(0xFF6887F7)), + foreground: ThemedColor(light: Color(0xFFF8F9FA), dark: Color(0xFF202124)), ); extension SyntaxHighlightingExtension on ColorScheme { diff --git a/packages/devtools_app/lib/src/shared/ui/filter.dart b/packages/devtools_app/lib/src/shared/ui/filter.dart index 8e25308bf3b..9d5b1b1a038 100644 --- a/packages/devtools_app/lib/src/shared/ui/filter.dart +++ b/packages/devtools_app/lib/src/shared/ui/filter.dart @@ -54,13 +54,14 @@ mixin FilterControllerMixin on DisposableController void setActiveFilter({String? query, SettingFilters? settingFilters}) { _activeFilter.value = Filter( - queryFilter: query != null - ? QueryFilter.parse( - query, - args: queryFilterArgs, - useRegExp: useRegExp.value, - ) - : QueryFilter.empty(args: queryFilterArgs), + queryFilter: + query != null + ? QueryFilter.parse( + query, + args: queryFilterArgs, + useRegExp: useRegExp.value, + ) + : QueryFilter.empty(args: queryFilterArgs), settingFilters: settingFilters ?? this.settingFilters, ); } @@ -101,8 +102,9 @@ mixin FilterControllerMixin on DisposableController bool get isFilterActive { final filter = activeFilter.value; final queryFilterActive = !filter.queryFilter.isEmpty; - final settingFilterActive = - filter.settingFilters.any((filter) => filter.enabled); + final settingFilterActive = filter.settingFilters.any( + (filter) => filter.enabled, + ); return queryFilterActive || settingFilterActive; } @@ -148,16 +150,14 @@ mixin FilterControllerMixin on DisposableController final settingFilterIds = settingFilters.map((filter) => filter.id); for (final settingFilterValue in valuesFromTag) { if (settingFilterIds.contains(settingFilterValue.id)) { - final settingFilter = settingFilters - .firstWhere((filter) => filter.id == settingFilterValue.id); + final settingFilter = settingFilters.firstWhere( + (filter) => filter.id == settingFilterValue.id, + ); settingFilter.setting.value = settingFilterValue.value!; } } - setActiveFilter( - query: tag.query, - settingFilters: settingFilters, - ); + setActiveFilter(query: tag.query, settingFilters: settingFilters); } void _resetToDefaultFilter() { @@ -186,12 +186,12 @@ class FilterDialog extends StatefulWidget { super.key, required this.controller, required this.filteredItem, - }) : assert(controller.queryFilterArgs.isNotEmpty), - settingFilterValuesAtOpen = List.generate( - controller.activeFilter.value.settingFilters.length, - (index) => - controller.activeFilter.value.settingFilters[index].setting.value, - ); + }) : assert(controller.queryFilterArgs.isNotEmpty), + settingFilterValuesAtOpen = List.generate( + controller.activeFilter.value.settingFilters.length, + (index) => + controller.activeFilter.value.settingFilters[index].setting.value, + ); final FilterControllerMixin controller; @@ -289,10 +289,7 @@ class _ToggleFilterElement extends StatelessWidget { ), ); if (filter.tooltip != null) { - content = DevToolsTooltip( - message: filter.tooltip, - child: content, - ); + content = DevToolsTooltip(message: filter.tooltip, child: content); } return content; } @@ -337,10 +334,7 @@ class _SettingFilterElement extends StatelessWidget { ), ); if (filter.tooltip != null) { - content = DevToolsTooltip( - message: filter.tooltip, - child: content, - ); + content = DevToolsTooltip(message: filter.tooltip, child: content); } return content; } @@ -365,10 +359,10 @@ class ToggleFilter extends SettingFilter { required super.defaultValue, super.tooltip, }) : super( - possibleValues: [true, false], - includeCallback: (T element, bool _) => includeCallback(element), - enabledCallback: (bool filterValue) => filterValue, - ); + possibleValues: [true, false], + includeCallback: (T element, bool _) => includeCallback(element), + enabledCallback: (bool filterValue) => filterValue, + ); } /// A filter setting that can be set to any of the predefined values @@ -387,14 +381,14 @@ class SettingFilter { required this.possibleValues, this.possibleValueDisplays, this.tooltip, - }) : _includeCallback = includeCallback, - _enabledCallback = enabledCallback, - setting = ValueNotifier(defaultValue), - assert(possibleValues.contains(defaultValue)), - assert( - possibleValueDisplays == null || - possibleValues.length == possibleValueDisplays.length, - ); + }) : _includeCallback = includeCallback, + _enabledCallback = enabledCallback, + setting = ValueNotifier(defaultValue), + assert(possibleValues.contains(defaultValue)), + assert( + possibleValueDisplays == null || + possibleValues.length == possibleValueDisplays.length, + ); /// The unique id for this setting filter. /// @@ -491,21 +485,25 @@ class QueryFilter { if (value.isNotEmpty) { for (final arg in args.values) { if (arg.matchesKey(part)) { - arg.isNegative = - part.startsWith(QueryFilterArgument.negativePrefix); - final valueStrings = - value.split(QueryFilterArgument.valueSeparator); - arg.values = useRegExp - ? valueStrings - .map((v) => RegExp(v, caseSensitive: false)) - .toList() - : valueStrings; + arg.isNegative = part.startsWith( + QueryFilterArgument.negativePrefix, + ); + final valueStrings = value.split( + QueryFilterArgument.valueSeparator, + ); + arg.values = + useRegExp + ? valueStrings + .map((v) => RegExp(v, caseSensitive: false)) + .toList() + : valueStrings; } } } } else { - substringExpressions - .add(useRegExp ? RegExp(part, caseSensitive: false) : part); + substringExpressions.add( + useRegExp ? RegExp(part, caseSensitive: false) : part, + ); } } @@ -532,12 +530,13 @@ class QueryFilter { final bool isEmpty; - String get query => isEmpty - ? '' - : [ - ...substringExpressions.toStringList(), - for (final arg in filterArguments.values) arg.display, - ].join(' ').trim(); + String get query => + isEmpty + ? '' + : [ + ...substringExpressions.toStringList(), + for (final arg in filterArguments.values) arg.display, + ].join(' ').trim(); } class QueryFilterArgument { @@ -591,9 +590,10 @@ class QueryFilterArgument { var matches = false; for (final value in values) { - matches = substringMatch - ? dataValue.caseInsensitiveContains(value) - : dataValue.caseInsensitiveEquals(value); + matches = + substringMatch + ? dataValue.caseInsensitiveContains(value) + : dataValue.caseInsensitiveEquals(value); if (matches) break; } return isNegative ? !matches : matches; @@ -663,35 +663,38 @@ class _StandaloneFilterFieldState extends State> autofocus: true, hintText: 'Filter', controller: queryTextFieldController, - prefixIcon: widget.controller.settingFilters.isNotEmpty - ? Container( - height: inputDecorationElementHeight, - padding: const EdgeInsets.only( - left: densePadding, - right: denseSpacing, - ), - child: ValueListenableBuilder( - valueListenable: widget.controller.activeFilter, - builder: (context, _, _) { - return DevToolsFilterButton( - message: 'More filters', - onPressed: () { - unawaited( - showDialog( - context: context, - builder: (context) => FilterDialog( - controller: widget.controller, - filteredItem: widget.filteredItem, + prefixIcon: + widget.controller.settingFilters.isNotEmpty + ? Container( + height: inputDecorationElementHeight, + padding: const EdgeInsets.only( + left: densePadding, + right: denseSpacing, + ), + child: ValueListenableBuilder( + valueListenable: widget.controller.activeFilter, + builder: (context, _, _) { + return DevToolsFilterButton( + message: 'More filters', + onPressed: () { + unawaited( + showDialog( + context: context, + builder: + (context) => FilterDialog( + controller: widget.controller, + filteredItem: widget.filteredItem, + ), ), - ), - ); - }, - isFilterActive: widget.controller.isFilterActive, - ); - }, - ), - ) - : null, + ); + }, + isFilterActive: + widget.controller.isFilterActive, + ); + }, + ), + ) + : null, additionalSuffixActions: [ if (widget.controller.queryFilterArgs.isNotEmpty) InputDecorationSuffixButton.help( @@ -758,16 +761,14 @@ class _FilterSyntax extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - Text( - ''' + Text(''' Type a query to show or hide specific ${pluralize(filteredItem, 2)}. Any text that is not paired with an available filter key below will be queried against all available data for each $filteredItem. Available filters: -''', - ), +'''), Padding( padding: const EdgeInsets.only(left: defaultSpacing), child: Row( @@ -778,10 +779,7 @@ Available filters: mainAxisSize: MainAxisSize.min, children: [ for (final key in filterKeys) - Text( - key, - style: usageTextStyle, - ), + Text(key, style: usageTextStyle), ], ), ), @@ -792,10 +790,7 @@ Available filters: mainAxisSize: MainAxisSize.min, children: [ for (final exampleUsage in filterExampleUsages) - Text( - '(e.g. $exampleUsage)', - style: usageTextStyle, - ), + Text('(e.g. $exampleUsage)', style: usageTextStyle), ], ), ), @@ -846,8 +841,8 @@ class FilterTag { final bool useRegExp; String get tag => [ - query.trim(), - jsonEncode(settingFilterValues), - if (useRegExp) useRegExpTag, - ].join(filterTagSeparator); + query.trim(), + jsonEncode(settingFilterValues), + if (useRegExp) useRegExpTag, + ].join(filterTagSeparator); } diff --git a/packages/devtools_app/lib/src/shared/ui/hover.dart b/packages/devtools_app/lib/src/shared/ui/hover.dart index b05b1feb296..29b353d69b9 100644 --- a/packages/devtools_app/lib/src/shared/ui/hover.dart +++ b/packages/devtools_app/lib/src/shared/ui/hover.dart @@ -17,12 +17,12 @@ import 'utils.dart'; double get _maxHoverCardHeight => scaleByFontFactor(250.0); TextStyle get _hoverTitleTextStyle => fixBlurryText( - TextStyle( - fontWeight: FontWeight.normal, - fontSize: scaleByFontFactor(15.0), - decoration: TextDecoration.none, - ), - ); + TextStyle( + fontWeight: FontWeight.normal, + fontSize: scaleByFontFactor(15.0), + decoration: TextDecoration.none, + ), +); /// Regex for valid Dart identifiers. final _identifier = RegExp(r'^[a-zA-Z0-9]|_|\$'); @@ -196,16 +196,16 @@ class HoverCard { required HoverCardController hoverCardController, String? title, }) : this( - context: context, - contents: contents, - width: width, - position: Offset( - math.max(0, event.position.dx - (width / 2.0)), - event.position.dy + _hoverYOffset, - ), - title: title, - hoverCardController: hoverCardController, - ); + context: context, + contents: contents, + width: width, + position: Offset( + math.max(0, event.position.dx - (width / 2.0)), + event.position.dy + _hoverYOffset, + ), + title: title, + hoverCardController: hoverCardController, + ); late OverlayEntry _overlayEntry; @@ -271,18 +271,18 @@ class HoverCardController { } } -typedef AsyncGenerateHoverCardDataFunc = Future Function({ - required PointerHoverEvent event, +typedef AsyncGenerateHoverCardDataFunc = + Future Function({ + required PointerHoverEvent event, - /// Returns true if the HoverCard is no longer visible. - /// - /// Use this callback to short circuit long running tasks. - required bool Function() isHoverStale, -}); + /// Returns true if the HoverCard is no longer visible. + /// + /// Use this callback to short circuit long running tasks. + required bool Function() isHoverStale, + }); -typedef SyncGenerateHoverCardDataFunc = HoverCardData Function( - PointerHoverEvent event, -); +typedef SyncGenerateHoverCardDataFunc = + HoverCardData Function(PointerHoverEvent event); /// A hover card based tooltip. class HoverCardTooltip extends StatefulWidget { @@ -312,8 +312,8 @@ class HoverCardTooltip extends StatefulWidget { required this.generateHoverCardData, required this.child, this.disposable, - }) : asyncGenerateHoverCardData = null, - asyncTimeout = null; + }) : asyncGenerateHoverCardData = null, + asyncTimeout = null; static const _hoverDelay = Duration(milliseconds: 500); static double get defaultHoverWidth => scaleByFontFactor(450.0); @@ -408,9 +408,10 @@ class _HoverCardTooltipState extends State { HoverCard? spinnerHoverCard; final hoverCardDataFuture = asyncGenerateHoverCardData( event: event, - isHoverStale: () => - spinnerHoverCard != null && - !_hoverCardController.isHoverCardStillActive(spinnerHoverCard), + isHoverStale: + () => + spinnerHoverCard != null && + !_hoverCardController.isHoverCardStillActive(spinnerHoverCard), ); final hoverCardDataCompleter = _hoverCardDataCompleter(hoverCardDataFuture); // If we have set the async hover card to show up only after a timeout, @@ -449,9 +450,7 @@ class _HoverCardTooltipState extends State { hoverCardController: _hoverCardController, ); - _setHoverCard( - spinnerHoverCard, - ); + _setHoverCard(spinnerHoverCard); // The spinner is showing, we can now generate the HoverCardData final hoverCardData = await hoverCardDataCompleter.future; diff --git a/packages/devtools_app/lib/src/shared/ui/icons.dart b/packages/devtools_app/lib/src/shared/ui/icons.dart index a7ce424e631..90a406e25c5 100644 --- a/packages/devtools_app/lib/src/shared/ui/icons.dart +++ b/packages/devtools_app/lib/src/shared/ui/icons.dart @@ -77,18 +77,12 @@ class CircleIcon extends StatelessWidget { return Container( width: defaultIconSize, height: defaultIconSize, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: color, - ), + decoration: BoxDecoration(shape: BoxShape.circle, color: color), alignment: Alignment.center, child: Text( text, textAlign: TextAlign.center, - style: TextStyle( - fontSize: scaleByFontFactor(9.0), - color: textColor, - ), + style: TextStyle(fontSize: scaleByFontFactor(9.0), color: textColor), ), ); } @@ -154,7 +148,7 @@ class CustomIconMaker { class IconKind { const IconKind(this.name, this.icon, [AssetImageIcon? abstractIcon]) - : abstractIcon = abstractIcon ?? icon; + : abstractIcon = abstractIcon ?? icon; static IconKind classIcon = const IconKind( 'class', @@ -258,10 +252,7 @@ class _ColorIconPainter extends CustomPainter { ), greyPaint, ) - ..drawRect( - iconRect, - Paint()..color = color, - ) + ..drawRect(iconRect, Paint()..color = color) ..drawRect( iconRect, Paint() @@ -297,8 +288,8 @@ class AssetImageIcon extends StatelessWidget { this.color, double? height, double? width, - }) : _width = width, - _height = height; + }) : _width = width, + _height = height; final String asset; final Color? color; @@ -334,17 +325,12 @@ class Octicons { /// A widget that renders either an [icon] from a font glyph or an [iconAsset] /// from the app bundle. class DevToolsIcon extends StatelessWidget { - DevToolsIcon({ - super.key, - this.icon, - this.iconAsset, - this.color, - double? size, - }) : assert( - (icon == null) != (iconAsset == null), - 'Exactly one of icon and iconAsset must be specified.', - ), - size = size ?? defaultIconSize; + DevToolsIcon({super.key, this.icon, this.iconAsset, this.color, double? size}) + : assert( + (icon == null) != (iconAsset == null), + 'Exactly one of icon and iconAsset must be specified.', + ), + size = size ?? defaultIconSize; /// The icon to use for this screen's tab. /// @@ -364,16 +350,12 @@ class DevToolsIcon extends StatelessWidget { Widget build(BuildContext context) { final color = this.color ?? Theme.of(context).colorScheme.onSurface; return icon != null - ? Icon( - icon, - size: size, - color: color, - ) + ? Icon(icon, size: size, color: color) : AssetImageIcon( - asset: iconAsset!, - height: size, - width: size, - color: color, - ); + asset: iconAsset!, + height: size, + width: size, + color: color, + ); } } diff --git a/packages/devtools_app/lib/src/shared/ui/search.dart b/packages/devtools_app/lib/src/shared/ui/search.dart index 4f59c7acb53..c4f62dce393 100644 --- a/packages/devtools_app/lib/src/shared/ui/search.dart +++ b/packages/devtools_app/lib/src/shared/ui/search.dart @@ -42,7 +42,8 @@ mixin SearchControllerMixin { set search(String value) { final previousSearchValue = _searchNotifier.value; - final shouldSearchPreviousMatches = previousSearchValue.isNotEmpty && + final shouldSearchPreviousMatches = + previousSearchValue.isNotEmpty && value.caseInsensitiveContains(previousSearchValue); _searchNotifier.value = value; refreshSearchMatches(searchPreviousMatches: shouldSearchPreviousMatches); @@ -188,8 +189,8 @@ mixin SearchControllerMixin { matchIndex.value = 1; // first item because [matchIndex] us 1-based } _activeSearchMatch.value?.isActiveSearchMatch = false; - _activeSearchMatch.value = searchMatches.value[activeMatchIndex] - ..isActiveSearchMatch = true; + _activeSearchMatch.value = + searchMatches.value[activeMatchIndex]..isActiveSearchMatch = true; onMatchChanged(activeMatchIndex); } @@ -199,7 +200,8 @@ mixin SearchControllerMixin { /// If [matchesForSearch] is overridden in such a way that /// [currentDataToSearchThrough] is not used, then this getter does not need /// to be implemented. - Iterable get currentDataToSearchThrough => throw UnimplementedError( + Iterable get currentDataToSearchThrough => + throw UnimplementedError( 'Implement this getter in order to use the default' ' [matchesForSearch] behavior.', ); @@ -248,8 +250,8 @@ mixin SearchControllerMixin { void initSearch() { _searchTextFieldController?.dispose(); _searchFieldFocusNode?.dispose(); - _searchTextFieldController = SearchTextEditingController() - ..text = _searchNotifier.value; + _searchTextFieldController = + SearchTextEditingController()..text = _searchNotifier.value; _searchFieldFocusNode = FocusNode(debugLabel: 'search-field'); } @@ -280,8 +282,8 @@ class AutoComplete extends StatefulWidget { required this.onTap, bool bottom = true, // If false placed above. bool maxWidth = true, - }) : isBottom = bottom, - isMaxWidth = maxWidth; + }) : isBottom = bottom, + isMaxWidth = maxWidth; final AutoCompleteSearchControllerMixin controller; final GlobalKey searchFieldKey; @@ -328,32 +330,33 @@ class AutoCompleteState extends State with AutoDisposeMixin { final colorScheme = Theme.of(context).colorScheme; - final autoCompleteTextStyle = Theme.of(context) - .regularTextStyle - .copyWith(color: colorScheme.contrastTextColor); - - final autoCompleteHighlightedTextStyle = - Theme.of(context).regularTextStyle.copyWith( - fontWeight: FontWeight.bold, - ); - - final tileContents = searchAutoComplete.value - .map( - (match) => _maybeHighlightMatchText( - match, - autoCompleteTextStyle, - autoCompleteHighlightedTextStyle, - ), - ) - .toList(); + final autoCompleteTextStyle = Theme.of( + context, + ).regularTextStyle.copyWith(color: colorScheme.contrastTextColor); + + final autoCompleteHighlightedTextStyle = Theme.of( + context, + ).regularTextStyle.copyWith(fontWeight: FontWeight.bold); + + final tileContents = + searchAutoComplete.value + .map( + (match) => _maybeHighlightMatchText( + match, + autoCompleteTextStyle, + autoCompleteHighlightedTextStyle, + ), + ) + .toList(); // When there are no tiles present, we don't need to display the // auto complete list. if (tileContents.isEmpty) return const SizedBox.shrink(); - final tileEntryHeight = tileContents.isEmpty - ? 0.0 - : calculateTextSpanHeight(tileContents.first) + denseSpacing; + final tileEntryHeight = + tileContents.isEmpty + ? 0.0 + : calculateTextSpanHeight(tileContents.first) + denseSpacing; // Find the searchField and place overlay below bottom of TextField and // make overlay width of TextField. This is also we decide the height of @@ -367,15 +370,17 @@ class AutoCompleteState extends State with AutoDisposeMixin { 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(); + topMatchesLimit = + min( + defaultTopMatchesLimit, + (maxAreaForPopup / tileEntryHeight) - 1, // zero based. + ).truncate(); // Total tiles visible. - final totalTiles = bottom - ? searchAutoComplete.value.length - : (maxAreaForPopup / tileEntryHeight).truncateToDouble(); + final totalTiles = + bottom + ? searchAutoComplete.value.length + : (maxAreaForPopup / tileEntryHeight).truncateToDouble(); final autoCompleteTiles = []; final count = min(searchAutoComplete.value.length, totalTiles); @@ -403,9 +408,10 @@ class AutoCompleteState extends State with AutoDisposeMixin { return Positioned( key: searchAutoCompleteKey, - width: isMaxWidth - ? box.size.width - : AutoCompleteSearchControllerMixin.minPopupWidth, + width: + isMaxWidth + ? box.size.width + : AutoCompleteSearchControllerMixin.minPopupWidth, height: count * tileEntryHeight, child: CompositedTransformFollower( link: controller.autoCompleteLayerLink, @@ -432,19 +438,16 @@ class AutoCompleteState extends State with AutoDisposeMixin { TextStyle highlightedTextStyle, ) { return match.transformAutoCompleteMatch( - transformMatchedSegment: (segment) => TextSpan( - text: segment, - style: highlightedTextStyle, - ), - transformUnmatchedSegment: (segment) => TextSpan( - text: segment, - style: regularTextStyle, - ), - combineSegments: (segments) => TextSpan( - text: segments.first.text, - style: segments.first.style, - children: segments.sublist(1), - ), + transformMatchedSegment: + (segment) => TextSpan(text: segment, style: highlightedTextStyle), + transformUnmatchedSegment: + (segment) => TextSpan(text: segment, style: regularTextStyle), + combineSegments: + (segments) => TextSpan( + text: segments.first.text, + style: segments.first.style, + children: segments.sublist(1), + ), ); } } @@ -489,10 +492,7 @@ class AutoCompleteTile extends StatelessWidget { currentHoveredIndex == index ? highlightColor : defaultColor, padding: const EdgeInsets.symmetric(horizontal: denseSpacing), alignment: Alignment.centerLeft, - child: Text.rich( - textSpan, - maxLines: 1, - ), + child: Text.rich(textSpan, maxLines: 1), ); }, ), @@ -559,9 +559,10 @@ mixin AutoCompleteSearchControllerMixin on SearchControllerMixin { final _currentHoveredIndex = ValueNotifier(0); - String? get currentHoveredText => searchAutoComplete.value.isNotEmpty - ? searchAutoComplete.value[currentHoveredIndex.value].text - : null; + String? get currentHoveredText => + searchAutoComplete.value.isNotEmpty + ? searchAutoComplete.value[currentHoveredIndex.value].text + : null; /// Last X position of caret in search field, used for pop-up position. double xPosition = 0.0; @@ -608,8 +609,9 @@ mixin AutoCompleteSearchControllerMixin on SearchControllerMixin { void updateCurrentSuggestion(String activeWord) { final hoveredText = currentHoveredText; - final suggestion = - hoveredText?.substring(min(activeWord.length, hoveredText.length)); + final suggestion = hoveredText?.substring( + min(activeWord.length, hoveredText.length), + ); if (suggestion == null || suggestion.isEmpty) { clearCurrentSuggestion(); @@ -715,10 +717,7 @@ mixin AutoCompleteSearchControllerMixin on SearchControllerMixin { var lastSpaceIndex = selectionValue.lastIndexOf(handleFields ? '.' : ' '); lastSpaceIndex = lastSpaceIndex >= 0 ? lastSpaceIndex + 1 : 0; - activeWord = selectionValue.substring( - lastSpaceIndex, - startSelection, - ); + activeWord = selectionValue.substring(lastSpaceIndex, startSelection); var variableStart = -1; // Validate activeWord is really a word. @@ -742,10 +741,7 @@ mixin AutoCompleteSearchControllerMixin on SearchControllerMixin { break; } else { lastSpaceIndex += variableStart; - activeWord = selectionValue.substring( - lastSpaceIndex, - startSelection, - ); + activeWord = selectionValue.substring(lastSpaceIndex, startSelection); break; } } @@ -788,17 +784,16 @@ mixin SearchableMixin { typedef SelectAutoComplete = void Function(String selection); /// Callback to handle highlighting item in the drop-down list. -typedef HighlightAutoComplete = void Function( - AutoCompleteSearchControllerMixin controller, - bool directionDown, -); +typedef HighlightAutoComplete = + void Function( + AutoCompleteSearchControllerMixin controller, + bool directionDown, + ); /// Provided by clients to specify where the autocomplete overlay should be /// positioned relative to the input text. -typedef OverlayXPositionBuilder = double Function( - String inputValue, - TextStyle? inputStyle, -); +typedef OverlayXPositionBuilder = + double Function(String inputValue, TextStyle? inputStyle); class SearchTextEditingController extends TextEditingController { String? _suggestionText; @@ -1047,7 +1042,8 @@ class StatelessSearchField // Guarantee that the TextField on all platforms renders in the same // color for border, label text, and cursor. Primarly, so golden screen // snapshots will compare with the exact color. - decoration: decoration ?? + decoration: + decoration ?? InputDecoration( constraints: BoxConstraints( minHeight: searchFieldHeight ?? defaultTextFieldHeight, @@ -1061,24 +1057,26 @@ class StatelessSearchField labelText: label, labelStyle: theme.subtleTextStyle, prefixIcon: Icon(Icons.search, size: defaultIconSize), - prefix: prefix != null - ? Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - prefix!, - SizedBox( - height: inputDecorationElementHeight, - width: defaultIconSize, - child: Transform.rotate( - angle: degToRad(90), - child: PaddedDivider.vertical(), + prefix: + prefix != null + ? Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + prefix!, + SizedBox( + height: inputDecorationElementHeight, + width: defaultIconSize, + child: Transform.rotate( + angle: degToRad(90), + child: PaddedDivider.vertical(), + ), ), - ), - ], - ) - : null, - suffix: suffix ?? + ], + ) + : null, + suffix: + suffix ?? _SearchFieldSuffix( controller: controller, supportsNavigation: supportsNavigation, @@ -1352,11 +1350,11 @@ class _SearchFieldSuffix extends StatelessWidget { return supportsNavigation ? SearchNavigationControls(controller, onClose: onClose) : InputDecorationSuffixButton.close( - onPressed: () { - controller.searchTextFieldController.clear(); - onClose?.call(); - }, - ); + onPressed: () { + controller.searchTextFieldController.clear(); + onClose?.call(); + }, + ); } } @@ -1389,13 +1387,14 @@ class SearchNavigationControls extends StatelessWidget { child: SizedBox( width: scaleByFontFactor(smallProgressSize), height: scaleByFontFactor(smallProgressSize), - child: isSearchInProgress - ? SmallCircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - Theme.of(context).regularTextStyle.color, - ), - ) - : const SizedBox(), + child: + isSearchInProgress + ? SmallCircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + Theme.of(context).regularTextStyle.color, + ), + ) + : const SizedBox(), ), ), _matchesStatus(numMatches), @@ -1456,7 +1455,8 @@ mixin SearchableDataMixin { /// [SearchControllerMixin.matchesForSearch] is overridden in such a way that /// [matchesSearchToken] is not used, then this method does not need to be /// implemented. - bool matchesSearchToken(RegExp regExpSearch) => throw UnimplementedError( + bool matchesSearchToken(RegExp regExpSearch) => + throw UnimplementedError( 'Implement this method in order to use the default' ' [SearchControllerMixin.matchesForSearch] behavior.', ); @@ -1482,8 +1482,7 @@ class AutoCompleteController extends DisposableController List matchesForSearch( String search, { bool searchPreviousMatches = false, - }) => - const []; + }) => const []; } class AutoCompleteMatch { @@ -1508,13 +1507,17 @@ class AutoCompleteMatch { for (final segment in matchedSegments) { if (previousEndIndex < segment.begin) { // Add the unmatched segment before the current matched segment: - final segmentBefore = - text.substring(previousEndIndex, segment.begin as int); + final segmentBefore = text.substring( + previousEndIndex, + segment.begin as int, + ); segments.add(transformUnmatchedSegment(segmentBefore)); } // Add the matched segment: - final matchedSegment = - text.substring(segment.begin as int, segment.end as int); + final matchedSegment = text.substring( + segment.begin as int, + segment.end as int, + ); segments.add(transformMatchedSegment(matchedSegment)); previousEndIndex = segment.end as int; } diff --git a/packages/devtools_app/lib/src/shared/ui/tab.dart b/packages/devtools_app/lib/src/shared/ui/tab.dart index e957d785dbf..518d05a8b98 100644 --- a/packages/devtools_app/lib/src/shared/ui/tab.dart +++ b/packages/devtools_app/lib/src/shared/ui/tab.dart @@ -24,11 +24,9 @@ class DevToolsTab extends Tab { required this.gaId, this.trailing, super.child, - }) : assert(text != null || child != null || icon != null), - assert(text == null || child == null), - super( - height: calculateHeight(icon, text, child), - ); + }) : assert(text != null || child != null || icon != null), + assert(text == null || child == null), + super(height: calculateHeight(icon, text, child)); factory DevToolsTab.create({ Key? key, @@ -40,10 +38,7 @@ class DevToolsTab extends Tab { key: key ?? ValueKey(tabName), gaId: '${gaPrefix}_$tabName', trailing: trailing, - child: Text( - tabName, - overflow: TextOverflow.ellipsis, - ), + child: Text(tabName, overflow: TextOverflow.ellipsis), ); } @@ -87,9 +82,9 @@ class AnalyticsTabbedView extends StatefulWidget { this.initialSelectedIndex, this.analyticsSessionIdentifier, }) : trailingWidgets = List.generate( - tabs.length, - (index) => tabs[index].tab.trailing ?? const SizedBox(), - ); + tabs.length, + (index) => tabs[index].tab.trailing ?? const SizedBox(), + ); final List tabs; @@ -133,10 +128,7 @@ class _AnalyticsTabbedViewState extends State _tabController?.removeListener(_onTabChanged); _tabController?.dispose(); - _tabController = TabController( - length: widget.tabs.length, - vsync: this, - ); + _tabController = TabController(length: widget.tabs.length, vsync: this); final initialIndex = widget.initialSelectedIndex; if (initialIndex != null) { @@ -187,7 +179,8 @@ class _AnalyticsTabbedViewState extends State super.didUpdateWidget(oldWidget); if (oldWidget.tabs != widget.tabs || oldWidget.gaScreen != widget.gaScreen) { - final isNewSession = oldWidget.analyticsSessionIdentifier != + final isNewSession = + oldWidget.analyticsSessionIdentifier != widget.analyticsSessionIdentifier && widget.analyticsSessionIdentifier != null; _initTabController(isNewSession: isNewSession); diff --git a/packages/devtools_app/lib/src/shared/ui/utils.dart b/packages/devtools_app/lib/src/shared/ui/utils.dart index f996a418a70..353e99fb83f 100644 --- a/packages/devtools_app/lib/src/shared/ui/utils.dart +++ b/packages/devtools_app/lib/src/shared/ui/utils.dart @@ -157,7 +157,8 @@ class _OffsetScrollbarState extends State { // offset controller. double delta = 0.0; if (widget.offsetController.position.hasContentDimensions) { - delta = widget.offsetController.offset - + delta = + widget.offsetController.offset - widget.offsetController.position.maxScrollExtent + widget.offsetController.position.minScrollExtent; if (widget.offsetController.position.hasViewportDimension) { @@ -165,22 +166,21 @@ class _OffsetScrollbarState extends State { // The viewport dimension from the offsetController may be one frame // behind the true viewport dimension. We add this delta so the // scrollbar always appears stuck to the side of the viewport. - delta += widget.offsetControllerViewportDimension - + delta += + widget.offsetControllerViewportDimension - widget.offsetController.position.viewportDimension; } } - final offset = widget.axis == Axis.vertical - ? Offset(delta, 0.0) - : Offset(0.0, delta); + final offset = + widget.axis == Axis.vertical + ? Offset(delta, 0.0) + : Offset(0.0, delta); return Transform.translate( offset: offset, child: Scrollbar( thumbVisibility: widget.isAlwaysShown, controller: widget.controller, - child: Transform.translate( - offset: -offset, - child: child, - ), + child: Transform.translate(offset: -offset, child: child), ), ); }, @@ -190,10 +190,7 @@ class _OffsetScrollbarState extends State { } /// Scrolls to [position] if [position] is not already visible in the scroll view. -void maybeScrollToPosition( - ScrollController scrollController, - double position, -) { +void maybeScrollToPosition(ScrollController scrollController, double position) { final extentVisible = Range( scrollController.offset, scrollController.offset + scrollController.position.extentInside, @@ -246,9 +243,7 @@ class ThemedColorPair { class ThemedColor { const ThemedColor({required this.light, required this.dark}); - const ThemedColor.fromSingle(Color color) - : light = color, - dark = color; + const ThemedColor.fromSingle(Color color) : light = color, dark = color; final Color light; diff --git a/packages/devtools_app/lib/src/shared/ui/vm_flag_widgets.dart b/packages/devtools_app/lib/src/shared/ui/vm_flag_widgets.dart index 4cdae9a510b..6de808e6375 100644 --- a/packages/devtools_app/lib/src/shared/ui/vm_flag_widgets.dart +++ b/packages/devtools_app/lib/src/shared/ui/vm_flag_widgets.dart @@ -175,18 +175,20 @@ class _VMFlagsDialogState extends State with AutoDisposeMixin { } void _updateFromController() { - flags = (serviceConnection.vmFlagManager.flags.value?.flags ?? []) - .map((flag) => _DialogFlag(flag)) - .toList(); + flags = + (serviceConnection.vmFlagManager.flags.value?.flags ?? []) + .map((flag) => _DialogFlag(flag)) + .toList(); _refilter(); } void _refilter() { final filter = filterController.text.trim().toLowerCase(); - filteredFlags = filter.isEmpty - ? flags - : flags.where((flag) => flag.filterText.contains(filter)).toList(); + filteredFlags = + filter.isEmpty + ? flags + : flags.where((flag) => flag.filterText.contains(filter)).toList(); } @override @@ -210,16 +212,10 @@ class _VMFlagsDialogState extends State with AutoDisposeMixin { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - width: 875, - height: 375, - child: _FlagTable(filteredFlags), - ), + SizedBox(width: 875, height: 375, child: _FlagTable(filteredFlags)), ], ), - actions: const [ - DialogCloseButton(), - ], + actions: const [DialogCloseButton()], ); } } @@ -250,11 +246,7 @@ class _FlagTable extends StatelessWidget { } class _NameColumn extends ColumnData<_DialogFlag> { - _NameColumn() - : super( - 'Name', - fixedWidthPx: scaleByFontFactor(180), - ); + _NameColumn() : super('Name', fixedWidthPx: scaleByFontFactor(180)); @override String getValue(_DialogFlag dataObject) => dataObject.name ?? ''; @@ -262,10 +254,7 @@ class _NameColumn extends ColumnData<_DialogFlag> { class _DescriptionColumn extends ColumnData<_DialogFlag> { _DescriptionColumn() - : super.wide( - 'Description', - minWidthPx: scaleByFontFactor(100), - ); + : super.wide('Description', minWidthPx: scaleByFontFactor(100)); @override String getValue(_DialogFlag dataObject) => dataObject.description ?? ''; @@ -279,12 +268,12 @@ class _DescriptionColumn extends ColumnData<_DialogFlag> { class _ValueColumn extends ColumnData<_DialogFlag> { _ValueColumn() - : super( - 'Value', - fixedWidthPx: scaleByFontFactor(100), - headerAlignment: TextAlign.right, - alignment: ColumnAlignment.right, - ); + : super( + 'Value', + fixedWidthPx: scaleByFontFactor(100), + headerAlignment: TextAlign.right, + alignment: ColumnAlignment.right, + ); @override String getValue(_DialogFlag dataObject) => dataObject.value ?? ''; @@ -295,9 +284,10 @@ class _ValueColumn extends ColumnData<_DialogFlag> { class _DialogFlag { _DialogFlag(this.flag) - : filterText = '${flag.name?.toLowerCase()}\n' - '${flag.comment?.toLowerCase()}\n' - '${flag.valueAsString?.toLowerCase()}'; + : filterText = + '${flag.name?.toLowerCase()}\n' + '${flag.comment?.toLowerCase()}\n' + '${flag.valueAsString?.toLowerCase()}'; final Flag flag; final String filterText; diff --git a/packages/devtools_app/lib/src/shared/utils.dart b/packages/devtools_app/lib/src/shared/utils.dart index 3adb7f1ddb4..046e980b786 100644 --- a/packages/devtools_app/lib/src/shared/utils.dart +++ b/packages/devtools_app/lib/src/shared/utils.dart @@ -31,12 +31,10 @@ 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; - }(), - ); + assert(() { + _log.info(message); + return true; + }()); } /// Whether DevTools is using a dark theme. @@ -101,11 +99,7 @@ List generateDeviceDescription( vmServiceConnection = ConnectionDescription( title: 'VM Service Connection', description: description, - actions: [ - CopyToClipboardControl( - dataProvider: () => description, - ), - ], + actions: [CopyToClipboardControl(dataProvider: () => description)], ); } @@ -124,7 +118,8 @@ List generateDeviceDescription( ), ConnectionDescription( title: 'Framework / Engine', - description: '${flutterVersion.frameworkRevision} / ' + description: + '${flutterVersion.frameworkRevision} / ' '${flutterVersion.engineRevision}', ), }, @@ -148,8 +143,9 @@ List issueLinkDetails() { connectedApp, includeVmServiceConnection: false, ); - final deviceDescription = descriptionEntries - .map((entry) => '${entry.title}: ${entry.description}'); + final deviceDescription = descriptionEntries.map( + (entry) => '${entry.title}: ${entry.description}', + ); issueDescriptionItems.addAll([ '**Connected Device**:', ...deviceDescription, @@ -252,10 +248,8 @@ class DebounceTimer { /// [callback] is triggered once immediately, and then every [duration] the /// timer checks to see if the previous [callback] call has finished running. /// If it has finished, then then next call to [callback] will begin. - DebounceTimer.periodic( - Duration duration, - Future Function() callback, - ) : _callback = callback { + DebounceTimer.periodic(Duration duration, Future Function() callback) + : _callback = callback { // Start running the first call to the callback. _runCallback(); @@ -347,9 +341,11 @@ class InterruptableChunkWorker { final chunkUpperIndexLimit = min(length, chunkStartingIndex + _chunkSize); - for (int indexIterator = chunkStartingIndex; - indexIterator < chunkUpperIndexLimit; - indexIterator++) { + for ( + int indexIterator = chunkStartingIndex; + indexIterator < chunkUpperIndexLimit; + indexIterator++ + ) { // If our localWorkId is no longer active, then do not continue working if (localWorkId != _workId) return completer.complete(false); callback(indexIterator); diff --git a/packages/devtools_app/lib/src/shared/vm_utils.dart b/packages/devtools_app/lib/src/shared/vm_utils.dart index 3e3f0094843..0096df959ee 100644 --- a/packages/devtools_app/lib/src/shared/vm_utils.dart +++ b/packages/devtools_app/lib/src/shared/vm_utils.dart @@ -41,13 +41,10 @@ Future findInstance( isolateId, classId, preferences.memory.refLimit.value, - )) - .instances - ?.firstWhereOrNull( - (instance) => - (instance is InstanceRef) && - (instance.identityHashCode == hashCode), - ); + )).instances?.firstWhereOrNull( + (instance) => + (instance is InstanceRef) && (instance.identityHashCode == hashCode), + ); if (result is InstanceRef) return result; return null; diff --git a/packages/devtools_app/lib/src/standalone_ui/standalone_screen.dart b/packages/devtools_app/lib/src/standalone_ui/standalone_screen.dart index 62411ab0a30..576d890488b 100644 --- a/packages/devtools_app/lib/src/standalone_ui/standalone_screen.dart +++ b/packages/devtools_app/lib/src/standalone_ui/standalone_screen.dart @@ -21,23 +21,24 @@ enum StandaloneScreenType { Widget get screen { return switch (this) { StandaloneScreenType.vsCodeFlutterPanel => const Padding( - padding: EdgeInsets.all(8.0), - child: CenteredMessage( - message: 'The Flutter sidebar for this SDK requires v3.96 or ' - 'newer of the Dart VS Code extension', - ), + padding: EdgeInsets.all(8.0), + child: CenteredMessage( + message: + 'The Flutter sidebar for this SDK requires v3.96 or ' + 'newer of the Dart VS Code extension', ), + ), StandaloneScreenType.editorSidebar => ValueListenableBuilder( - // TODO(dantup): Add a timeout here so if dtdManager.connection - // doesn't complete after some period we can give some kind of - // useful message. - valueListenable: dtdManager.connection, - builder: (context, data, _) { - return data == null - ? const CenteredCircularProgressIndicator() - : EditorSidebarPanel(data); - }, - ), + // TODO(dantup): Add a timeout here so if dtdManager.connection + // doesn't complete after some period we can give some kind of + // useful message. + valueListenable: dtdManager.connection, + builder: (context, data, _) { + return data == null + ? const CenteredCircularProgressIndicator() + : EditorSidebarPanel(data); + }, + ), }; } } diff --git a/packages/devtools_app/lib/src/standalone_ui/vs_code/debug_sessions.dart b/packages/devtools_app/lib/src/standalone_ui/vs_code/debug_sessions.dart index 8ee9ef4c914..f63616dfcde 100644 --- a/packages/devtools_app/lib/src/standalone_ui/vs_code/debug_sessions.dart +++ b/packages/devtools_app/lib/src/standalone_ui/vs_code/debug_sessions.dart @@ -34,10 +34,7 @@ class DebugSessions extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - 'Debug Sessions', - style: Theme.of(context).textTheme.titleMedium, - ), + Text('Debug Sessions', style: Theme.of(context).textTheme.titleMedium), if (sessions.isEmpty) const Padding( padding: EdgeInsets.only(left: borderPadding), @@ -45,11 +42,10 @@ class DebugSessions extends StatelessWidget { ) else Table( - columnWidths: const { - 0: FlexColumnWidth(), - }, - defaultColumnWidth: - FixedColumnWidth(actionsIconSize + denseSpacing), + columnWidths: const {0: FlexColumnWidth()}, + defaultColumnWidth: FixedColumnWidth( + actionsIconSize + denseSpacing, + ), defaultVerticalAlignment: TableCellVerticalAlignment.middle, children: [ for (final session in sessions.values) @@ -65,39 +61,33 @@ class DebugSessions extends StatelessWidget { final isDebug = mode == 'debug'; final isFlutter = session.debuggerType?.contains('Flutter') ?? false; - final label = session.flutterMode != null - ? '${session.name} (${session.flutterMode})' - : session.name; + final label = + session.flutterMode != null + ? '${session.name} (${session.flutterMode})' + : session.name; return TableRow( children: [ - Text( - label, - style: Theme.of(context).regularTextStyle, - ), + Text(label, style: Theme.of(context).regularTextStyle), IconButton( - onPressed: editor.supportsHotReload && (isDebug || !isFlutter) - ? () { - ga.select( - editor.gaId, - gac.hotReload, - ); - unawaited(editor.hotReload(session.id)); - } - : null, + onPressed: + editor.supportsHotReload && (isDebug || !isFlutter) + ? () { + ga.select(editor.gaId, gac.hotReload); + unawaited(editor.hotReload(session.id)); + } + : null, tooltip: 'Hot Reload', icon: Icon(hotReloadIcon, size: actionsIconSize), ), IconButton( - onPressed: editor.supportsHotRestart && (isDebug || !isFlutter) - ? () { - ga.select( - editor.gaId, - gac.hotRestart, - ); - unawaited(editor.hotRestart(session.id)); - } - : null, + onPressed: + editor.supportsHotRestart && (isDebug || !isFlutter) + ? () { + ga.select(editor.gaId, gac.hotRestart); + unawaited(editor.hotRestart(session.id)); + } + : null, tooltip: 'Hot Restart', icon: Icon(hotRestartIcon, size: actionsIconSize), ), diff --git a/packages/devtools_app/lib/src/standalone_ui/vs_code/devices.dart b/packages/devtools_app/lib/src/standalone_ui/vs_code/devices.dart index 574a7078150..3890fe5e7df 100644 --- a/packages/devtools_app/lib/src/standalone_ui/vs_code/devices.dart +++ b/packages/devtools_app/lib/src/standalone_ui/vs_code/devices.dart @@ -18,15 +18,16 @@ class Devices extends StatelessWidget { required Map devices, required this.selectedDeviceId, super.key, - }) : supportedDevices = { - for (final MapEntry(key: id, value: device) in devices.entries) - if (device.supported) id: device, - }, - unsupportedDevicePlatformTypes = devices.values - .where((device) => !device.supported) - .map((device) => device.platformType) - .nonNulls - .toSet(); + }) : supportedDevices = { + for (final MapEntry(key: id, value: device) in devices.entries) + if (device.supported) id: device, + }, + unsupportedDevicePlatformTypes = + devices.values + .where((device) => !device.supported) + .map((device) => device.platformType) + .nonNulls + .toSet(); final EditorClient editor; final Map supportedDevices; @@ -39,10 +40,7 @@ class Devices extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - 'Devices', - style: theme.textTheme.titleMedium, - ), + Text('Devices', style: theme.textTheme.titleMedium), if (supportedDevices.isEmpty) const Text('Connect a device or enable web/desktop platforms.') else @@ -56,10 +54,7 @@ class Devices extends StatelessWidget { isSelected: device.id == selectedDeviceId, ), for (final platformType in unsupportedDevicePlatformTypes) - _createPlatformTypeEnablerRow( - theme, - platformType, - ), + _createPlatformTypeEnablerRow(theme, platformType), ], ), ], @@ -72,9 +67,10 @@ class Devices extends StatelessWidget { required bool isSelected, }) { final backgroundColor = isSelected ? theme.colorScheme.secondary : null; - final foregroundColor = isSelected - ? theme.colorScheme.onSecondary - : theme.colorScheme.onSurface; + final foregroundColor = + isSelected + ? theme.colorScheme.onSecondary + : theme.colorScheme.onSurface; return TableRow( decoration: BoxDecoration(color: backgroundColor), diff --git a/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/devtools_view.dart b/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/devtools_view.dart index 458c7b6ab6a..1b3bd33c54a 100644 --- a/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/devtools_view.dart +++ b/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/devtools_view.dart @@ -79,10 +79,7 @@ class SidebarDevToolsScreens extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - 'DevTools', - style: theme.textTheme.titleMedium, - ), + Text('DevTools', style: theme.textTheme.titleMedium), if (editor.supportsOpenDevToolsForceExternal) ToolbarAction( icon: Icons.open_in_browser_outlined, @@ -92,21 +89,20 @@ class SidebarDevToolsScreens extends StatelessWidget { editor.gaId, gac.EditorSidebar.openDevToolsExternally.name, ); - unawaited( - editor.openDevToolsPage(null, forceExternal: true), - ); + unawaited(editor.openDevToolsPage(null, forceExternal: true)); }, ), ], ), Table( defaultVerticalAlignment: TableCellVerticalAlignment.middle, - columnWidths: singleColumn - ? null - : const { - 0: FlexColumnWidth(), - 1: FlexColumnWidth(), - }, + columnWidths: + singleColumn + ? null + : const { + 0: FlexColumnWidth(), + 1: FlexColumnWidth(), + }, children: generateRows(singleColumn), ), ], @@ -125,12 +121,13 @@ class SidebarDevToolsScreens extends StatelessWidget { editor: editor, singleColumn: singleColumn, hasDebugSessions: debugSessions.isNotEmpty, - onPressed: (data) => openDevToolsScreen( - screenId: data.screenId, - requiresDebugSession: data.requiresDebugSession, - prefersDebugSession: data.prefersDebugSession, - editor: editor, - ), + onPressed: + (data) => openDevToolsScreen( + screenId: data.screenId, + requiresDebugSession: data.requiresDebugSession, + prefersDebugSession: data.prefersDebugSession, + editor: editor, + ), ), ) .toList(); @@ -147,12 +144,13 @@ class SidebarDevToolsScreens extends StatelessWidget { editor: editor, singleColumn: singleColumn, hasDebugSessions: debugSessions.isNotEmpty, - onPressed: (data) => openDevToolsScreen( - screenId: data.screenId, - requiresDebugSession: data.requiresDebugSession, - prefersDebugSession: data.prefersDebugSession, - editor: editor, - ), + onPressed: + (data) => openDevToolsScreen( + screenId: data.screenId, + requiresDebugSession: data.requiresDebugSession, + prefersDebugSession: data.prefersDebugSession, + editor: editor, + ), ), ); } @@ -179,9 +177,10 @@ class SidebarDevToolsScreens extends StatelessWidget { ScreenMetaData.debugger || ScreenMetaData.vmTools || // This screen will be removed from the first party DevTools screens soon. - // If the user depends on package:provider, the provider extension should - // show up in the DevTools extensions list instead. - ScreenMetaData.provider || + // If the user depends on package:provider, the provider extension should + // show up in the DevTools extensions list instead. + ScreenMetaData + .provider || ScreenMetaData.simple => false, _ => true, diff --git a/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/shared.dart b/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/shared.dart index c9a8fea4ecc..7a176b954e8 100644 --- a/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/shared.dart +++ b/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/shared.dart @@ -12,14 +12,15 @@ import '../../../shared/analytics/analytics.dart' as ga; import '../../../shared/analytics/constants.dart' as gac; import '../../../shared/ui/icons.dart'; -typedef DevToolsButtonData = ({ - String label, - IconData? icon, - String? iconAsset, - String screenId, - bool requiresDebugSession, - bool prefersDebugSession, -}); +typedef DevToolsButtonData = + ({ + String label, + IconData? icon, + String? iconAsset, + String screenId, + bool requiresDebugSession, + bool prefersDebugSession, + }); TableRow createDevToolsScreenRow({ required DevToolsButtonData dataLeft, @@ -33,14 +34,15 @@ TableRow createDevToolsScreenRow({ !singleColumn || dataRight == null, 'dataRight must be null is singleColumn is true', ); - final cellRight = dataRight != null - ? _DevToolsScreenButton( - data: dataRight, - editor: editor, - hasDebugSessions: hasDebugSessions, - onPressed: onPressed, - ) - : const SizedBox(); + final cellRight = + dataRight != null + ? _DevToolsScreenButton( + data: dataRight, + editor: editor, + hasDebugSessions: hasDebugSessions, + onPressed: onPressed, + ) + : const SizedBox(); return TableRow( children: [ _DevToolsScreenButton( @@ -108,10 +110,7 @@ void openDevToolsScreen({ required bool prefersDebugSession, required EditorClient editor, }) { - ga.select( - editor.gaId, - gac.EditorSidebar.openDevToolsScreen(screenId), - ); + ga.select(editor.gaId, gac.EditorSidebar.openDevToolsScreen(screenId)); unawaited( editor.openDevToolsPage( null, diff --git a/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/sidebar_extensions_controller.dart b/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/sidebar_extensions_controller.dart index b9b6795025c..c4a90718da5 100644 --- a/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/sidebar_extensions_controller.dart +++ b/packages/devtools_app/lib/src/standalone_ui/vs_code/devtools/sidebar_extensions_controller.dart @@ -76,8 +76,9 @@ class SidebarDevToolsExtensionsController extends DisposableController /// [_deduplicateAndUpdate]. ValueListenable> get uniqueExtensions => _uniqueExtensions; - final _uniqueExtensions = - ValueNotifier>([]); + final _uniqueExtensions = ValueNotifier>( + [], + ); /// The set of extension hashcodes that have been ignored due to being a /// duplicate of some kind. @@ -104,8 +105,9 @@ class SidebarDevToolsExtensionsController extends DisposableController await _initialized.future; // Cleanup state for debug sessions that are no longer available. - final removed = - _debugSessions.keys.toSet().difference(newDebugSessions.keys.toSet()); + final removed = _debugSessions.keys.toSet().difference( + newDebugSessions.keys.toSet(), + ); for (final sessionId in removed) { final session = _debugSessions[sessionId]!; final rootFileUri = session.projectRootFileUri; @@ -123,8 +125,7 @@ class SidebarDevToolsExtensionsController extends DisposableController (await dtdManager.projectRoots( depth: staticExtensionsSearchDepth, forceRefresh: true, - )) - ?.uris ?? + ))?.uris ?? [], ); } @@ -159,15 +160,16 @@ class SidebarDevToolsExtensionsController extends DisposableController // watch event from the IDE or analysis server to signal when any // package_config.json file in the workspace changes. Future _detectExtensions(Uri? projectRootUri) async { - final extensionService = projectRootUri == null - ? - // A null [projectRootUri] indicates that this is an extensions lookup - // for the entire workspace, not a debug session with a fixed root URI. - ExtensionService(ignoreServiceConnection: true) - : ExtensionService( - fixedAppRoot: projectRootUri, - ignoreServiceConnection: true, - ); + final extensionService = + projectRootUri == null + ? + // A null [projectRootUri] indicates that this is an extensions lookup + // for the entire workspace, not a debug session with a fixed root URI. + ExtensionService(ignoreServiceConnection: true) + : ExtensionService( + fixedAppRoot: projectRootUri, + ignoreServiceConnection: true, + ); assert( !_extensionServiceByRootUri.containsKey(projectRootUri), 'The initialization for the ExtensionService for root uri ' @@ -205,12 +207,13 @@ class SidebarDevToolsExtensionsController extends DisposableController extensionType: 'all', ); - final deduped = allExtensions - .where( - (ext) => - !_ignoredExtensionsByHashCode.contains(identityHashCode(ext)), - ) - .toList(); + final deduped = + allExtensions + .where( + (ext) => + !_ignoredExtensionsByHashCode.contains(identityHashCode(ext)), + ) + .toList(); _uniqueExtensions.value = deduped..sort(); } diff --git a/packages/devtools_app/lib/src/standalone_ui/vs_code/flutter_panel.dart b/packages/devtools_app/lib/src/standalone_ui/vs_code/flutter_panel.dart index 5572aa99da5..8994b3caac1 100644 --- a/packages/devtools_app/lib/src/standalone_ui/vs_code/flutter_panel.dart +++ b/packages/devtools_app/lib/src/standalone_ui/vs_code/flutter_panel.dart @@ -51,12 +51,15 @@ class _EditorSidebarPanelState extends State { Expanded( child: FutureBuilder( future: _editor, - builder: (context, snapshot) => - switch ((snapshot.connectionState, snapshot.data)) { - (ConnectionState.done, final editor?) => - _EditorConnectedPanel(editor), - _ => const CenteredCircularProgressIndicator(), - }, + builder: + (context, snapshot) => switch (( + snapshot.connectionState, + snapshot.data, + )) { + (ConnectionState.done, final editor?) => + _EditorConnectedPanel(editor), + _ => const CenteredCircularProgressIndicator(), + }, ), ), ], diff --git a/packages/devtools_app/pubspec.yaml b/packages/devtools_app/pubspec.yaml index 934d07d8992..f16c4598b24 100644 --- a/packages/devtools_app/pubspec.yaml +++ b/packages/devtools_app/pubspec.yaml @@ -4,13 +4,13 @@ publish_to: none # Note: this version should only be updated by running the 'dt update-version' # command that updates the version here and in 'devtools.dart'. -version: 2.41.0-dev.2 +version: 2.41.0-dev.3 repository: https://github.com/flutter/devtools/tree/master/packages/devtools_app environment: - sdk: ">=3.7.0-41.0.dev <4.0.0" - flutter: ">=3.27.0-1.0.pre.123" + sdk: ">=3.7.0-160.0.dev <4.0.0" + flutter: ">=3.27.0-1.0.pre.563" dependencies: ansi_up: ^1.0.0 diff --git a/packages/devtools_app/test/app_size/app_size_screen_test.dart b/packages/devtools_app/test/app_size/app_size_screen_test.dart index fc6574bfa8b..9b9be65122c 100644 --- a/packages/devtools_app/test/app_size/app_size_screen_test.dart +++ b/packages/devtools_app/test/app_size/app_size_screen_test.dart @@ -79,10 +79,7 @@ void main() { required AppSizeTestController controller, }) async { await tester.pumpWidget( - wrapWithControllers( - const AppSizeBody(), - appSize: controller, - ), + wrapWithControllers(const AppSizeBody(), appSize: controller), ); deferredLoadingSupportEnabled = true; await tester.pumpAndSettle(const Duration(seconds: 1)); @@ -122,94 +119,84 @@ void main() { expect(find.text('App Size'), findsOneWidget); }); - testWidgetsWithWindowSize( - 'builds initial content', - windowSize, - (WidgetTester tester) async { - await pumpAppSizeScreen( - tester, - controller: appSizeController, - ); + testWidgetsWithWindowSize('builds initial content', windowSize, ( + WidgetTester tester, + ) async { + await pumpAppSizeScreen(tester, controller: appSizeController); - expect(find.byType(AppSizeBody), findsOneWidget); - expect(find.byType(TabBar), findsOneWidget); + expect(find.byType(AppSizeBody), findsOneWidget); + expect(find.byType(TabBar), findsOneWidget); - expect(find.byKey(AppSizeScreen.analysisTabKey), findsOneWidget); - expect(find.byKey(AppSizeScreen.diffTabKey), findsOneWidget); + expect(find.byKey(AppSizeScreen.analysisTabKey), findsOneWidget); + expect(find.byKey(AppSizeScreen.diffTabKey), findsOneWidget); - await loadDataAndPump(tester); + await loadDataAndPump(tester); - // Verify the state of the splitter. - final splitFinder = find.byType(SplitPane); - expect(splitFinder, findsOneWidget); - final SplitPane splitter = tester.widget(splitFinder); - expect(splitter.initialFractions[0], equals(0.67)); - expect(splitter.initialFractions[1], equals(0.33)); - }, - ); + // Verify the state of the splitter. + final splitFinder = find.byType(SplitPane); + expect(splitFinder, findsOneWidget); + final SplitPane splitter = tester.widget(splitFinder); + expect(splitter.initialFractions[0], equals(0.67)); + expect(splitter.initialFractions[1], equals(0.33)); + }); - testWidgetsWithWindowSize( - 'builds deferred content', - windowSize, - (WidgetTester tester) async { - await pumpAppSizeScreen( - tester, - controller: appSizeController, - ); - await loadDataAndPump(tester, data: deferredAppFile); + testWidgetsWithWindowSize('builds deferred content', windowSize, ( + WidgetTester tester, + ) async { + await pumpAppSizeScreen(tester, controller: appSizeController); + await loadDataAndPump(tester, data: deferredAppFile); - // Verify the dropdown for selecting app units exists. - final appUnitDropdownFinder = _findDropdownButton(); - expect(appUnitDropdownFinder, findsOneWidget); + // Verify the dropdown for selecting app units exists. + final appUnitDropdownFinder = _findDropdownButton(); + expect(appUnitDropdownFinder, findsOneWidget); - // Verify the entire app is shown. - final breadcrumbs = _fetchBreadcrumbs(tester); - expect(breadcrumbs.length, 1); - expect(breadcrumbs.first.text, equals('Entire App [39.8 MB]')); - expect(find.richText('Main [39.5 MB]'), findsOneWidget); + // Verify the entire app is shown. + final breadcrumbs = _fetchBreadcrumbs(tester); + expect(breadcrumbs.length, 1); + expect(breadcrumbs.first.text, equals('Entire App [39.8 MB]')); + expect(find.richText('Main [39.5 MB]'), findsOneWidget); - // Open the dropdown. - await tester.tap(appUnitDropdownFinder); - await tester.pumpAndSettle(); + // Open the dropdown. + await tester.tap(appUnitDropdownFinder); + await tester.pumpAndSettle(); - // Verify the menu items in the dropdown are expected. - final entireAppMenuItemFinder = - _findMenuItemWithText('Entire App'); - expect(entireAppMenuItemFinder, findsOneWidget); - final mainMenuItemFinder = _findMenuItemWithText('Main'); - expect(mainMenuItemFinder, findsOneWidget); - final deferredMenuItemFinder = - _findMenuItemWithText('Deferred'); - expect(deferredMenuItemFinder, findsOneWidget); - - // Select the main unit. - await tester.tap(find.text('Main').hitTestable()); - await tester.pumpAndSettle(); + // Verify the menu items in the dropdown are expected. + final entireAppMenuItemFinder = _findMenuItemWithText( + 'Entire App', + ); + expect(entireAppMenuItemFinder, findsOneWidget); + final mainMenuItemFinder = _findMenuItemWithText('Main'); + expect(mainMenuItemFinder, findsOneWidget); + final deferredMenuItemFinder = _findMenuItemWithText('Deferred'); + expect(deferredMenuItemFinder, findsOneWidget); + + // Select the main unit. + await tester.tap(find.text('Main').hitTestable()); + await tester.pumpAndSettle(); - // Verify the main unit is shown. - final mainBreadcrumbs = _fetchBreadcrumbs(tester); - expect(mainBreadcrumbs.length, 1); - expect(mainBreadcrumbs.first.text, equals('Main [39.5 MB]')); - expect(find.richText('appsize_app.app [39.5 MB]'), findsOneWidget); + // Verify the main unit is shown. + final mainBreadcrumbs = _fetchBreadcrumbs(tester); + expect(mainBreadcrumbs.length, 1); + expect(mainBreadcrumbs.first.text, equals('Main [39.5 MB]')); + expect(find.richText('appsize_app.app [39.5 MB]'), findsOneWidget); - // Open the dropdown. - await tester.tap(appUnitDropdownFinder); - await tester.pumpAndSettle(); + // Open the dropdown. + await tester.tap(appUnitDropdownFinder); + await tester.pumpAndSettle(); - // Select the deferred units. - await tester.tap(find.text('Deferred').hitTestable()); - await tester.pumpAndSettle(); + // Select the deferred units. + await tester.tap(find.text('Deferred').hitTestable()); + await tester.pumpAndSettle(); - // Verify the deferred units are shown. - final deferredBreadcrumbs = _fetchBreadcrumbs(tester); - expect(deferredBreadcrumbs.length, 1); - expect(deferredBreadcrumbs.first.text, equals('Deferred [344.3 KB]')); - expect( - find.richText('flutter_assets [344.3 KB] (Deferred)'), - findsOneWidget, - ); - }, - ); + // Verify the deferred units are shown. + final deferredBreadcrumbs = _fetchBreadcrumbs(tester); + expect(deferredBreadcrumbs.length, 1); + expect(deferredBreadcrumbs.first.text, equals('Deferred [344.3 KB]')); + expect( + find.richText('flutter_assets [344.3 KB] (Deferred)'), + findsOneWidget, + ); + }); }); group('SnapshotView', () { @@ -218,78 +205,65 @@ void main() { appSizeController = AppSizeTestController(); }); - testWidgetsWithWindowSize( - 'imports file and loads data', - windowSize, - (WidgetTester tester) async { - await pumpAppSizeScreen( - tester, - controller: appSizeController, - ); + testWidgetsWithWindowSize('imports file and loads data', windowSize, ( + WidgetTester tester, + ) async { + await pumpAppSizeScreen(tester, controller: appSizeController); - expect(find.byKey(AppSizeScreen.diffTypeDropdownKey), findsNothing); - expect(find.byType(ClearButton), findsOneWidget); + expect(find.byKey(AppSizeScreen.diffTypeDropdownKey), findsNothing); + expect(find.byType(ClearButton), findsOneWidget); - expect(find.byType(FileImportContainer), findsOneWidget); - expect(find.text(AnalysisView.importInstructions), findsOneWidget); - expect(find.text('No File Selected'), findsOneWidget); + expect(find.byType(FileImportContainer), findsOneWidget); + expect(find.text(AnalysisView.importInstructions), findsOneWidget); + expect(find.text('No File Selected'), findsOneWidget); - appSizeController.loadTreeFromJsonFile( - jsonFile: newV8JsonFile, - onError: (error) => {}, - delayed: true, - ); - await tester.pump(const Duration(milliseconds: 500)); - expect(find.text(AppSizeScreen.loadingMessage), findsOneWidget); - await tester.pumpAndSettle(); + appSizeController.loadTreeFromJsonFile( + jsonFile: newV8JsonFile, + onError: (error) => {}, + delayed: true, + ); + await tester.pump(const Duration(milliseconds: 500)); + expect(find.text(AppSizeScreen.loadingMessage), findsOneWidget); + await tester.pumpAndSettle(); - expect(find.byType(FileImportContainer), findsNothing); - expect(find.text(AnalysisView.importInstructions), findsNothing); - expect(find.text('No File Selected'), findsNothing); - expect(find.byType(AnalysisView), findsOneWidget); - expect( - find.text( - 'Dart AOT snapshot: lib/src/app_size/stub_data/new_v8.dart - 7/28/2020 1:29 PM', - ), - findsOneWidget, - ); - expect( - find.byKey(AppSizeScreen.analysisViewTreemapKey), - findsOneWidget, - ); + expect(find.byType(FileImportContainer), findsNothing); + expect(find.text(AnalysisView.importInstructions), findsNothing); + expect(find.text('No File Selected'), findsNothing); + expect(find.byType(AnalysisView), findsOneWidget); + expect( + find.text( + 'Dart AOT snapshot: lib/src/app_size/stub_data/new_v8.dart - 7/28/2020 1:29 PM', + ), + findsOneWidget, + ); + expect(find.byKey(AppSizeScreen.analysisViewTreemapKey), findsOneWidget); - final breadcrumbs = _fetchBreadcrumbs(tester); - expect(breadcrumbs.length, 1); - expect(breadcrumbs.first.text, equals('Root [6.0 MB]')); - expect(find.byType(BreadcrumbNavigator), findsOneWidget); + final breadcrumbs = _fetchBreadcrumbs(tester); + expect(breadcrumbs.length, 1); + expect(breadcrumbs.first.text, equals('Root [6.0 MB]')); + expect(find.byType(BreadcrumbNavigator), findsOneWidget); - expect(find.richText('package:flutter'), findsOneWidget); - expect(find.richText('dart:core'), findsOneWidget); + expect(find.richText('package:flutter'), findsOneWidget); + expect(find.richText('dart:core'), findsOneWidget); - expect(find.byType(AppSizeAnalysisTable), findsOneWidget); - expect(find.byType(AppSizeDiffTable), findsNothing); - }, - ); + expect(find.byType(AppSizeAnalysisTable), findsOneWidget); + expect(find.byType(AppSizeDiffTable), findsNothing); + }); - testWidgetsWithWindowSize( - 'clears data', - windowSize, - (WidgetTester tester) async { - await pumpAppSizeScreen( - tester, - controller: appSizeController, - ); + testWidgetsWithWindowSize('clears data', windowSize, ( + WidgetTester tester, + ) async { + await pumpAppSizeScreen(tester, controller: appSizeController); - await loadDataAndPump(tester); + await loadDataAndPump(tester); - await tester.tap(find.byType(ClearButton)); - await tester.pumpAndSettle(); + await tester.tap(find.byType(ClearButton)); + await tester.pumpAndSettle(); - expect(find.byType(FileImportContainer), findsOneWidget); - expect(find.text(AnalysisView.importInstructions), findsOneWidget); - expect(find.text('No File Selected'), findsOneWidget); - }, - ); + expect(find.byType(FileImportContainer), findsOneWidget); + expect(find.text(AnalysisView.importInstructions), findsOneWidget); + expect(find.text('No File Selected'), findsOneWidget); + }); }); group('DiffView', () { @@ -299,10 +273,7 @@ void main() { }); Future loadDiffTabAndSettle(WidgetTester tester) async { - await pumpAppSizeScreen( - tester, - controller: appSizeController, - ); + await pumpAppSizeScreen(tester, controller: appSizeController); await tester.tap(find.byKey(AppSizeScreen.diffTabKey)); await tester.pumpAndSettle(); } @@ -320,72 +291,62 @@ void main() { await tester.pumpAndSettle(); } - testWidgetsWithWindowSize( - 'builds initial content', - windowSize, - (WidgetTester tester) async { - await loadDiffTabAndSettle(tester); + testWidgetsWithWindowSize('builds initial content', windowSize, ( + WidgetTester tester, + ) async { + await loadDiffTabAndSettle(tester); - expect(find.byKey(AppSizeScreen.diffTypeDropdownKey), findsOneWidget); - expect(find.byKey(AppSizeScreen.appUnitDropdownKey), findsNothing); - expect(find.byType(ClearButton), findsOneWidget); + expect(find.byKey(AppSizeScreen.diffTypeDropdownKey), findsOneWidget); + expect(find.byKey(AppSizeScreen.appUnitDropdownKey), findsNothing); + expect(find.byType(ClearButton), findsOneWidget); - expect(find.byType(DualFileImportContainer), findsOneWidget); - expect(find.byType(FileImportContainer), findsNWidgets(2)); - expect(find.text(DiffView.importOldInstructions), findsOneWidget); - expect(find.text(DiffView.importNewInstructions), findsOneWidget); - expect(find.text('No File Selected'), findsNWidgets(2)); - }, - ); + expect(find.byType(DualFileImportContainer), findsOneWidget); + expect(find.byType(FileImportContainer), findsNWidgets(2)); + expect(find.text(DiffView.importOldInstructions), findsOneWidget); + expect(find.text(DiffView.importNewInstructions), findsOneWidget); + expect(find.text('No File Selected'), findsNWidgets(2)); + }); - testWidgetsWithWindowSize( - 'imports files and loads data', - windowSize, - (WidgetTester tester) async { - await loadDiffTabAndSettle(tester); + testWidgetsWithWindowSize('imports files and loads data', windowSize, ( + WidgetTester tester, + ) async { + await loadDiffTabAndSettle(tester); - appSizeController.loadDiffTreeFromJsonFiles( - oldFile: oldV8JsonFile, - newFile: newV8JsonFile, - onError: (error) => {}, - delayed: true, - ); - await tester.pump(const Duration(milliseconds: 500)); - expect(find.text(AppSizeScreen.loadingMessage), findsOneWidget); - await tester.pumpAndSettle(); + appSizeController.loadDiffTreeFromJsonFiles( + oldFile: oldV8JsonFile, + newFile: newV8JsonFile, + onError: (error) => {}, + delayed: true, + ); + await tester.pump(const Duration(milliseconds: 500)); + expect(find.text(AppSizeScreen.loadingMessage), findsOneWidget); + await tester.pumpAndSettle(); - expect(find.byType(FileImportContainer), findsNothing); - expect(find.text(DiffView.importOldInstructions), findsNothing); - expect(find.text(DiffView.importNewInstructions), findsNothing); - expect(find.text('No File Selected'), findsNothing); + expect(find.byType(FileImportContainer), findsNothing); + expect(find.text(DiffView.importOldInstructions), findsNothing); + expect(find.text(DiffView.importNewInstructions), findsNothing); + expect(find.text('No File Selected'), findsNothing); - expect(find.byType(DiffView), findsOneWidget); + expect(find.byType(DiffView), findsOneWidget); - expect( - find.text( - 'Diffing Dart AOT snapshots: lib/src/app_size/stub_data/old_v8.dart - 7/28/2020 1:29 PM (OLD) vs (NEW) lib/src/app_size/stub_data/new_v8.dart - 7/28/2020 1:29 PM', - ), - findsOneWidget, - ); - expect( - find.byKey(AppSizeScreen.diffViewTreemapKey), - findsOneWidget, - ); - expect( - find.byKey(AppSizeScreen.analysisViewTreemapKey), - findsNothing, - ); + expect( + find.text( + 'Diffing Dart AOT snapshots: lib/src/app_size/stub_data/old_v8.dart - 7/28/2020 1:29 PM (OLD) vs (NEW) lib/src/app_size/stub_data/new_v8.dart - 7/28/2020 1:29 PM', + ), + findsOneWidget, + ); + expect(find.byKey(AppSizeScreen.diffViewTreemapKey), findsOneWidget); + expect(find.byKey(AppSizeScreen.analysisViewTreemapKey), findsNothing); - final breadcrumbs = _fetchBreadcrumbs(tester); - expect(breadcrumbs.length, 1); - expect(breadcrumbs.first.text, equals('Root [+1.5 MB]')); - expect(find.richText('package:pointycastle'), findsOneWidget); - expect(find.richText('package:flutter'), findsOneWidget); + final breadcrumbs = _fetchBreadcrumbs(tester); + expect(breadcrumbs.length, 1); + expect(breadcrumbs.first.text, equals('Root [+1.5 MB]')); + expect(find.richText('package:pointycastle'), findsOneWidget); + expect(find.richText('package:flutter'), findsOneWidget); - expect(find.byType(AppSizeAnalysisTable), findsNothing); - expect(find.byType(AppSizeDiffTable), findsOneWidget); - }, - ); + expect(find.byType(AppSizeAnalysisTable), findsNothing); + expect(find.byType(AppSizeDiffTable), findsOneWidget); + }); testWidgetsWithWindowSize( 'loads data and shows different tree types', @@ -420,24 +381,22 @@ void main() { }, ); - testWidgetsWithWindowSize( - 'clears data', - windowSize, - (WidgetTester tester) async { - await loadDiffTabAndSettle(tester); + testWidgetsWithWindowSize('clears data', windowSize, ( + WidgetTester tester, + ) async { + await loadDiffTabAndSettle(tester); - await loadDiffDataAndPump(tester, oldV8JsonFile, newV8JsonFile); + await loadDiffDataAndPump(tester, oldV8JsonFile, newV8JsonFile); - await tester.tap(find.byType(ClearButton)); - await tester.pumpAndSettle(); + await tester.tap(find.byType(ClearButton)); + await tester.pumpAndSettle(); - expect(find.byType(DualFileImportContainer), findsOneWidget); - expect(find.byType(FileImportContainer), findsNWidgets(2)); - expect(find.text(DiffView.importOldInstructions), findsOneWidget); - expect(find.text(DiffView.importNewInstructions), findsOneWidget); - expect(find.text('No File Selected'), findsNWidgets(2)); - }, - ); + expect(find.byType(DualFileImportContainer), findsOneWidget); + expect(find.byType(FileImportContainer), findsNWidgets(2)); + expect(find.text(DiffView.importOldInstructions), findsOneWidget); + expect(find.text(DiffView.importNewInstructions), findsOneWidget); + expect(find.text('No File Selected'), findsNWidgets(2)); + }); }); group('AppSizeController', () { @@ -545,164 +504,155 @@ void main() { }, ); - testWidgetsWithWindowSize( - 'builds deferred content for diff table', - windowSize, - (WidgetTester tester) async { - await pumpAppSizeScreen( - tester, - controller: appSizeController, - ); - await tester.tap(find.byKey(AppSizeScreen.diffTabKey)); - await tester.pumpAndSettle(); + testWidgetsWithWindowSize('builds deferred content for diff table', windowSize, ( + WidgetTester tester, + ) async { + await pumpAppSizeScreen(tester, controller: appSizeController); + await tester.tap(find.byKey(AppSizeScreen.diffTabKey)); + await tester.pumpAndSettle(); - await loadDiffTreeAndPump(tester, diffNonDeferredApp, diffDeferredApp); + await loadDiffTreeAndPump(tester, diffNonDeferredApp, diffDeferredApp); - // Verify the dropdown for selecting app units exists. - final appUnitDropdownFinder = _findDropdownButton(); - expect(appUnitDropdownFinder, findsOneWidget); + // Verify the dropdown for selecting app units exists. + final appUnitDropdownFinder = _findDropdownButton(); + expect(appUnitDropdownFinder, findsOneWidget); - // Open the app unit dropdown. - await tester.tap(appUnitDropdownFinder); - await tester.pumpAndSettle(); + // Open the app unit dropdown. + await tester.tap(appUnitDropdownFinder); + await tester.pumpAndSettle(); - // Verify the menu items in the dropdown are expected. - final entireAppMenuItemFinder = - _findMenuItemWithText('Entire App'); - expect(entireAppMenuItemFinder, findsOneWidget); - final mainMenuItemFinder = _findMenuItemWithText('Main'); - expect(mainMenuItemFinder, findsOneWidget); - final deferredMenuItemFinder = - _findMenuItemWithText('Deferred'); - expect(deferredMenuItemFinder, findsOneWidget); - - // Select the main unit. - await tester.tap(find.richText('Main').hitTestable()); - await tester.pumpAndSettle(); + // Verify the menu items in the dropdown are expected. + final entireAppMenuItemFinder = _findMenuItemWithText( + 'Entire App', + ); + expect(entireAppMenuItemFinder, findsOneWidget); + final mainMenuItemFinder = _findMenuItemWithText('Main'); + expect(mainMenuItemFinder, findsOneWidget); + final deferredMenuItemFinder = _findMenuItemWithText('Deferred'); + expect(deferredMenuItemFinder, findsOneWidget); + + // Select the main unit. + await tester.tap(find.richText('Main').hitTestable()); + await tester.pumpAndSettle(); - // Verify the main unit is shown for entire app. - final mainBreadcrumbs = _fetchBreadcrumbs(tester); - expect(mainBreadcrumbs.length, 1); - expect( - mainBreadcrumbs.first.text, - equals( - '/Main/appsize_app.app/Contents/Frameworks/App.framework/Resources/flutter_assets [-344.3 KB]', - ), - ); - expect( - find.richText('packages/cupertino_icons/assets [-276.8 KB]'), - findsOneWidget, - ); + // Verify the main unit is shown for entire app. + final mainBreadcrumbs = _fetchBreadcrumbs(tester); + expect(mainBreadcrumbs.length, 1); + expect( + mainBreadcrumbs.first.text, + equals( + '/Main/appsize_app.app/Contents/Frameworks/App.framework/Resources/flutter_assets [-344.3 KB]', + ), + ); + expect( + find.richText('packages/cupertino_icons/assets [-276.8 KB]'), + findsOneWidget, + ); - // Open the diffType dropdown. - await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); - await tester.pumpAndSettle(); + // Open the diffType dropdown. + await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); + await tester.pumpAndSettle(); - // Select increase only. - await tester.tap(find.text('Increase Only').hitTestable()); - await tester.pumpAndSettle(); + // Select increase only. + await tester.tap(find.text('Increase Only').hitTestable()); + await tester.pumpAndSettle(); - // Verify the main unit is shown for increase only. - final mainIncreaseBreadcrumbs = _fetchBreadcrumbs(tester); - expect(mainIncreaseBreadcrumbs.length, 1); - expect( - mainIncreaseBreadcrumbs.first.text, - equals( - '/Main/appsize_app.app/Contents/Frameworks/App.framework/Resources/flutter_assets [0 B]', - ), - ); + // Verify the main unit is shown for increase only. + final mainIncreaseBreadcrumbs = _fetchBreadcrumbs(tester); + expect(mainIncreaseBreadcrumbs.length, 1); + expect( + mainIncreaseBreadcrumbs.first.text, + equals( + '/Main/appsize_app.app/Contents/Frameworks/App.framework/Resources/flutter_assets [0 B]', + ), + ); - // Open the diffType dropdown. - await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); - await tester.pumpAndSettle(); + // Open the diffType dropdown. + await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); + await tester.pumpAndSettle(); - // Select decrease only. - await tester.tap(find.text('Decrease Only').hitTestable()); - await tester.pumpAndSettle(); + // Select decrease only. + await tester.tap(find.text('Decrease Only').hitTestable()); + await tester.pumpAndSettle(); - // Verify the main unit is shown for decrease only. - final mainDecreaseBreadcrumbs = _fetchBreadcrumbs(tester); - expect(mainDecreaseBreadcrumbs.length, 1); - expect( - mainDecreaseBreadcrumbs.first.text, - equals( - '/Main/appsize_app.app/Contents/Frameworks/App.framework/Resources/flutter_assets [-344.3 KB]', - ), - ); - expect( - find.richText('packages/cupertino_icons/assets [-276.8 KB]'), - findsOneWidget, - ); + // Verify the main unit is shown for decrease only. + final mainDecreaseBreadcrumbs = _fetchBreadcrumbs(tester); + expect(mainDecreaseBreadcrumbs.length, 1); + expect( + mainDecreaseBreadcrumbs.first.text, + equals( + '/Main/appsize_app.app/Contents/Frameworks/App.framework/Resources/flutter_assets [-344.3 KB]', + ), + ); + expect( + find.richText('packages/cupertino_icons/assets [-276.8 KB]'), + findsOneWidget, + ); - // Open the diffType dropdown. - await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); - await tester.pumpAndSettle(); + // Open the diffType dropdown. + await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); + await tester.pumpAndSettle(); - // Select entire app. - await tester.tap(find.text('Combined').hitTestable()); - await tester.pumpAndSettle(); + // Select entire app. + await tester.tap(find.text('Combined').hitTestable()); + await tester.pumpAndSettle(); - // Open the app unit dropdown. - await tester.tap(appUnitDropdownFinder); - await tester.pumpAndSettle(); + // Open the app unit dropdown. + await tester.tap(appUnitDropdownFinder); + await tester.pumpAndSettle(); - // Select the deferred units. - await tester.tap(find.text('Deferred').hitTestable()); - await tester.pumpAndSettle(); + // Select the deferred units. + await tester.tap(find.text('Deferred').hitTestable()); + await tester.pumpAndSettle(); - // Verify the deferred units are shown for entire app. - final deferredBreadcrumbs = _fetchBreadcrumbs(tester); - expect(deferredBreadcrumbs.length, 1); - expect( - deferredBreadcrumbs.first.text, - equals('/Deferred/flutter_assets [+344.3 KB]'), - ); - expect( - find.richText('packages/cupertino_icons/assets [+276.8 KB]'), - findsOneWidget, - ); + // Verify the deferred units are shown for entire app. + final deferredBreadcrumbs = _fetchBreadcrumbs(tester); + expect(deferredBreadcrumbs.length, 1); + expect( + deferredBreadcrumbs.first.text, + equals('/Deferred/flutter_assets [+344.3 KB]'), + ); + expect( + find.richText('packages/cupertino_icons/assets [+276.8 KB]'), + findsOneWidget, + ); - // Open the diffType dropdown. - await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); - await tester.pumpAndSettle(); + // Open the diffType dropdown. + await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); + await tester.pumpAndSettle(); - // Select increase only. - await tester.tap(find.text('Increase Only').hitTestable()); - await tester.pumpAndSettle(); + // Select increase only. + await tester.tap(find.text('Increase Only').hitTestable()); + await tester.pumpAndSettle(); - // Verify the deferred unit is shown for increase only. - final deferredIncreaseBreadcrumbs = _fetchBreadcrumbs(tester); - expect(deferredIncreaseBreadcrumbs.length, 1); - expect( - deferredIncreaseBreadcrumbs.first.text, - equals( - '/Deferred/flutter_assets [+344.3 KB]', - ), - ); - expect( - find.richText('packages/cupertino_icons/assets [+276.8 KB]'), - findsOneWidget, - ); + // Verify the deferred unit is shown for increase only. + final deferredIncreaseBreadcrumbs = _fetchBreadcrumbs(tester); + expect(deferredIncreaseBreadcrumbs.length, 1); + expect( + deferredIncreaseBreadcrumbs.first.text, + equals('/Deferred/flutter_assets [+344.3 KB]'), + ); + expect( + find.richText('packages/cupertino_icons/assets [+276.8 KB]'), + findsOneWidget, + ); - // Open the diffType dropdown. - await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); - await tester.pumpAndSettle(); + // Open the diffType dropdown. + await tester.tap(find.byKey(AppSizeScreen.diffTypeDropdownKey)); + await tester.pumpAndSettle(); - // Select decrease only. - await tester.tap(find.text('Decrease Only').hitTestable()); - await tester.pumpAndSettle(); + // Select decrease only. + await tester.tap(find.text('Decrease Only').hitTestable()); + await tester.pumpAndSettle(); - // Verify the main unit is shown for decrease only. - final deferredDecreaseBreadcrumbs = _fetchBreadcrumbs(tester); - expect(deferredDecreaseBreadcrumbs.length, 1); - expect( - deferredDecreaseBreadcrumbs.first.text, - equals( - '/Deferred/flutter_assets [0 B]', - ), - ); - }, - ); + // Verify the main unit is shown for decrease only. + final deferredDecreaseBreadcrumbs = _fetchBreadcrumbs(tester); + expect(deferredDecreaseBreadcrumbs.length, 1); + expect( + deferredDecreaseBreadcrumbs.first.text, + equals('/Deferred/flutter_assets [0 B]'), + ); + }); }); } diff --git a/packages/devtools_app/test/app_size/code_size_attribution_test.dart b/packages/devtools_app/test/app_size/code_size_attribution_test.dart index fa4f96eb3f0..1e5d8216ac7 100644 --- a/packages/devtools_app/test/app_size/code_size_attribution_test.dart +++ b/packages/devtools_app/test/app_size/code_size_attribution_test.dart @@ -41,16 +41,15 @@ void main() { ); }); - testWidgets( - 'builds dominator tree by default', - (WidgetTester tester) async { - await tester.pumpWidget(wrap(callGraphWithDominators)); - expect(find.text('Dominator Tree'), findsOneWidget); - expect(find.text('Call Graph'), findsNothing); - expect(find.byType(DominatorTree), findsOneWidget); - expect(find.byType(CallGraphView), findsNothing); - }, - ); + testWidgets('builds dominator tree by default', ( + WidgetTester tester, + ) async { + await tester.pumpWidget(wrap(callGraphWithDominators)); + expect(find.text('Dominator Tree'), findsOneWidget); + expect(find.text('Call Graph'), findsNothing); + expect(find.byType(DominatorTree), findsOneWidget); + expect(find.byType(CallGraphView), findsNothing); + }); testWidgets('builds call graph', (WidgetTester tester) async { await tester.pumpWidget(wrap(callGraphWithDominators)); @@ -92,18 +91,14 @@ void main() { expect(find.text('From'), findsOneWidget); expect(find.text('To'), findsOneWidget); - final fromTable = find - .byType(FlatTable) - .evaluate() - .first - .widget as FlatTable; + final fromTable = + find.byType(FlatTable).evaluate().first.widget + as FlatTable; expect(fromTable.data, isEmpty); - final toTable = find - .byType(FlatTable) - .evaluate() - .last - .widget as FlatTable; + final toTable = + find.byType(FlatTable).evaluate().last.widget + as FlatTable; expect(toTable.data.length, equals(17)); }); @@ -114,27 +109,28 @@ void main() { expect(find.text('From'), findsOneWidget); expect(find.text('To'), findsOneWidget); - var fromTable = find - .byType(FlatTable) - .evaluate() - .first - .widget as FlatTable; + var fromTable = + find.byType(FlatTable).evaluate().first.widget + as FlatTable; expect(fromTable.data, isEmpty); - var toTable = find.byType(FlatTable).evaluate().last.widget - as FlatTable; + var toTable = + find.byType(FlatTable).evaluate().last.widget + as FlatTable; expect(toTable.data.length, equals(17)); // Tap to re-root call graph. await tester.tap(find.richText('dart:math')); await tester.pumpAndSettle(); - fromTable = find.byType(FlatTable).evaluate().first.widget - as FlatTable; + fromTable = + find.byType(FlatTable).evaluate().first.widget + as FlatTable; expect(fromTable.data.length, equals(3)); - toTable = find.byType(FlatTable).evaluate().last.widget - as FlatTable; + toTable = + find.byType(FlatTable).evaluate().last.widget + as FlatTable; expect(toTable.data.length, equals(1)); }); }); @@ -155,11 +151,13 @@ void main() { expect(find.byKey(DominatorTree.dominatorTreeTableKey), findsOneWidget); expect(find.text('Package'), findsOneWidget); - final treeTable = find - .byKey(DominatorTree.dominatorTreeTableKey) - .evaluate() - .first - .widget as TreeTable; + final treeTable = + find + .byKey(DominatorTree.dominatorTreeTableKey) + .evaluate() + .first + .widget + as TreeTable; expect(treeTable.dataRoots.length, equals(1)); final root = treeTable.dataRoots.first; @@ -174,15 +172,18 @@ void main() { testWidgets('expands tree to selected node', (WidgetTester tester) async { dominatorTree = DominatorTree( dominatorTreeRoot: DominatorTreeNode.from(callGraph.root.dominatorRoot), - selectedNode: callGraph.root.dominated - .firstWhere((node) => node.display == 'package:code_size_package'), + selectedNode: callGraph.root.dominated.firstWhere( + (node) => node.display == 'package:code_size_package', + ), ); await tester.pumpWidget(wrap(dominatorTree)); - final treeTable = find - .byKey(DominatorTree.dominatorTreeTableKey) - .evaluate() - .first - .widget as TreeTable; + final treeTable = + find + .byKey(DominatorTree.dominatorTreeTableKey) + .evaluate() + .first + .widget + as TreeTable; final root = treeTable.dataRoots.first; expect(root.isExpanded, isTrue); diff --git a/packages/devtools_app/test/cpu_profiler/cpu_profile_model_test.dart b/packages/devtools_app/test/cpu_profiler/cpu_profile_model_test.dart index ec3a2511572..9cf54c92dcd 100644 --- a/packages/devtools_app/test/cpu_profiler/cpu_profile_model_test.dart +++ b/packages/devtools_app/test/cpu_profiler/cpu_profile_model_test.dart @@ -28,20 +28,20 @@ void main() { ); }); - test( - 'empty frame regression test', - () { - final cpuProfileEmptyData = - CpuProfileData.fromJson(cpuProfileResponseEmptyJson); - expect( - cpuProfileEmptyData.profileMetaData.time!.end!.inMilliseconds, - 47377796, - ); - final filtered = - CpuProfileData.filterFrom(cpuProfileEmptyData, (_) => true); - expect(filtered.profileMetaData.time!.end!.inMilliseconds, 0); - }, - ); + test('empty frame regression test', () { + final cpuProfileEmptyData = CpuProfileData.fromJson( + cpuProfileResponseEmptyJson, + ); + expect( + cpuProfileEmptyData.profileMetaData.time!.end!.inMilliseconds, + 47377796, + ); + final filtered = CpuProfileData.filterFrom( + cpuProfileEmptyData, + (_) => true, + ); + expect(filtered.profileMetaData.time!.end!.inMilliseconds, 0); + }); test('init from parse', () { expect( @@ -72,10 +72,7 @@ void main() { ..end = const Duration(microseconds: 47377799063), ); - expect( - subProfile.stackFramesJson, - equals(subProfileStackFrames), - ); + expect(subProfile.stackFramesJson, equals(subProfileStackFrames)); expect( subProfile.cpuSamples.map((sample) => sample.json), equals(subProfileTraceEvents), @@ -92,10 +89,7 @@ void main() { cpuProfileData, (stackFrame) => !stackFrame.packageUri.startsWith('dart:'), ); - expect( - filteredProfile.stackFramesJson, - equals(filteredStackFrames), - ); + expect(filteredProfile.stackFramesJson, equals(filteredStackFrames)); expect( filteredProfile.cpuSamples.map((sample) => sample.toJson), equals(filteredCpuSampleTraceEvents), @@ -115,39 +109,33 @@ void main() { expect(cpuProfileData.toJson(), equals(goldenCpuProfileDataJson)); }); - test( - 'converts golden samples to golden cpu profile data', - () async { - final generatedCpuProfileData = - await CpuProfileData.generateFromCpuSamples( - isolateId: goldenSamplesIsolate, - cpuSamples: CpuSamples.parse(goldenCpuSamplesJson)!, - ); + test('converts golden samples to golden cpu profile data', () async { + final generatedCpuProfileData = + await CpuProfileData.generateFromCpuSamples( + isolateId: goldenSamplesIsolate, + cpuSamples: CpuSamples.parse(goldenCpuSamplesJson)!, + ); - expect( - generatedCpuProfileData.toJson(), - equals(goldenCpuProfileDataJson), - ); - }, - ); + expect( + generatedCpuProfileData.toJson(), + equals(goldenCpuProfileDataJson), + ); + }); - test( - 'to json defaults packageUri to resolvedUrl', - () { - const id = '140357727781376-12'; + test('to json defaults packageUri to resolvedUrl', () { + const id = '140357727781376-12'; - final profileData = Map.of(goldenCpuProfileDataJson); - final stackFrame = goldenCpuProfileStackFrames[id] as Map; - final stackFrameData = {id: stackFrame}; - profileData['stackFrames'] = stackFrameData; - stackFrameData[id]!.remove(CpuProfileData.resolvedPackageUriKey); + final profileData = Map.of(goldenCpuProfileDataJson); + final stackFrame = goldenCpuProfileStackFrames[id] as Map; + final stackFrameData = {id: stackFrame}; + profileData['stackFrames'] = stackFrameData; + stackFrameData[id]!.remove(CpuProfileData.resolvedPackageUriKey); - final parsedProfileData = CpuProfileData.fromJson(profileData); + final parsedProfileData = CpuProfileData.fromJson(profileData); - final jsonPackageUri = parsedProfileData.stackFrames[id]!.packageUri; - expect(jsonPackageUri, stackFrame['resolvedUrl']); - }, - ); + final jsonPackageUri = parsedProfileData.stackFrames[id]!.packageUri; + expect(jsonPackageUri, stackFrame['resolvedUrl']); + }); test('generateFromCpuSamples handles duplicate resolvedUrls', () async { const resolvedUrl = 'the/resolved/Url'; @@ -274,34 +262,50 @@ void main() { expect(testStackFrame.ancestorIds.toList(), ['cpuProfileRoot']); expect(stackFrameA.ancestorIds.toList(), ['cpuProfileRoot']); expect(stackFrameB.ancestorIds.toList(), ['id_0', 'cpuProfileRoot']); - expect( - stackFrameC.ancestorIds.toList(), - ['id_1', 'id_0', 'cpuProfileRoot'], - ); - expect( - stackFrameD.ancestorIds.toList(), - ['id_1', 'id_0', 'cpuProfileRoot'], - ); - expect( - stackFrameE.ancestorIds.toList(), - ['id_3', 'id_1', 'id_0', 'cpuProfileRoot'], - ); - expect( - stackFrameF.ancestorIds.toList(), - ['id_4', 'id_3', 'id_1', 'id_0', 'cpuProfileRoot'], - ); - expect( - stackFrameF2.ancestorIds.toList(), - ['id_3', 'id_1', 'id_0', 'cpuProfileRoot'], - ); - expect( - stackFrameC2.ancestorIds.toList(), - ['id_5', 'id_4', 'id_3', 'id_1', 'id_0', 'cpuProfileRoot'], - ); - expect( - stackFrameC3.ancestorIds.toList(), - ['id_6', 'id_3', 'id_1', 'id_0', 'cpuProfileRoot'], - ); + expect(stackFrameC.ancestorIds.toList(), [ + 'id_1', + 'id_0', + 'cpuProfileRoot', + ]); + expect(stackFrameD.ancestorIds.toList(), [ + 'id_1', + 'id_0', + 'cpuProfileRoot', + ]); + expect(stackFrameE.ancestorIds.toList(), [ + 'id_3', + 'id_1', + 'id_0', + 'cpuProfileRoot', + ]); + expect(stackFrameF.ancestorIds.toList(), [ + 'id_4', + 'id_3', + 'id_1', + 'id_0', + 'cpuProfileRoot', + ]); + expect(stackFrameF2.ancestorIds.toList(), [ + 'id_3', + 'id_1', + 'id_0', + 'cpuProfileRoot', + ]); + expect(stackFrameC2.ancestorIds.toList(), [ + 'id_5', + 'id_4', + 'id_3', + 'id_1', + 'id_0', + 'cpuProfileRoot', + ]); + expect(stackFrameC3.ancestorIds.toList(), [ + 'id_6', + 'id_3', + 'id_1', + 'id_0', + 'cpuProfileRoot', + ]); }); test('shallowCopy', () { @@ -390,14 +394,8 @@ void main() { }); test('tooltip', () { - expect( - testTagRootedStackFrame.tooltip, - equals('[Tag] TagA - 10.0 ms'), - ); - expect( - stackFrameA.tooltip, - equals('[Native] A - 10.0 ms'), - ); + expect(testTagRootedStackFrame.tooltip, equals('[Tag] TagA - 10.0 ms')); + expect(stackFrameA.tooltip, equals('[Native] A - 10.0 ms')); expect( stackFrameB.tooltip, equals('[Dart] B - 10.0 ms - dart:async/zone.dart:2222'), diff --git a/packages/devtools_app/test/cpu_profiler/cpu_profile_transformer_test.dart b/packages/devtools_app/test/cpu_profiler/cpu_profile_transformer_test.dart index e50e1220eea..3d7b8ad3ded 100644 --- a/packages/devtools_app/test/cpu_profiler/cpu_profile_transformer_test.dart +++ b/packages/devtools_app/test/cpu_profiler/cpu_profile_transformer_test.dart @@ -34,17 +34,15 @@ void main() { test('process response with missing leaf frame', () { bool runTest() { - final cpuProfileDataWithMissingLeaf = - CpuProfileData.fromJson(responseWithMissingLeafFrame); - expect( - () async { - await cpuProfileTransformer.processData( - cpuProfileDataWithMissingLeaf, - processId: 'test', - ); - }, - throwsA(const TypeMatcher()), + final cpuProfileDataWithMissingLeaf = CpuProfileData.fromJson( + responseWithMissingLeafFrame, ); + expect(() async { + await cpuProfileTransformer.processData( + cpuProfileDataWithMissingLeaf, + processId: 'test', + ); + }, throwsA(const TypeMatcher())); return true; } diff --git a/packages/devtools_app/test/cpu_profiler/cpu_profiler_controller_test.dart b/packages/devtools_app/test/cpu_profiler/cpu_profiler_controller_test.dart index 45c66bfd9c9..58ace8a0269 100644 --- a/packages/devtools_app/test/cpu_profiler/cpu_profiler_controller_test.dart +++ b/packages/devtools_app/test/cpu_profiler/cpu_profiler_controller_test.dart @@ -105,9 +105,10 @@ void main() { extentMicros: 100, processId: 'test', ); - final originalData = controller.cpuProfileStore.lookupProfile( - label: CpuProfilerController.userTagNone, - )!; + final originalData = + controller.cpuProfileStore.lookupProfile( + label: CpuProfilerController.userTagNone, + )!; expect( originalData.functionProfile.stackFrames.values.length, equals(17), @@ -117,10 +118,10 @@ void main() { expect(filteredData.stackFrames.values.length, equals(12)); // The native frame filter is applied by default. - final originalNativeFrames = originalData - .functionProfile.stackFrames.values - .where((sf) => sf.isNative) - .toList(); + final originalNativeFrames = + originalData.functionProfile.stackFrames.values + .where((sf) => sf.isNative) + .toList(); final filteredNativeFrames = filteredData.stackFrames.values.where((sf) => sf.isNative).toList(); expect(originalNativeFrames.length, equals(5)); @@ -134,9 +135,10 @@ void main() { extentMicros: 100, processId: 'test', ); - final originalData = controller.cpuProfileStore.lookupProfile( - label: CpuProfilerController.userTagNone, - )!; + final originalData = + controller.cpuProfileStore.lookupProfile( + label: CpuProfilerController.userTagNone, + )!; expect( originalData.functionProfile.stackFrames.values.length, equals(17), @@ -188,9 +190,10 @@ void main() { extentMicros: 100, processId: 'test', ); - final originalData = controller.cpuProfileStore.lookupProfile( - label: CpuProfilerController.userTagNone, - )!; + final originalData = + controller.cpuProfileStore.lookupProfile( + label: CpuProfilerController.userTagNone, + )!; expect( originalData.functionProfile.stackFrames.values.length, equals(17), @@ -242,16 +245,10 @@ void main() { test('selectCpuStackFrame', () async { final dataNotifierValue = controller.dataNotifier.value!; - expect( - dataNotifierValue.selectedStackFrame, - isNull, - ); + expect(dataNotifierValue.selectedStackFrame, isNull); expect(controller.selectedCpuStackFrameNotifier.value, isNull); controller.selectCpuStackFrame(testStackFrame); - expect( - dataNotifierValue.selectedStackFrame, - equals(testStackFrame), - ); + expect(dataNotifierValue.selectedStackFrame, equals(testStackFrame)); expect( controller.selectedCpuStackFrameNotifier.value, equals(testStackFrame), @@ -327,8 +324,9 @@ void main() { test('processDataForTag', () async { await disableAllFiltering(); - final cpuProfileDataWithTags = - CpuProfileData.fromJson(cpuProfileDataWithUserTagsJson); + final cpuProfileDataWithTags = CpuProfileData.fromJson( + cpuProfileDataWithUserTagsJson, + ); await controller.transformer.processData( cpuProfileDataWithTags, processId: 'test', @@ -345,13 +343,16 @@ void main() { expect( dataNotifierValue - .cpuProfileRoot.profileMetaData.time!.duration.inMicroseconds, + .cpuProfileRoot + .profileMetaData + .time! + .duration + .inMicroseconds, equals(250), ); expect( dataNotifierValue.cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 1 - excl: 0 - incl: 5 Frame1 - children: 2 - excl: 0 - incl: 5 Frame2 - children: 2 - excl: 0 - incl: 2 @@ -359,48 +360,41 @@ void main() { Frame4 - children: 0 - excl: 1 - incl: 1 Frame5 - children: 1 - excl: 2 - incl: 3 Frame6 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); await controller.loadDataWithTag('userTagA'); expect( controller.dataNotifier.value!.cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 1 - excl: 0 - incl: 2 Frame1 - children: 2 - excl: 0 - incl: 2 Frame2 - children: 1 - excl: 0 - incl: 1 Frame3 - children: 0 - excl: 1 - incl: 1 Frame5 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); await controller.loadDataWithTag('userTagB'); expect( controller.dataNotifier.value!.cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 1 - excl: 0 - incl: 1 Frame1 - children: 1 - excl: 0 - incl: 1 Frame2 - children: 1 - excl: 0 - incl: 1 Frame4 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); await controller.loadDataWithTag('userTagC'); expect( controller.dataNotifier.value!.cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 1 - excl: 0 - incl: 2 Frame1 - children: 1 - excl: 0 - incl: 2 Frame5 - children: 1 - excl: 1 - incl: 2 Frame6 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); await controller.loadDataWithTag(CpuProfilerController.groupByUserTag); @@ -421,8 +415,9 @@ void main() { controller.activeFilter.value.settingFilters[0].setting.value, isTrue, ); - final cpuProfileDataWithTags = - CpuProfileData.fromJson(cpuProfileDataWithUserTagsJson); + final cpuProfileDataWithTags = CpuProfileData.fromJson( + cpuProfileDataWithUserTagsJson, + ); await controller.transformer.processData( cpuProfileDataWithTags, processId: 'test', @@ -442,8 +437,7 @@ void main() { ); expect( cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 1 - excl: 0 - incl: 5 Frame1 - children: 2 - excl: 0 - incl: 5 Frame2 - children: 2 - excl: 0 - incl: 2 @@ -451,50 +445,42 @@ void main() { Frame4 - children: 0 - excl: 1 - incl: 1 Frame5 - children: 1 - excl: 2 - incl: 3 Frame6 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); await controller.loadDataWithTag('userTagA'); expect( controller.dataNotifier.value!.cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 2 - excl: 0 - incl: 2 Frame2 - children: 0 - excl: 1 - incl: 1 Frame5 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); await controller.loadDataWithTag('userTagB'); expect( controller.dataNotifier.value!.cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 1 - excl: 0 - incl: 1 Frame2 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); await controller.loadDataWithTag('userTagC'); expect( controller.dataNotifier.value!.cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 1 - excl: 0 - incl: 2 Frame5 - children: 1 - excl: 1 - incl: 2 Frame6 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); await controller.loadDataWithTag(CpuProfilerController.groupByUserTag); expect( controller.dataNotifier.value!.cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 3 - excl: 0 - incl: 5 userTagA - children: 2 - excl: 0 - incl: 2 Frame2 - children: 0 - excl: 1 - incl: 1 @@ -504,15 +490,13 @@ void main() { userTagC - children: 1 - excl: 0 - incl: 2 Frame5 - children: 1 - excl: 1 - incl: 2 Frame6 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); await controller.loadDataWithTag(CpuProfilerController.groupByVmTag); expect( controller.dataNotifier.value!.cpuProfileRoot.profileAsString(), - equals( - ''' + equals(''' all - children: 3 - excl: 0 - incl: 5 vmTagA - children: 2 - excl: 0 - incl: 2 Frame2 - children: 0 - excl: 1 - incl: 1 @@ -522,8 +506,7 @@ void main() { vmTagC - children: 1 - excl: 0 - incl: 2 Frame5 - children: 1 - excl: 1 - incl: 2 Frame6 - children: 0 - excl: 1 - incl: 1 -''', - ), +'''), ); }); @@ -540,24 +523,15 @@ void main() { test('disposes', () { controller.dispose(); - expect( - () { - controller.dataNotifier.addListener(() {}); - }, - throwsA(anything), - ); - expect( - () { - controller.selectedCpuStackFrameNotifier.addListener(() {}); - }, - throwsA(anything), - ); - expect( - () { - controller.profilerBusyStatus.addListener(() {}); - }, - throwsA(anything), - ); + expect(() { + controller.dataNotifier.addListener(() {}); + }, throwsA(anything)); + expect(() { + controller.selectedCpuStackFrameNotifier.addListener(() {}); + }, throwsA(anything)); + expect(() { + controller.profilerBusyStatus.addListener(() {}); + }, throwsA(anything)); }); }); } diff --git a/packages/devtools_app/test/cpu_profiler/cpu_profiler_test.dart b/packages/devtools_app/test/cpu_profiler/cpu_profiler_test.dart index 881079f01c5..5a5eca05dd6 100644 --- a/packages/devtools_app/test/cpu_profiler/cpu_profiler_test.dart +++ b/packages/devtools_app/test/cpu_profiler/cpu_profiler_test.dart @@ -45,10 +45,7 @@ void main() { final transformer = CpuProfileTransformer(); controller = CpuProfilerController(); cpuProfileData = CpuProfileData.fromJson(goldenCpuProfileDataJson); - await transformer.processData( - cpuProfileData, - processId: 'test', - ); + await transformer.processData(cpuProfileData, processId: 'test'); setGlobal( DevToolsEnvironmentParameters, @@ -60,90 +57,69 @@ void main() { setGlobal(PreferencesController, PreferencesController()); setGlobal(IdeTheme, IdeTheme()); final mockScriptManager = MockScriptManager(); - when(mockScriptManager.sortedScripts).thenReturn( - ValueNotifier>([]), - ); - when(mockScriptManager.scriptRefForUri(any)).thenReturn( - ScriptRef( - uri: 'package:test/script.dart', - id: 'script.dart', - ), - ); + when( + mockScriptManager.sortedScripts, + ).thenReturn(ValueNotifier>([])); + when( + mockScriptManager.scriptRefForUri(any), + ).thenReturn(ScriptRef(uri: 'package:test/script.dart', id: 'script.dart')); setGlobal(ScriptManager, mockScriptManager); }); group('CpuProfiler', () { const windowSize = Size(2000.0, 1000.0); - testWidgetsWithWindowSize( - 'builds for empty cpuProfileData', - windowSize, - (WidgetTester tester) async { - cpuProfileData = CpuProfileData.fromJson(emptyCpuProfileDataJson); - cpuProfiler = CpuProfiler( - data: cpuProfileData, - controller: controller, - ); - await tester.pumpWidget(wrap(cpuProfiler)); - expect(find.byType(TabBar), findsOneWidget); - expect(find.byType(CpuBottomUpTable), findsOneWidget); - expect(find.byType(CpuCallTreeTable), findsNothing); - expect(find.byType(CpuMethodTable), findsNothing); - expect(find.byType(CpuProfileFlameChart), findsNothing); - expect(find.byType(CpuProfileStats), findsOneWidget); - expect(find.byType(UserTagDropdown), findsOneWidget); - expect(find.byType(ExpandAllButton), findsOneWidget); - expect(find.byType(CollapseAllButton), findsOneWidget); - expect(find.byType(FlameChartHelpButton), findsNothing); - expect( - find.byType(SearchField), - findsNothing, - ); - expect( - find.byType(SearchField), - findsNothing, - ); - expect(find.byKey(ProfilerTab.bottomUp.key), findsOneWidget); - expect(find.byKey(ProfilerTab.callTree.key), findsOneWidget); - expect(find.byKey(ProfilerTab.methodTable.key), findsOneWidget); - expect(find.byKey(ProfilerTab.cpuFlameChart.key), findsOneWidget); - }, - ); + testWidgetsWithWindowSize('builds for empty cpuProfileData', windowSize, ( + WidgetTester tester, + ) async { + cpuProfileData = CpuProfileData.fromJson(emptyCpuProfileDataJson); + cpuProfiler = CpuProfiler(data: cpuProfileData, controller: controller); + await tester.pumpWidget(wrap(cpuProfiler)); + expect(find.byType(TabBar), findsOneWidget); + expect(find.byType(CpuBottomUpTable), findsOneWidget); + expect(find.byType(CpuCallTreeTable), findsNothing); + expect(find.byType(CpuMethodTable), findsNothing); + expect(find.byType(CpuProfileFlameChart), findsNothing); + expect(find.byType(CpuProfileStats), findsOneWidget); + expect(find.byType(UserTagDropdown), findsOneWidget); + expect(find.byType(ExpandAllButton), findsOneWidget); + expect(find.byType(CollapseAllButton), findsOneWidget); + expect(find.byType(FlameChartHelpButton), findsNothing); + expect(find.byType(SearchField), findsNothing); + expect(find.byType(SearchField), findsNothing); + expect(find.byKey(ProfilerTab.bottomUp.key), findsOneWidget); + expect(find.byKey(ProfilerTab.callTree.key), findsOneWidget); + expect(find.byKey(ProfilerTab.methodTable.key), findsOneWidget); + expect(find.byKey(ProfilerTab.cpuFlameChart.key), findsOneWidget); + }); - testWidgetsWithWindowSize( - 'builds for valid cpuProfileData', - windowSize, - (WidgetTester tester) async { - cpuProfiler = CpuProfiler( - data: cpuProfileData, - controller: controller, - ); - await tester.pumpWidget(wrap(cpuProfiler)); - expect(find.byType(TabBar), findsOneWidget); - expect(find.byType(CpuBottomUpTable), findsOneWidget); - expect(find.byType(CpuProfileStats), findsOneWidget); - expect(find.byType(UserTagDropdown), findsOneWidget); - expect(find.byType(ExpandAllButton), findsOneWidget); - expect(find.byType(CollapseAllButton), findsOneWidget); - expect(find.byType(FlameChartHelpButton), findsNothing); - expect( - find.byType(SearchField), - findsNothing, - ); - expect( - find.byType(SearchField), - findsNothing, - ); - expect(find.byKey(ProfilerTab.bottomUp.key), findsOneWidget); - expect(find.byKey(ProfilerTab.callTree.key), findsOneWidget); - expect(find.byKey(ProfilerTab.methodTable.key), findsOneWidget); - expect(find.byKey(ProfilerTab.cpuFlameChart.key), findsOneWidget); - }, - ); + testWidgetsWithWindowSize('builds for valid cpuProfileData', windowSize, ( + WidgetTester tester, + ) async { + cpuProfiler = CpuProfiler(data: cpuProfileData, controller: controller); + await tester.pumpWidget(wrap(cpuProfiler)); + expect(find.byType(TabBar), findsOneWidget); + expect(find.byType(CpuBottomUpTable), findsOneWidget); + expect(find.byType(CpuProfileStats), findsOneWidget); + expect(find.byType(UserTagDropdown), findsOneWidget); + expect(find.byType(ExpandAllButton), findsOneWidget); + expect(find.byType(CollapseAllButton), findsOneWidget); + expect(find.byType(FlameChartHelpButton), findsNothing); + expect(find.byType(SearchField), findsNothing); + expect(find.byType(SearchField), findsNothing); + expect(find.byKey(ProfilerTab.bottomUp.key), findsOneWidget); + expect(find.byKey(ProfilerTab.callTree.key), findsOneWidget); + expect(find.byKey(ProfilerTab.methodTable.key), findsOneWidget); + expect(find.byKey(ProfilerTab.cpuFlameChart.key), findsOneWidget); + }); Future loadData(ProfilerScreenController controller) async { - for (final filter in controller - .cpuProfilerController.activeFilter.value.settingFilters) { + for (final filter + in controller + .cpuProfilerController + .activeFilter + .value + .settingFilters) { filter.setting.value = false; } final data = CpuProfilePair( @@ -176,8 +152,9 @@ void main() { // initialization. await Future.delayed(const Duration(seconds: 1)); - cpuProfileData = - CpuProfileData.fromJson(cpuProfileDataWithUserTagsJson); + cpuProfileData = CpuProfileData.fromJson( + cpuProfileDataWithUserTagsJson, + ); }); testWidgetsWithWindowSize( @@ -286,133 +263,99 @@ void main() { ); }); - testWidgetsWithWindowSize( - 'switches tabs', - windowSize, - (WidgetTester tester) async { - cpuProfiler = CpuProfiler( - data: cpuProfileData, - controller: controller, - ); - await tester.pumpWidget(wrap(cpuProfiler)); - expect(find.byType(TabBar), findsOneWidget); - expect(find.byType(CpuBottomUpTable), findsOneWidget); - expect(find.byType(CpuCallTreeTable), findsNothing); - expect(find.byType(CpuMethodTable), findsNothing); - expect(find.byType(CpuProfileFlameChart), findsNothing); - expect(find.byType(DevToolsFilterButton), findsOneWidget); - expect(find.byType(UserTagDropdown), findsOneWidget); - expect(find.byType(ExpandAllButton), findsOneWidget); - expect(find.byType(CollapseAllButton), findsOneWidget); - expect(find.byType(FlameChartHelpButton), findsNothing); - expect(find.byType(ModeDropdown), findsNothing); - expect( - find.byType(SearchField), - findsNothing, - ); - expect( - find.byType(SearchField), - findsNothing, - ); - - await tester.tap(find.text('Call Tree')); - await tester.pumpAndSettle(); - expect(find.byType(CpuBottomUpTable), findsNothing); - expect(find.byType(CpuCallTreeTable), findsOneWidget); - expect(find.byType(CpuMethodTable), findsNothing); - expect(find.byType(CpuProfileFlameChart), findsNothing); - expect(find.byType(DevToolsFilterButton), findsOneWidget); - expect(find.byType(UserTagDropdown), findsOneWidget); - expect(find.byType(ExpandAllButton), findsOneWidget); - expect(find.byType(CollapseAllButton), findsOneWidget); - expect(find.byType(FlameChartHelpButton), findsNothing); - expect(find.byType(ModeDropdown), findsNothing); - expect( - find.byType(SearchField), - findsNothing, - ); - expect( - find.byType(SearchField), - findsNothing, - ); + testWidgetsWithWindowSize('switches tabs', windowSize, ( + WidgetTester tester, + ) async { + cpuProfiler = CpuProfiler(data: cpuProfileData, controller: controller); + await tester.pumpWidget(wrap(cpuProfiler)); + expect(find.byType(TabBar), findsOneWidget); + expect(find.byType(CpuBottomUpTable), findsOneWidget); + expect(find.byType(CpuCallTreeTable), findsNothing); + expect(find.byType(CpuMethodTable), findsNothing); + expect(find.byType(CpuProfileFlameChart), findsNothing); + expect(find.byType(DevToolsFilterButton), findsOneWidget); + expect(find.byType(UserTagDropdown), findsOneWidget); + expect(find.byType(ExpandAllButton), findsOneWidget); + expect(find.byType(CollapseAllButton), findsOneWidget); + expect(find.byType(FlameChartHelpButton), findsNothing); + expect(find.byType(ModeDropdown), findsNothing); + expect(find.byType(SearchField), findsNothing); + expect(find.byType(SearchField), findsNothing); + + await tester.tap(find.text('Call Tree')); + await tester.pumpAndSettle(); + expect(find.byType(CpuBottomUpTable), findsNothing); + expect(find.byType(CpuCallTreeTable), findsOneWidget); + expect(find.byType(CpuMethodTable), findsNothing); + expect(find.byType(CpuProfileFlameChart), findsNothing); + expect(find.byType(DevToolsFilterButton), findsOneWidget); + expect(find.byType(UserTagDropdown), findsOneWidget); + expect(find.byType(ExpandAllButton), findsOneWidget); + expect(find.byType(CollapseAllButton), findsOneWidget); + expect(find.byType(FlameChartHelpButton), findsNothing); + expect(find.byType(ModeDropdown), findsNothing); + expect(find.byType(SearchField), findsNothing); + expect(find.byType(SearchField), findsNothing); + + await tester.tap(find.text('Method Table')); + await tester.pumpAndSettle(); + expect(find.byType(CpuBottomUpTable), findsNothing); + expect(find.byType(CpuCallTreeTable), findsNothing); + expect(find.byType(CpuMethodTable), findsOneWidget); + expect(find.byType(CpuProfileFlameChart), findsNothing); + expect(find.byType(DevToolsFilterButton), findsOneWidget); + expect(find.byType(UserTagDropdown), findsOneWidget); + expect(find.byType(ExpandAllButton), findsNothing); + expect(find.byType(CollapseAllButton), findsNothing); + expect(find.byType(FlameChartHelpButton), findsNothing); + expect(find.byType(ModeDropdown), findsNothing); + expect(find.byType(SearchField), findsOneWidget); + expect(find.byType(SearchField), findsNothing); + + await tester.tap(find.text('CPU Flame Chart')); + await tester.pumpAndSettle(); + expect(find.byType(CpuBottomUpTable), findsNothing); + expect(find.byType(CpuCallTreeTable), findsNothing); + expect(find.byType(CpuMethodTable), findsNothing); + expect(find.byType(CpuProfileFlameChart), findsOneWidget); + expect(find.byType(DevToolsFilterButton), findsOneWidget); + expect(find.byType(UserTagDropdown), findsOneWidget); + expect(find.byType(ExpandAllButton), findsNothing); + expect(find.byType(CollapseAllButton), findsNothing); + expect(find.byType(FlameChartHelpButton), findsOneWidget); + expect(find.byType(ModeDropdown), findsNothing); + expect(find.byType(SearchField), findsNothing); + expect(find.byType(SearchField), findsOneWidget); + }); - await tester.tap(find.text('Method Table')); - await tester.pumpAndSettle(); - expect(find.byType(CpuBottomUpTable), findsNothing); - expect(find.byType(CpuCallTreeTable), findsNothing); - expect(find.byType(CpuMethodTable), findsOneWidget); - expect(find.byType(CpuProfileFlameChart), findsNothing); - expect(find.byType(DevToolsFilterButton), findsOneWidget); - expect(find.byType(UserTagDropdown), findsOneWidget); - expect(find.byType(ExpandAllButton), findsNothing); - expect(find.byType(CollapseAllButton), findsNothing); - expect(find.byType(FlameChartHelpButton), findsNothing); - expect(find.byType(ModeDropdown), findsNothing); - expect( - find.byType(SearchField), - findsOneWidget, - ); - expect( - find.byType(SearchField), - findsNothing, - ); + testWidgetsWithWindowSize('can expand and collapse data', windowSize, ( + WidgetTester tester, + ) async { + cpuProfiler = CpuProfiler(data: cpuProfileData, controller: controller); + await tester.pumpWidget(wrap(cpuProfiler)); + await tester.tap(find.text('Call Tree')); + await tester.pumpAndSettle(); - await tester.tap(find.text('CPU Flame Chart')); - await tester.pumpAndSettle(); - expect(find.byType(CpuBottomUpTable), findsNothing); - expect(find.byType(CpuCallTreeTable), findsNothing); - expect(find.byType(CpuMethodTable), findsNothing); - expect(find.byType(CpuProfileFlameChart), findsOneWidget); - expect(find.byType(DevToolsFilterButton), findsOneWidget); - expect(find.byType(UserTagDropdown), findsOneWidget); - expect(find.byType(ExpandAllButton), findsNothing); - expect(find.byType(CollapseAllButton), findsNothing); - expect(find.byType(FlameChartHelpButton), findsOneWidget); - expect(find.byType(ModeDropdown), findsNothing); - expect( - find.byType(SearchField), - findsNothing, - ); - expect( - find.byType(SearchField), - findsOneWidget, - ); - }, - ); + expect(cpuProfileData.cpuProfileRoot.isExpanded, isFalse); + await tester.tap(find.byType(ExpandAllButton)); + expect(cpuProfiler.callTreeRoots.first.isExpanded, isTrue); + await tester.tap(find.byType(CollapseAllButton)); + expect(cpuProfiler.callTreeRoots.first.isExpanded, isFalse); - testWidgetsWithWindowSize( - 'can expand and collapse data', - windowSize, - (WidgetTester tester) async { - cpuProfiler = CpuProfiler( - data: cpuProfileData, - controller: controller, - ); - await tester.pumpWidget(wrap(cpuProfiler)); - await tester.tap(find.text('Call Tree')); - await tester.pumpAndSettle(); - - expect(cpuProfileData.cpuProfileRoot.isExpanded, isFalse); - await tester.tap(find.byType(ExpandAllButton)); - expect(cpuProfiler.callTreeRoots.first.isExpanded, isTrue); - await tester.tap(find.byType(CollapseAllButton)); - expect(cpuProfiler.callTreeRoots.first.isExpanded, isFalse); - - await tester.tap(find.text('Bottom Up')); - await tester.pumpAndSettle(); - for (final root in cpuProfiler.bottomUpRoots) { - expect(root.isExpanded, isFalse); - } - await tester.tap(find.byType(ExpandAllButton)); - for (final root in cpuProfiler.bottomUpRoots) { - expect(root.isExpanded, isTrue); - } - await tester.tap(find.byType(CollapseAllButton)); - for (final root in cpuProfiler.bottomUpRoots) { - expect(root.isExpanded, isFalse); - } - }, - ); + await tester.tap(find.text('Bottom Up')); + await tester.pumpAndSettle(); + for (final root in cpuProfiler.bottomUpRoots) { + expect(root.isExpanded, isFalse); + } + await tester.tap(find.byType(ExpandAllButton)); + for (final root in cpuProfiler.bottomUpRoots) { + expect(root.isExpanded, isTrue); + } + await tester.tap(find.byType(CollapseAllButton)); + for (final root in cpuProfiler.bottomUpRoots) { + expect(root.isExpanded, isFalse); + } + }); group('UserTag filters', () { late ProfilerScreenController controller; @@ -424,8 +367,9 @@ void main() { // initialization. await Future.delayed(const Duration(seconds: 1)); - cpuProfileData = - CpuProfileData.fromJson(cpuProfileDataWithUserTagsJson); + cpuProfileData = CpuProfileData.fromJson( + cpuProfileDataWithUserTagsJson, + ); await controller.cpuProfilerController.transformer.processData( cpuProfileData, processId: 'test', @@ -445,145 +389,159 @@ void main() { ); }); - testWidgetsWithWindowSize( - 'can filter data by user tag', - windowSize, - (WidgetTester tester) async { - await tester.runAsync(() async { - // We need to pump the entire `ProfilerScreenBody` widget because the - // CpuProfiler widget has `cpuProfileData` passed in from there, and - // CpuProfiler needs to be rebuilt on data updates. - await tester.pumpWidget( - wrapWithControllers( - const ProfilerScreenBody(), - profiler: controller, - ), - ); - await tester.pump(); + testWidgetsWithWindowSize('can filter data by user tag', windowSize, ( + WidgetTester tester, + ) async { + await tester.runAsync(() async { + // We need to pump the entire `ProfilerScreenBody` widget because the + // CpuProfiler widget has `cpuProfileData` passed in from there, and + // CpuProfiler needs to be rebuilt on data updates. + await tester.pumpWidget( + wrapWithControllers( + const ProfilerScreenBody(), + profiler: controller, + ), + ); + await tester.pump(); - expect(controller.cpuProfilerController.userTags.length, equals(3)); + expect(controller.cpuProfilerController.userTags.length, equals(3)); - expect(find.byType(UserTagDropdown), findsOneWidget); - // There is a Text widget and a RichText widget. - expect( - find.text('Filter by tag: userTagA', skipOffstage: false), - findsWidgets, - ); - expect( - find.text('Filter by tag: userTagB', skipOffstage: false), - findsWidgets, - ); - expect( - find.text('Filter by tag: userTagC', skipOffstage: false), - findsWidgets, - ); - expect( - find.text('Group by: User Tag', skipOffstage: false), - findsWidgets, - ); + expect(find.byType(UserTagDropdown), findsOneWidget); + // There is a Text widget and a RichText widget. + expect( + find.text('Filter by tag: userTagA', skipOffstage: false), + findsWidgets, + ); + expect( + find.text('Filter by tag: userTagB', skipOffstage: false), + findsWidgets, + ); + expect( + find.text('Filter by tag: userTagC', skipOffstage: false), + findsWidgets, + ); + expect( + find.text('Group by: User Tag', skipOffstage: false), + findsWidgets, + ); - await tester.tap(find.text('Call Tree')); - await tester.pumpAndSettle(); - expect(find.byType(CpuCallTreeTable), findsOneWidget); - await tester.tap(find.text('Expand All')); - await tester.pumpAndSettle(); + await tester.tap(find.text('Call Tree')); + await tester.pumpAndSettle(); + expect(find.byType(CpuCallTreeTable), findsOneWidget); + await tester.tap(find.text('Expand All')); + await tester.pumpAndSettle(); - expect( - controller.cpuProfileData!.profileMetaData.time!.duration - .inMicroseconds, - equals(250), - ); + expect( + controller + .cpuProfileData! + .profileMetaData + .time! + .duration + .inMicroseconds, + equals(250), + ); - expect(find.richTextContaining('Frame1'), findsOneWidget); - expect(find.richTextContaining('Frame2'), findsOneWidget); - expect(find.richTextContaining('Frame3'), findsOneWidget); - expect(find.richTextContaining('Frame4'), findsOneWidget); - expect(find.richTextContaining('Frame5'), findsOneWidget); - expect(find.richTextContaining('Frame6'), findsOneWidget); - expect(find.text('userTagA'), findsNothing); - expect(find.text('userTagB'), findsNothing); - expect(find.text('userTagC'), findsNothing); - - await tester.tap(find.byType(UserTagDropdown)); - await tester.pumpAndSettle(); - await tester.tap(find.text('Filter by tag: userTagA').last); + expect(find.richTextContaining('Frame1'), findsOneWidget); + expect(find.richTextContaining('Frame2'), findsOneWidget); + expect(find.richTextContaining('Frame3'), findsOneWidget); + expect(find.richTextContaining('Frame4'), findsOneWidget); + expect(find.richTextContaining('Frame5'), findsOneWidget); + expect(find.richTextContaining('Frame6'), findsOneWidget); + expect(find.text('userTagA'), findsNothing); + expect(find.text('userTagB'), findsNothing); + expect(find.text('userTagC'), findsNothing); - // Await a small delay to allow the CpuProfilerController to finish - // processing data for the new user tag. - await Future.delayed(const Duration(seconds: 1)); - await tester.pumpAndSettle(); + await tester.tap(find.byType(UserTagDropdown)); + await tester.pumpAndSettle(); + await tester.tap(find.text('Filter by tag: userTagA').last); - await tester.tap(find.text('Expand All')); - await tester.pumpAndSettle(); - expect( - controller.cpuProfileData!.profileMetaData.time!.duration - .inMicroseconds, - equals(100), - ); - expect(find.richTextContaining('Frame1'), findsNothing); - expect(find.richTextContaining('Frame2'), findsOneWidget); - expect(find.richTextContaining('Frame3'), findsNothing); - expect(find.richTextContaining('Frame4'), findsNothing); - expect(find.richTextContaining('Frame5'), findsOneWidget); - expect(find.richTextContaining('Frame6'), findsNothing); - expect(find.text('userTagA'), findsNothing); - expect(find.text('userTagB'), findsNothing); - expect(find.text('userTagC'), findsNothing); - - await tester.tap(find.byType(UserTagDropdown)); - await tester.pumpAndSettle(); - await tester.tap(find.text('Filter by tag: userTagB').last); + // Await a small delay to allow the CpuProfilerController to finish + // processing data for the new user tag. + await Future.delayed(const Duration(seconds: 1)); + await tester.pumpAndSettle(); - // Await a small delay to allow the CpuProfilerController to finish - // processing data for the new user tag. - await Future.delayed(const Duration(seconds: 1)); - await tester.pumpAndSettle(); + await tester.tap(find.text('Expand All')); + await tester.pumpAndSettle(); + expect( + controller + .cpuProfileData! + .profileMetaData + .time! + .duration + .inMicroseconds, + equals(100), + ); + expect(find.richTextContaining('Frame1'), findsNothing); + expect(find.richTextContaining('Frame2'), findsOneWidget); + expect(find.richTextContaining('Frame3'), findsNothing); + expect(find.richTextContaining('Frame4'), findsNothing); + expect(find.richTextContaining('Frame5'), findsOneWidget); + expect(find.richTextContaining('Frame6'), findsNothing); + expect(find.text('userTagA'), findsNothing); + expect(find.text('userTagB'), findsNothing); + expect(find.text('userTagC'), findsNothing); - await tester.tap(find.text('Expand All')); - await tester.pumpAndSettle(); - expect( - controller.cpuProfileData!.profileMetaData.time!.duration - .inMicroseconds, - equals(50), - ); - expect(find.richTextContaining('Frame1'), findsNothing); - expect(find.richTextContaining('Frame2'), findsOneWidget); - expect(find.richTextContaining('Frame3'), findsNothing); - expect(find.richTextContaining('Frame4'), findsNothing); - expect(find.richTextContaining('Frame5'), findsNothing); - expect(find.richTextContaining('Frame6'), findsNothing); - expect(find.text('userTagA'), findsNothing); - expect(find.text('userTagB'), findsNothing); - expect(find.text('userTagC'), findsNothing); - - await tester.tap(find.byType(UserTagDropdown)); - await tester.pumpAndSettle(); - await tester.tap(find.text('Filter by tag: userTagC').last); + await tester.tap(find.byType(UserTagDropdown)); + await tester.pumpAndSettle(); + await tester.tap(find.text('Filter by tag: userTagB').last); - // Await a small delay to allow the CpuProfilerController to finish - // processing data for the new user tag. - await Future.delayed(const Duration(seconds: 1)); - await tester.pumpAndSettle(); + // Await a small delay to allow the CpuProfilerController to finish + // processing data for the new user tag. + await Future.delayed(const Duration(seconds: 1)); + await tester.pumpAndSettle(); - await tester.tap(find.text('Expand All')); - await tester.pumpAndSettle(); - expect( - controller.cpuProfileData!.profileMetaData.time!.duration - .inMicroseconds, - equals(100), - ); - expect(find.richTextContaining('Frame1'), findsNothing); - expect(find.richTextContaining('Frame2'), findsNothing); - expect(find.richTextContaining('Frame3'), findsNothing); - expect(find.richTextContaining('Frame4'), findsNothing); - expect(find.richTextContaining('Frame5'), findsOneWidget); - expect(find.richTextContaining('Frame6'), findsOneWidget); - expect(find.text('userTagA'), findsNothing); - expect(find.text('userTagB'), findsNothing); - expect(find.text('userTagC'), findsNothing); - }); - }, - ); + await tester.tap(find.text('Expand All')); + await tester.pumpAndSettle(); + expect( + controller + .cpuProfileData! + .profileMetaData + .time! + .duration + .inMicroseconds, + equals(50), + ); + expect(find.richTextContaining('Frame1'), findsNothing); + expect(find.richTextContaining('Frame2'), findsOneWidget); + expect(find.richTextContaining('Frame3'), findsNothing); + expect(find.richTextContaining('Frame4'), findsNothing); + expect(find.richTextContaining('Frame5'), findsNothing); + expect(find.richTextContaining('Frame6'), findsNothing); + expect(find.text('userTagA'), findsNothing); + expect(find.text('userTagB'), findsNothing); + expect(find.text('userTagC'), findsNothing); + + await tester.tap(find.byType(UserTagDropdown)); + await tester.pumpAndSettle(); + await tester.tap(find.text('Filter by tag: userTagC').last); + + // Await a small delay to allow the CpuProfilerController to finish + // processing data for the new user tag. + await Future.delayed(const Duration(seconds: 1)); + await tester.pumpAndSettle(); + + await tester.tap(find.text('Expand All')); + await tester.pumpAndSettle(); + expect( + controller + .cpuProfileData! + .profileMetaData + .time! + .duration + .inMicroseconds, + equals(100), + ); + expect(find.richTextContaining('Frame1'), findsNothing); + expect(find.richTextContaining('Frame2'), findsNothing); + expect(find.richTextContaining('Frame3'), findsNothing); + expect(find.richTextContaining('Frame4'), findsNothing); + expect(find.richTextContaining('Frame5'), findsOneWidget); + expect(find.richTextContaining('Frame6'), findsOneWidget); + expect(find.text('userTagA'), findsNothing); + expect(find.text('userTagB'), findsNothing); + expect(find.text('userTagC'), findsNothing); + }); + }); }); group('Group by', () { @@ -597,8 +555,9 @@ void main() { await Future.delayed(const Duration(seconds: 1)); preferences.toggleVmDeveloperMode(true); - cpuProfileData = - CpuProfileData.fromJson(cpuProfileDataWithUserTagsJson); + cpuProfileData = CpuProfileData.fromJson( + cpuProfileDataWithUserTagsJson, + ); await loadData(controller); }); @@ -700,9 +659,10 @@ void main() { sampleCount: 100, samplePeriod: 100, stackDepth: 128, - time: TimeRange() - ..start = const Duration() - ..end = const Duration(microseconds: 10000), + time: + TimeRange() + ..start = const Duration() + ..end = const Duration(microseconds: 10000), ); await tester.pumpWidget(wrap(CpuProfileStats(metadata: metadata))); await tester.pumpAndSettle(); @@ -732,43 +692,43 @@ void main() { expect(find.text('Sampling depth: 128'), findsOneWidget); }); - testWidgets( - 'displays correctly for invalid data', - (WidgetTester tester) async { - final metadata = CpuProfileMetaData( - sampleCount: 100, - samplePeriod: 0, - stackDepth: 128, - time: TimeRange() - ..start = const Duration() - ..end = const Duration(microseconds: 10000), - ); - await tester.pumpWidget(wrap(CpuProfileStats(metadata: metadata))); - await tester.pumpAndSettle(); + testWidgets('displays correctly for invalid data', ( + WidgetTester tester, + ) async { + final metadata = CpuProfileMetaData( + sampleCount: 100, + samplePeriod: 0, + stackDepth: 128, + time: + TimeRange() + ..start = const Duration() + ..end = const Duration(microseconds: 10000), + ); + await tester.pumpWidget(wrap(CpuProfileStats(metadata: metadata))); + await tester.pumpAndSettle(); - expect( - find.byTooltip('The duration of time spanned by the CPU samples'), - findsOneWidget, - ); - expect( - find.byTooltip('The number of samples included in the profile'), - findsOneWidget, - ); - expect( - find.byTooltip( - 'The frequency at which samples are collected by the profiler', - ), - findsOneWidget, - ); - expect( - find.byTooltip('The maximum stack trace depth of a collected sample'), - findsOneWidget, - ); - expect(find.text('Duration: 10.0 ms'), findsOneWidget); - expect(find.text('Sample count: 100'), findsOneWidget); - expect(find.text('Sampling rate: -- Hz'), findsOneWidget); - expect(find.text('Sampling depth: 128'), findsOneWidget); - }, - ); + expect( + find.byTooltip('The duration of time spanned by the CPU samples'), + findsOneWidget, + ); + expect( + find.byTooltip('The number of samples included in the profile'), + findsOneWidget, + ); + expect( + find.byTooltip( + 'The frequency at which samples are collected by the profiler', + ), + findsOneWidget, + ); + expect( + find.byTooltip('The maximum stack trace depth of a collected sample'), + findsOneWidget, + ); + expect(find.text('Duration: 10.0 ms'), findsOneWidget); + expect(find.text('Sample count: 100'), findsOneWidget); + expect(find.text('Sampling rate: -- Hz'), findsOneWidget); + expect(find.text('Sampling depth: 128'), findsOneWidget); + }); }); } diff --git a/packages/devtools_app/test/cpu_profiler/method_table/method_table_model_test.dart b/packages/devtools_app/test/cpu_profiler/method_table/method_table_model_test.dart index d09c1584c97..a326b1eee30 100644 --- a/packages/devtools_app/test/cpu_profiler/method_table/method_table_model_test.dart +++ b/packages/devtools_app/test/cpu_profiler/method_table/method_table_model_test.dart @@ -17,9 +17,10 @@ void main() { selfCount: 1, profileMetaData: ProfileMetaData( sampleCount: 10, - time: TimeRange() - ..start = Duration.zero - ..end = const Duration(seconds: 1), + time: + TimeRange() + ..start = Duration.zero + ..end = const Duration(seconds: 1), ), stackFrameIds: {'1'}, ); @@ -31,9 +32,10 @@ void main() { selfCount: 4, profileMetaData: ProfileMetaData( sampleCount: 10, - time: TimeRange() - ..start = Duration.zero - ..end = const Duration(seconds: 1), + time: + TimeRange() + ..start = Duration.zero + ..end = const Duration(seconds: 1), ), stackFrameIds: {'2'}, ); @@ -45,9 +47,10 @@ void main() { selfCount: 2, profileMetaData: ProfileMetaData( sampleCount: 10, - time: TimeRange() - ..start = Duration.zero - ..end = const Duration(seconds: 1), + time: + TimeRange() + ..start = Duration.zero + ..end = const Duration(seconds: 1), ), stackFrameIds: {'3'}, ); @@ -59,9 +62,10 @@ void main() { selfCount: 3, profileMetaData: ProfileMetaData( sampleCount: 10, - time: TimeRange() - ..start = Duration.zero - ..end = const Duration(seconds: 1), + time: + TimeRange() + ..start = Duration.zero + ..end = const Duration(seconds: 1), ), stackFrameIds: {'4'}, ); diff --git a/packages/devtools_app/test/cpu_profiler/method_table/method_table_test.dart b/packages/devtools_app/test/cpu_profiler/method_table/method_table_test.dart index 56a28802eec..dd59c16b9bf 100644 --- a/packages/devtools_app/test/cpu_profiler/method_table/method_table_test.dart +++ b/packages/devtools_app/test/cpu_profiler/method_table/method_table_test.dart @@ -33,15 +33,12 @@ void main() { setGlobal(IdeTheme, IdeTheme()); setGlobal(OfflineDataController, OfflineDataController()); final mockScriptManager = MockScriptManager(); - when(mockScriptManager.sortedScripts).thenReturn( - ValueNotifier>([]), - ); - when(mockScriptManager.scriptRefForUri(any)).thenReturn( - ScriptRef( - uri: 'package:test/script.dart', - id: 'script.dart', - ), - ); + when( + mockScriptManager.sortedScripts, + ).thenReturn(ValueNotifier>([])); + when( + mockScriptManager.scriptRefForUri(any), + ).thenReturn(ScriptRef(uri: 'package:test/script.dart', id: 'script.dart')); setGlobal(ScriptManager, mockScriptManager); final data = CpuProfileData.fromJson(simpleCpuProfile2); await CpuProfileTransformer().processData(data, processId: 'test'); @@ -54,86 +51,78 @@ void main() { Future pumpMethodTable(WidgetTester tester) async { await tester.pumpWidget( - wrap( - CpuMethodTable( - methodTableController: methodTableController, - ), - ), + wrap(CpuMethodTable(methodTableController: methodTableController)), ); await tester.pumpAndSettle(); expect(find.byType(CpuMethodTable), findsOneWidget); } group('$CpuMethodTable', () { - testWidgetsWithWindowSize( - 'loads methods with no selection', - windowSize, - (WidgetTester tester) async { - await pumpMethodTable(tester); - expect( - find.byType(SearchableFlatTable), - findsOneWidget, - ); - expect(find.text('Method'), findsOneWidget); - expect(find.text('Total %'), findsOneWidget); - expect(find.text('Self %'), findsOneWidget); - expect(find.text('Caller %'), findsNothing); - expect(find.text('Callee %'), findsNothing); - expect( - find.text('Select a method to view its call graph.'), - findsOneWidget, - ); - await expectLater( - find.byType(CpuMethodTable), - matchesDevToolsGolden( - '../../test_infra/goldens/cpu_profiler/method_table_no_selection.png', - ), - ); - }, - ); + testWidgetsWithWindowSize('loads methods with no selection', windowSize, ( + WidgetTester tester, + ) async { + await pumpMethodTable(tester); + expect( + find.byType(SearchableFlatTable), + findsOneWidget, + ); + expect(find.text('Method'), findsOneWidget); + expect(find.text('Total %'), findsOneWidget); + expect(find.text('Self %'), findsOneWidget); + expect(find.text('Caller %'), findsNothing); + expect(find.text('Callee %'), findsNothing); + expect( + find.text('Select a method to view its call graph.'), + findsOneWidget, + ); + await expectLater( + find.byType(CpuMethodTable), + matchesDevToolsGolden( + '../../test_infra/goldens/cpu_profiler/method_table_no_selection.png', + ), + ); + }); - testWidgetsWithWindowSize( - 'loads methods with selection', - windowSize, - (WidgetTester tester) async { - final interestingNode = methodTableController.methods.value.first; - expect(interestingNode.name, 'A'); - expect(interestingNode.predecessors, isNotEmpty); - expect(interestingNode.successors, isNotEmpty); + testWidgetsWithWindowSize('loads methods with selection', windowSize, ( + WidgetTester tester, + ) async { + final interestingNode = methodTableController.methods.value.first; + expect(interestingNode.name, 'A'); + expect(interestingNode.predecessors, isNotEmpty); + expect(interestingNode.successors, isNotEmpty); - methodTableController.selectedNode.value = interestingNode; - await pumpMethodTable(tester); - expect( - find.byType(SearchableFlatTable), - findsOneWidget, - ); - expect(find.byType(FlatTable), findsNWidgets(2)); - expect(find.text('Method'), findsNWidgets(3)); - expect(find.text('Total %'), findsOneWidget); - expect(find.text('Self %'), findsOneWidget); - expect(find.text('Caller %'), findsOneWidget); - expect(find.text('Callee %'), findsOneWidget); - expect( - find.text('Select a method to view its call graph.'), - findsNothing, - ); - await expectLater( - find.byType(CpuMethodTable), - matchesDevToolsGolden( - '../../test_infra/goldens/cpu_profiler/method_table_with_selection.png', - ), - ); + methodTableController.selectedNode.value = interestingNode; + await pumpMethodTable(tester); + expect( + find.byType(SearchableFlatTable), + findsOneWidget, + ); + expect(find.byType(FlatTable), findsNWidgets(2)); + expect(find.text('Method'), findsNWidgets(3)); + expect(find.text('Total %'), findsOneWidget); + expect(find.text('Self %'), findsOneWidget); + expect(find.text('Caller %'), findsOneWidget); + expect(find.text('Callee %'), findsOneWidget); + expect( + find.text('Select a method to view its call graph.'), + findsNothing, + ); + await expectLater( + find.byType(CpuMethodTable), + matchesDevToolsGolden( + '../../test_infra/goldens/cpu_profiler/method_table_with_selection.png', + ), + ); - methodTableController.selectedNode.value = - methodTableController.methods.value.last; - await tester.pumpAndSettle(); - await expectLater( - find.byType(CpuMethodTable), - matchesDevToolsGolden( - '../../test_infra/goldens/cpu_profiler/method_table_with_selection_2.png', - ), - ); - }, - ); + methodTableController.selectedNode.value = + methodTableController.methods.value.last; + await tester.pumpAndSettle(); + await expectLater( + find.byType(CpuMethodTable), + matchesDevToolsGolden( + '../../test_infra/goldens/cpu_profiler/method_table_with_selection_2.png', + ), + ); + }); }); } diff --git a/packages/devtools_app/test/cpu_profiler/profiler_screen_controller_test.dart b/packages/devtools_app/test/cpu_profiler/profiler_screen_controller_test.dart index 71bdff07d35..9dd1f8a4f7d 100644 --- a/packages/devtools_app/test/cpu_profiler/profiler_screen_controller_test.dart +++ b/packages/devtools_app/test/cpu_profiler/profiler_screen_controller_test.dart @@ -12,8 +12,9 @@ void main() { group('ProfilerScreenController', () { late ProfilerScreenController controller; final fakeServiceConnection = FakeServiceConnectionManager(); - when(fakeServiceConnection.serviceManager.connectedApp!.isFlutterAppNow) - .thenReturn(false); + when( + fakeServiceConnection.serviceManager.connectedApp!.isFlutterAppNow, + ).thenReturn(false); setUp(() { setGlobal( @@ -36,27 +37,18 @@ void main() { test('disposes', () { controller.dispose(); - expect( - () { - controller.recordingNotifier.addListener(() {}); - }, - throwsA(anything), - ); + expect(() { + controller.recordingNotifier.addListener(() {}); + }, throwsA(anything)); - expect( - () { - controller.cpuProfilerController.dataNotifier.addListener(() {}); - }, - throwsA(anything), - ); + expect(() { + controller.cpuProfilerController.dataNotifier.addListener(() {}); + }, throwsA(anything)); - expect( - () { - controller.cpuProfilerController.selectedCpuStackFrameNotifier - .addListener(() {}); - }, - throwsA(anything), - ); + expect(() { + controller.cpuProfilerController.selectedCpuStackFrameNotifier + .addListener(() {}); + }, throwsA(anything)); }); }); } diff --git a/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart b/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart index 8476d584035..e0e479652ad 100644 --- a/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart +++ b/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart @@ -34,16 +34,16 @@ void main() { expect(find.byType(StartStopRecordingButton), findsOneWidget); expect(find.byType(ClearButton), findsOneWidget); expect(find.text('Load all CPU samples'), findsOneWidget); - if (scene.fakeServiceConnection.serviceManager.connectedApp! + if (scene + .fakeServiceConnection + .serviceManager + .connectedApp! .isFlutterNativeAppNow) { expect(find.text('Profile app start up'), findsOneWidget); } expect(find.byType(CpuSamplingRateDropdown), findsOneWidget); expect(find.byType(OpenSaveButtonGroup), findsOneWidget); - expect( - find.byType(ProfileRecordingInstructions), - findsOneWidget, - ); + expect(find.byType(ProfileRecordingInstructions), findsOneWidget); expect(find.byType(RecordingStatus), findsNothing); expect(find.byType(CircularProgressIndicator), findsNothing); expect(find.byType(CpuProfiler), findsNothing); @@ -103,10 +103,7 @@ void main() { // Start recording. await tester.tap(find.byType(StartStopRecordingButton)); await tester.pump(const Duration(seconds: 1)); - expect( - find.byType(ProfileRecordingInstructions), - findsNothing, - ); + expect(find.byType(ProfileRecordingInstructions), findsNothing); expect(find.byType(RecordingStatus), findsOneWidget); expect(find.byType(CircularProgressIndicator), findsOneWidget); expect(find.byType(CpuProfiler), findsNothing); @@ -125,37 +122,32 @@ void main() { }, ); - testWidgetsWithWindowSize( - 'builds for disabled profiler', - windowSize, - (WidgetTester tester) async { - await tester.runAsync(() async { - await scene.fakeServiceConnection.serviceManager.service!.setFlag( - vm_flags.profiler, - 'false', - ); - }); - await pumpProfilerScreen(tester); - - expect(find.byType(CpuProfilerDisabled), findsOneWidget); - expect( - find.byType(ProfileRecordingInstructions), - findsNothing, + testWidgetsWithWindowSize('builds for disabled profiler', windowSize, ( + WidgetTester tester, + ) async { + await tester.runAsync(() async { + await scene.fakeServiceConnection.serviceManager.service!.setFlag( + vm_flags.profiler, + 'false', ); - expect(find.byType(RecordButton), findsNothing); - expect(find.byType(StopRecordingButton), findsNothing); - expect(find.byType(ClearButton), findsNothing); - expect(find.byType(CpuSamplingRateDropdown), findsNothing); - expect(find.byType(OpenSaveButtonGroup), findsNothing); - - await tester.runAsync(() async { - await tester.tap(find.text('Enable profiler')); - // Delay to ensure the memory profiler has collected data. - await tester.pump(const Duration(seconds: 1)); - }); - await tester.pumpAndSettle(); - verifyBaseState(); - }, - ); + }); + await pumpProfilerScreen(tester); + + expect(find.byType(CpuProfilerDisabled), findsOneWidget); + expect(find.byType(ProfileRecordingInstructions), findsNothing); + expect(find.byType(RecordButton), findsNothing); + expect(find.byType(StopRecordingButton), findsNothing); + expect(find.byType(ClearButton), findsNothing); + expect(find.byType(CpuSamplingRateDropdown), findsNothing); + expect(find.byType(OpenSaveButtonGroup), findsNothing); + + await tester.runAsync(() async { + await tester.tap(find.text('Enable profiler')); + // Delay to ensure the memory profiler has collected data. + await tester.pump(const Duration(seconds: 1)); + }); + await tester.pumpAndSettle(); + verifyBaseState(); + }); }); } diff --git a/packages/devtools_app/test/debugger/association_variable_test.dart b/packages/devtools_app/test/debugger/association_variable_test.dart index bbf90e2615f..1587388cf91 100644 --- a/packages/devtools_app/test/debugger/association_variable_test.dart +++ b/packages/devtools_app/test/debugger/association_variable_test.dart @@ -59,22 +59,18 @@ void main() { isSystemIsolate: false, ); final variable = DartObjectNode.create( - BoundVariable( - name: 'test', - value: instance, - ), + BoundVariable(name: 'test', value: instance), isolateRef, ); - when(manager.serviceManager.service!.getObject(isolateId, objectId)) - .thenAnswer((_) async { + when( + manager.serviceManager.service!.getObject(isolateId, objectId), + ).thenAnswer((_) async { return instance; }); await buildVariablesTree(variable); - expect(variable.children, [ - matchesVariable(name: 'Hey', value: '12.34'), - ]); + expect(variable.children, [matchesVariable(name: 'Hey', value: '12.34')]); }, ); @@ -107,22 +103,18 @@ void main() { ], ); final variable = DartObjectNode.create( - BoundVariable( - name: 'test', - value: instance, - ), + BoundVariable(name: 'test', value: instance), isolateRef, ); - when(manager.serviceManager.service!.getObject(isolateId, objectId)) - .thenAnswer((_) async { + when( + manager.serviceManager.service!.getObject(isolateId, objectId), + ).thenAnswer((_) async { return instance; }); await buildVariablesTree(variable); - expect(variable.children, [ - matchesVariable(name: '1', value: '12.34'), - ]); + expect(variable.children, [matchesVariable(name: '1', value: '12.34')]); }, ); @@ -155,14 +147,12 @@ void main() { ], ); final variable = DartObjectNode.create( - BoundVariable( - name: 'test', - value: instance, - ), + BoundVariable(name: 'test', value: instance), isolateRef, ); - when(manager.serviceManager.service!.getObject(isolateId, objectId)) - .thenAnswer((_) async { + when( + manager.serviceManager.service!.getObject(isolateId, objectId), + ).thenAnswer((_) async { return instance; }); @@ -179,19 +169,8 @@ void main() { ); } -Matcher matchesVariable({ - required String? name, - required Object value, -}) { +Matcher matchesVariable({required String? name, required Object value}) { return const TypeMatcher() - .having( - (v) => v.displayValue, - 'displayValue', - equals(value), - ) - .having( - (v) => v.name, - 'name', - equals(name), - ); + .having((v) => v.displayValue, 'displayValue', equals(value)) + .having((v) => v.name, 'name', equals(name)); } diff --git a/packages/devtools_app/test/debugger/debugger_codeview_statistics_test.dart b/packages/devtools_app/test/debugger/debugger_codeview_statistics_test.dart index 084e191f500..3f683d951ab 100644 --- a/packages/devtools_app/test/debugger/debugger_codeview_statistics_test.dart +++ b/packages/devtools_app/test/debugger/debugger_codeview_statistics_test.dart @@ -38,10 +38,12 @@ void main() { isProfileBuild: false, isWebApp: false, ); - when(fakeServiceConnection.serviceManager.connectedApp!.isProfileBuildNow) - .thenReturn(false); - when(fakeServiceConnection.serviceManager.connectedApp!.isDartWebAppNow) - .thenReturn(false); + when( + fakeServiceConnection.serviceManager.connectedApp!.isProfileBuildNow, + ).thenReturn(false); + when( + fakeServiceConnection.serviceManager.connectedApp!.isDartWebAppNow, + ).thenReturn(false); setGlobal(ServiceConnectionManager, fakeServiceConnection); setGlobal(IdeTheme, IdeTheme()); setGlobal(ScriptManager, MockScriptManager()); @@ -54,29 +56,32 @@ void main() { scriptsHistory.pushEntry(mockScript!); final mockCodeViewController = debuggerController.codeViewController; - when(mockCodeViewController.currentScriptRef) - .thenReturn(ValueNotifier(mockScriptRef)); - when(mockCodeViewController.currentParsedScript) - .thenReturn(ValueNotifier(mockParsedScript)); + when( + mockCodeViewController.currentScriptRef, + ).thenReturn(ValueNotifier(mockScriptRef)); + when( + mockCodeViewController.currentParsedScript, + ).thenReturn(ValueNotifier(mockParsedScript)); when(mockCodeViewController.scriptsHistory).thenReturn(scriptsHistory); showCodeCoverage = ValueNotifier(false); showProfileHits = ValueNotifier(false); - when(mockCodeViewController.toggleShowCodeCoverage()).thenAnswer( - (_) => showCodeCoverage.value = !showCodeCoverage.value, - ); - when(mockCodeViewController.toggleShowProfileInformation()).thenAnswer( - (_) => showProfileHits.value = !showProfileHits.value, - ); + when( + mockCodeViewController.toggleShowCodeCoverage(), + ).thenAnswer((_) => showCodeCoverage.value = !showCodeCoverage.value); + when( + mockCodeViewController.toggleShowProfileInformation(), + ).thenAnswer((_) => showProfileHits.value = !showProfileHits.value); when(mockCodeViewController.showCodeCoverage).thenReturn(showCodeCoverage); - when(mockCodeViewController.showProfileInformation) - .thenReturn(showProfileHits); + when( + mockCodeViewController.showProfileInformation, + ).thenReturn(showProfileHits); refreshCodeCoverageInvoked = false; - // TODO(jacobr): is there a better way to clean this up? - // ignore: discarded_futures - when(mockCodeViewController.refreshCodeStatistics()).thenAnswer( - (_) async => refreshCodeCoverageInvoked = true, - ); + when( + // TODO(jacobr): is there a better way to clean this up? + // ignore: discarded_futures + mockCodeViewController.refreshCodeStatistics(), + ).thenAnswer((_) async => refreshCodeCoverageInvoked = true); when(codeViewController.navigationInProgress).thenReturn(false); }); @@ -140,10 +145,7 @@ void main() { // Coverage display starts disabled. gutterItemCoverageTester(tester, false); gutterItemProfileInfoTester(tester, false); - expect( - tester.widget(findRefresh).onPressed, - isNull, - ); + expect(tester.widget(findRefresh).onPressed, isNull); // Toggle showing coverage and verify the gutter items contain coverage // information. @@ -151,10 +153,7 @@ void main() { await pumpDebuggerScreen(tester, debuggerController); gutterItemCoverageTester(tester, true); gutterItemProfileInfoTester(tester, false); - expect( - tester.widget(findRefresh).onPressed, - isNotNull, - ); + expect(tester.widget(findRefresh).onPressed, isNotNull); // Toggle showing profiler information and verify the gutter items contain // profiling information. @@ -162,10 +161,7 @@ void main() { await pumpDebuggerScreen(tester, debuggerController); gutterItemCoverageTester(tester, true); gutterItemProfileInfoTester(tester, true); - expect( - tester.widget(findRefresh).onPressed, - isNotNull, - ); + expect(tester.widget(findRefresh).onPressed, isNotNull); // Test the refresh coverage button. await tester.tap(findRefresh); @@ -177,20 +173,14 @@ void main() { await pumpDebuggerScreen(tester, debuggerController); gutterItemCoverageTester(tester, false); gutterItemProfileInfoTester(tester, true); - expect( - tester.widget(findRefresh).onPressed, - isNotNull, - ); + expect(tester.widget(findRefresh).onPressed, isNotNull); // Toggle again and verify the profiling information is no longer present. await tester.tap(findProfileToggle); await pumpDebuggerScreen(tester, debuggerController); gutterItemCoverageTester(tester, false); gutterItemProfileInfoTester(tester, false); - expect( - tester.widget(findRefresh).onPressed, - isNull, - ); + expect(tester.widget(findRefresh).onPressed, isNull); }, ); } diff --git a/packages/devtools_app/test/debugger/debugger_codeview_test.dart b/packages/devtools_app/test/debugger/debugger_codeview_test.dart index 3b54f172ad0..263b2fbc648 100644 --- a/packages/devtools_app/test/debugger/debugger_codeview_test.dart +++ b/packages/devtools_app/test/debugger/debugger_codeview_test.dart @@ -54,15 +54,18 @@ void main() { ); setGlobal(PreferencesController, PreferencesController()); fakeServiceConnection.consoleService.ensureServiceInitialized(); - when(fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger')) - .thenReturn(ValueNotifier(0)); + when( + fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger'), + ).thenReturn(ValueNotifier(0)); scriptsHistory.pushEntry(mockScript!); final mockCodeViewController = debuggerController.codeViewController; - when(mockCodeViewController.currentScriptRef) - .thenReturn(ValueNotifier(mockScriptRef)); - when(mockCodeViewController.currentParsedScript) - .thenReturn(ValueNotifier(mockParsedScript)); + when( + mockCodeViewController.currentScriptRef, + ).thenReturn(ValueNotifier(mockScriptRef)); + when( + mockCodeViewController.currentParsedScript, + ).thenReturn(ValueNotifier(mockParsedScript)); when(mockCodeViewController.scriptsHistory).thenReturn(scriptsHistory); }); @@ -106,9 +109,7 @@ void main() { ); await expectLater( find.byType(CodeView), - matchesDevToolsGolden( - '../test_infra/goldens/codeview_scrollbars.png', - ), + matchesDevToolsGolden('../test_infra/goldens/codeview_scrollbars.png'), ); }, ); @@ -117,30 +118,27 @@ void main() { 'search in file field is visible', smallWindowSize, (WidgetTester tester) async { - when(codeViewController.showSearchInFileField) - .thenReturn(ValueNotifier(true)); + when( + codeViewController.showSearchInFileField, + ).thenReturn(ValueNotifier(true)); when(codeViewController.searchFieldFocusNode).thenReturn(FocusNode()); - when(codeViewController.searchTextFieldController) - .thenReturn(SearchTextEditingController()); + when( + codeViewController.searchTextFieldController, + ).thenReturn(SearchTextEditingController()); await pumpDebuggerScreen(tester, debuggerController); expect(find.byType(SearchField), findsOneWidget); }, ); - testWidgetsWithWindowSize( - 'file opener is visible', - smallWindowSize, - (WidgetTester tester) async { - when(codeViewController.showFileOpener).thenReturn(ValueNotifier(true)); - when(scriptManager.sortedScripts).thenReturn(ValueNotifier([])); - await pumpDebuggerScreen(tester, debuggerController); - expect( - find.byKey(debuggerCodeViewFileOpenerKey), - findsOneWidget, - ); - }, - ); + testWidgetsWithWindowSize('file opener is visible', smallWindowSize, ( + WidgetTester tester, + ) async { + when(codeViewController.showFileOpener).thenReturn(ValueNotifier(true)); + when(scriptManager.sortedScripts).thenReturn(ValueNotifier([])); + await pumpDebuggerScreen(tester, debuggerController); + expect(find.byKey(debuggerCodeViewFileOpenerKey), findsOneWidget); + }); group('fetchScriptLocationFullFilePath', () { testWidgets('gets the full path', (WidgetTester tester) async { @@ -153,57 +151,62 @@ void main() { ), ); - final filePath = - await fetchScriptLocationFullFilePath(codeViewController); + final filePath = await fetchScriptLocationFullFilePath( + codeViewController, + ); expect(filePath, equals(mockScriptRefFileUri)); }); - testWidgets( - 'gets the path if immediately available', - (WidgetTester tester) async { - when(codeViewController.scriptLocation).thenReturn( - ValueNotifier( - ScriptLocation( - mockScriptRef, - location: const SourcePosition(line: 50, column: 50), - ), + testWidgets('gets the path if immediately available', ( + WidgetTester tester, + ) async { + when(codeViewController.scriptLocation).thenReturn( + ValueNotifier( + ScriptLocation( + mockScriptRef, + location: const SourcePosition(line: 50, column: 50), ), - ); - // Prefetch File Uris - await serviceConnection.serviceManager.resolvedUriManager.fetchFileUris( - serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!, - [mockScriptRef.uri!], - ); - - final filePath = - await fetchScriptLocationFullFilePath(codeViewController); - - expect(filePath, equals(mockScriptRefFileUri)); - }, - ); + ), + ); + // Prefetch File Uris + await serviceConnection.serviceManager.resolvedUriManager.fetchFileUris( + serviceConnection + .serviceManager + .isolateManager + .selectedIsolate + .value! + .id!, + [mockScriptRef.uri!], + ); + + final filePath = await fetchScriptLocationFullFilePath( + codeViewController, + ); + + expect(filePath, equals(mockScriptRefFileUri)); + }); - testWidgets( - 'returns null if package not found', - (WidgetTester tester) async { - when(codeViewController.scriptLocation).thenReturn( - ValueNotifier( - ScriptLocation( - ScriptRef( - uri: 'some/unknown/file', - id: 'unknown-script-ref-for-test', - ), - location: const SourcePosition(line: 123, column: 456), + testWidgets('returns null if package not found', ( + WidgetTester tester, + ) async { + when(codeViewController.scriptLocation).thenReturn( + ValueNotifier( + ScriptLocation( + ScriptRef( + uri: 'some/unknown/file', + id: 'unknown-script-ref-for-test', ), + location: const SourcePosition(line: 123, column: 456), ), - ); + ), + ); - final filePath = - await fetchScriptLocationFullFilePath(codeViewController); + final filePath = await fetchScriptLocationFullFilePath( + codeViewController, + ); - expect(filePath, isNull); - }, - ); + expect(filePath, isNull); + }); }); } diff --git a/packages/devtools_app/test/debugger/debugger_console_test.dart b/packages/devtools_app/test/debugger/debugger_console_test.dart index fd4533065f8..0e0294e4fd8 100644 --- a/packages/devtools_app/test/debugger/debugger_console_test.dart +++ b/packages/devtools_app/test/debugger/debugger_console_test.dart @@ -22,10 +22,12 @@ void main() { const windowSize = Size(4000.0, 4000.0); - when(fakeServiceConnection.serviceManager.connectedApp!.isProfileBuildNow) - .thenReturn(false); - when(fakeServiceConnection.serviceManager.connectedApp!.isDartWebAppNow) - .thenReturn(false); + when( + fakeServiceConnection.serviceManager.connectedApp!.isProfileBuildNow, + ).thenReturn(false); + when( + fakeServiceConnection.serviceManager.connectedApp!.isDartWebAppNow, + ).thenReturn(false); setGlobal(ServiceConnectionManager, fakeServiceConnection); setGlobal(IdeTheme, IdeTheme()); setGlobal(ScriptManager, MockScriptManager()); @@ -37,8 +39,9 @@ void main() { ); setGlobal(PreferencesController, PreferencesController()); fakeServiceConnection.consoleService.ensureServiceInitialized(); - when(fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger')) - .thenReturn(ValueNotifier(0)); + when( + fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger'), + ).thenReturn(ValueNotifier(0)); Future pumpConsole( WidgetTester tester, diff --git a/packages/devtools_app/test/debugger/debugger_controller_test.dart b/packages/devtools_app/test/debugger/debugger_controller_test.dart index 925d036aa94..a0b6cdbafe2 100644 --- a/packages/devtools_app/test/debugger/debugger_controller_test.dart +++ b/packages/devtools_app/test/debugger/debugger_controller_test.dart @@ -239,10 +239,7 @@ void main() { debuggerController.matchesForSearch('hello world').toString(), equals('[5:28-39, 6:9-20]'), ); - expect( - debuggerController.matchesForSearch('').toString(), - equals('[]'), - ); + expect(debuggerController.matchesForSearch('').toString(), equals('[]')); }); }); } diff --git a/packages/devtools_app/test/debugger/debugger_evaluation_test.dart b/packages/devtools_app/test/debugger/debugger_evaluation_test.dart index 6e18a47de63..9c0b8e24be5 100644 --- a/packages/devtools_app/test/debugger/debugger_evaluation_test.dart +++ b/packages/devtools_app/test/debugger/debugger_evaluation_test.dart @@ -63,298 +63,235 @@ void main() { await whenMatches(debuggerController.selectedStackFrame, (f) => f != null); } - group( - 'EvalOnDartLibrary', - () { - test( - 'returns scoped variables when EditingParts is not a field', - () async { - await runMethodAndWaitForPause( - 'AnotherClass().pauseWithScopedVariablesMethod()', - ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: 'foo', - leftSide: '', - rightSide: '', - ), - evalService, - ), - equals(['foo', 'foobar']), - ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: 'b', - leftSide: '', - rightSide: '', - ), - evalService, - ), - equals(['bar', 'baz']), - ); - }, - timeout: const Timeout.factor(8), - ); + group('EvalOnDartLibrary', () { + test( + 'returns scoped variables when EditingParts is not a field', + () async { + await runMethodAndWaitForPause( + 'AnotherClass().pauseWithScopedVariablesMethod()', + ); + expect( + await autoCompleteResultsFor( + EditingParts(activeWord: 'foo', leftSide: '', rightSide: ''), + evalService, + ), + equals(['foo', 'foobar']), + ); + expect( + await autoCompleteResultsFor( + EditingParts(activeWord: 'b', leftSide: '', rightSide: ''), + evalService, + ), + equals(['bar', 'baz']), + ); + }, + timeout: const Timeout.factor(8), + ); - test( - 'returns filtered members when EditingParts is a field ', - () async { - await runMethodAndWaitForPause( - 'AnotherClass().pauseWithScopedVariablesMethod()', - ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: 'f', - leftSide: 'foo.', - rightSide: '', - ), - evalService, - ), - equals(['field1', 'field2', 'func1', 'func2']), - ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: 'fu', - leftSide: 'foo.', - rightSide: '', - ), - evalService, - ), - equals(['func1', 'func2']), - ); - }, - timeout: const Timeout.factor(8), - ); + test( + 'returns filtered members when EditingParts is a field ', + () async { + await runMethodAndWaitForPause( + 'AnotherClass().pauseWithScopedVariablesMethod()', + ); + expect( + await autoCompleteResultsFor( + EditingParts(activeWord: 'f', leftSide: 'foo.', rightSide: ''), + evalService, + ), + equals(['field1', 'field2', 'func1', 'func2']), + ); + expect( + await autoCompleteResultsFor( + EditingParts(activeWord: 'fu', leftSide: 'foo.', rightSide: ''), + evalService, + ), + equals(['func1', 'func2']), + ); + }, + timeout: const Timeout.factor(8), + ); - test( - 'returns filtered members when EditingParts is a class name ', - () async { - await runMethodAndWaitForPause( - 'AnotherClass().pauseWithScopedVariablesMethod()', - ); - expect( - await autoCompleteResultsFor( - EditingParts( - leftSide: 'FooClass.', - activeWord: '', - rightSide: '', - ), - evalService, + test( + 'returns filtered members when EditingParts is a class name ', + () async { + await runMethodAndWaitForPause( + 'AnotherClass().pauseWithScopedVariablesMethod()', + ); + expect( + await autoCompleteResultsFor( + EditingParts(leftSide: 'FooClass.', activeWord: '', rightSide: ''), + evalService, + ), + equals([ + 'staticField1', + 'staticField2', + 'namedConstructor', + 'factory1', + 'staticMethod', + ]), + ); + expect( + await autoCompleteResultsFor( + EditingParts( + activeWord: 'fa', + leftSide: 'FooClass.', + rightSide: '', ), - equals([ - 'staticField1', - 'staticField2', - 'namedConstructor', - 'factory1', - 'staticMethod', + evalService, + ), + equals(['factory1']), + ); + }, + timeout: const Timeout.factor(8), + ); + test( + 'returns privates only from library', + // TODO(https://github.com/flutter/devtools/issues/7099): unskip once + // this test flake is fixed. + skip: true, + () async { + await runMethodAndWaitForPause( + 'AnotherClass().pauseWithScopedVariablesMethod()', + ); + await expectLater( + autoCompleteResultsFor( + EditingParts(activeWord: '_', leftSide: '', rightSide: ''), + evalService, + ), + completion( + unorderedEquals([ + '_privateField2', + '_privateField1', + '_PrivateClass', ]), - ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: 'fa', - leftSide: 'FooClass.', - rightSide: '', - ), - evalService, - ), - equals(['factory1']), - ); - }, - timeout: const Timeout.factor(8), + ), + ); + }, + timeout: const Timeout.factor(8), + ); + test('returns exported members from import', () async { + await runMethodAndWaitForPause( + 'AnotherClass().pauseWithScopedVariablesMethod()', ); - test( - 'returns privates only from library', - // TODO(https://github.com/flutter/devtools/issues/7099): unskip once - // this test flake is fixed. - skip: true, - () async { - await runMethodAndWaitForPause( - 'AnotherClass().pauseWithScopedVariablesMethod()', - ); - await expectLater( - autoCompleteResultsFor( - EditingParts( - activeWord: '_', - leftSide: '', - rightSide: '', - ), - evalService, - ), - completion( - unorderedEquals( - [ - '_privateField2', - '_privateField1', - '_PrivateClass', - ], - ), - ), - ); - }, - timeout: const Timeout.factor(8), + expect( + await autoCompleteResultsFor( + EditingParts( + activeWord: 'exportedField', + leftSide: '', + rightSide: '', + ), + evalService, + ), + equals(['exportedField']), ); - test( - 'returns exported members from import', - () async { - await runMethodAndWaitForPause( - 'AnotherClass().pauseWithScopedVariablesMethod()', - ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: 'exportedField', - leftSide: '', - rightSide: '', - ), - evalService, - ), - equals([ - 'exportedField', - ]), - ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: 'ExportedClass', - leftSide: '', - rightSide: '', - ), - evalService, - ), - equals([ - 'ExportedClass', - ]), - ); + expect( + await autoCompleteResultsFor( + EditingParts( + activeWord: 'ExportedClass', + leftSide: '', + rightSide: '', + ), + evalService, + ), + equals(['ExportedClass']), + ); - // Privates are not exported - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: '_privateExportedField', - leftSide: '', - rightSide: '', - ), - evalService, - ), - equals([]), - ); + // Privates are not exported + expect( + await autoCompleteResultsFor( + EditingParts( + activeWord: '_privateExportedField', + leftSide: '', + rightSide: '', + ), + evalService, + ), + equals([]), + ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: '_PrivateExportedClass', - leftSide: '', - rightSide: '', - ), - evalService, - ), - equals([]), - ); - }, - timeout: const Timeout.factor(8), + expect( + await autoCompleteResultsFor( + EditingParts( + activeWord: '_PrivateExportedClass', + leftSide: '', + rightSide: '', + ), + evalService, + ), + equals([]), ); + }, timeout: const Timeout.factor(8)); - test( - 'returns prefixes of libraries imported', - () async { - await runMethodAndWaitForPause( - 'AnotherClass().pauseWithScopedVariablesMethod()', - ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: 'developer', - leftSide: '', - rightSide: '', - ), - evalService, - ), - equals([ - 'developer', - ]), - ); + test('returns prefixes of libraries imported', () async { + await runMethodAndWaitForPause( + 'AnotherClass().pauseWithScopedVariablesMethod()', + ); + expect( + await autoCompleteResultsFor( + EditingParts(activeWord: 'developer', leftSide: '', rightSide: ''), + evalService, + ), + equals(['developer']), + ); - expect( - await autoCompleteResultsFor( - EditingParts( - activeWord: 'math', - leftSide: '', - rightSide: '', - ), - evalService, - ), - equals([ - 'math', - ]), - ); - }, - timeout: const Timeout.factor(8), + expect( + await autoCompleteResultsFor( + EditingParts(activeWord: 'math', leftSide: '', rightSide: ''), + evalService, + ), + equals(['math']), ); + }, timeout: const Timeout.factor(8)); - test( - 'returns no operators for int', - () async { - await runMethodAndWaitForPause( - 'AnotherClass().pauseWithScopedVariablesMethod()', - ); - expect( - await autoCompleteResultsFor( - EditingParts( - leftSide: '7.', - activeWord: '', - rightSide: '', - ), - evalService, - ), - equals( - [ - 'hashCode', - 'bitLength', - 'toString', - 'remainder', - 'abs', - 'sign', - 'isEven', - 'isOdd', - 'isNaN', - 'isNegative', - 'isInfinite', - 'isFinite', - 'toUnsigned', - 'toSigned', - 'compareTo', - 'round', - 'floor', - 'ceil', - 'truncate', - 'roundToDouble', - 'floorToDouble', - 'ceilToDouble', - 'truncateToDouble', - 'clamp', - 'toInt', - 'toDouble', - 'toStringAsFixed', - 'toStringAsExponential', - 'toStringAsPrecision', - 'toRadixString', - 'modPow', - 'modInverse', - 'gcd', - 'noSuchMethod', - 'runtimeType', - ], - ), - ); - }, - timeout: const Timeout.factor(8), + test('returns no operators for int', () async { + await runMethodAndWaitForPause( + 'AnotherClass().pauseWithScopedVariablesMethod()', ); - }, - ); + expect( + await autoCompleteResultsFor( + EditingParts(leftSide: '7.', activeWord: '', rightSide: ''), + evalService, + ), + equals([ + 'hashCode', + 'bitLength', + 'toString', + 'remainder', + 'abs', + 'sign', + 'isEven', + 'isOdd', + 'isNaN', + 'isNegative', + 'isInfinite', + 'isFinite', + 'toUnsigned', + 'toSigned', + 'compareTo', + 'round', + 'floor', + 'ceil', + 'truncate', + 'roundToDouble', + 'floorToDouble', + 'ceilToDouble', + 'truncateToDouble', + 'clamp', + 'toInt', + 'toDouble', + 'toStringAsFixed', + 'toStringAsExponential', + 'toStringAsPrecision', + 'toRadixString', + 'modPow', + 'modInverse', + 'gcd', + 'noSuchMethod', + 'runtimeType', + ]), + ); + }, timeout: const Timeout.factor(8)); + }); } diff --git a/packages/devtools_app/test/debugger/debugger_floating_test.dart b/packages/devtools_app/test/debugger/debugger_floating_test.dart index ceb06eac404..23b2c618631 100644 --- a/packages/devtools_app/test/debugger/debugger_floating_test.dart +++ b/packages/devtools_app/test/debugger/debugger_floating_test.dart @@ -17,10 +17,12 @@ void main() { final debuggerController = createMockDebuggerControllerWithDefaults(); final scriptManager = MockScriptManager(); - when(fakeServiceConnection.serviceManager.connectedApp!.isProfileBuildNow) - .thenReturn(false); - when(fakeServiceConnection.serviceManager.connectedApp!.isDartWebAppNow) - .thenReturn(false); + when( + fakeServiceConnection.serviceManager.connectedApp!.isProfileBuildNow, + ).thenReturn(false); + when( + fakeServiceConnection.serviceManager.connectedApp!.isDartWebAppNow, + ).thenReturn(false); setGlobal(ServiceConnectionManager, fakeServiceConnection); setGlobal(IdeTheme, IdeTheme()); setGlobal(ScriptManager, scriptManager); @@ -51,10 +53,7 @@ void main() { final animatedOpacity = animatedOpacityFinder.evaluate().first.widget as AnimatedOpacity; expect(animatedOpacity.opacity, equals(1.0)); - expect( - find.text('Main isolate is paused in the debugger'), - findsOneWidget, - ); + expect(find.text('Main isolate is paused in the debugger'), findsOneWidget); expect(find.byTooltip('Resume'), findsOneWidget); expect(find.byTooltip('Step over'), findsOneWidget); }); diff --git a/packages/devtools_app/test/debugger/debugger_screen_breakpoints_test.dart b/packages/devtools_app/test/debugger/debugger_screen_breakpoints_test.dart index c849a02c890..849c2b0ded4 100644 --- a/packages/devtools_app/test/debugger/debugger_screen_breakpoints_test.dart +++ b/packages/devtools_app/test/debugger/debugger_screen_breakpoints_test.dart @@ -36,8 +36,9 @@ void main() { ); setGlobal(PreferencesController, PreferencesController()); fakeServiceConnection.consoleService.ensureServiceInitialized(); - when(fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger')) - .thenReturn(ValueNotifier(0)); + when( + fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger'), + ).thenReturn(ValueNotifier(0)); final debuggerController = createMockDebuggerControllerWithDefaults(); final breakpoints = [ @@ -60,10 +61,12 @@ void main() { ), ]; final codeViewController = debuggerController.codeViewController; - when(mockBreakpointManager.breakpoints) - .thenReturn(ValueNotifier(breakpoints)); - when(mockBreakpointManager.breakpointsWithLocation) - .thenReturn(ValueNotifier(breakpointsWithLocation)); + when( + mockBreakpointManager.breakpoints, + ).thenReturn(ValueNotifier(breakpoints)); + when( + mockBreakpointManager.breakpointsWithLocation, + ).thenReturn(ValueNotifier(breakpointsWithLocation)); when(scriptManager.sortedScripts).thenReturn(ValueNotifier([])); when(codeViewController.scriptLocation).thenReturn(ValueNotifier(null)); @@ -74,30 +77,25 @@ void main() { DebuggerController controller, ) async { await tester.pumpWidget( - wrapWithControllers( - const DebuggerWindows(), - debugger: controller, - ), + wrapWithControllers(const DebuggerWindows(), debugger: controller), ); } - testWidgetsWithWindowSize( - 'Breakpoints show items', - windowSize, - (WidgetTester tester) async { - await pumpDebuggerScreen(tester, debuggerController); + testWidgetsWithWindowSize('Breakpoints show items', windowSize, ( + WidgetTester tester, + ) async { + await pumpDebuggerScreen(tester, debuggerController); - expect(find.text('Breakpoints'), findsOneWidget); + expect(find.text('Breakpoints'), findsOneWidget); - // test for items in the breakpoint list - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is RichText && - widget.text.toPlainText().contains('script.dart:10'), - ), - findsOneWidget, - ); - }, - ); + // test for items in the breakpoint list + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is RichText && + widget.text.toPlainText().contains('script.dart:10'), + ), + findsOneWidget, + ); + }); } diff --git a/packages/devtools_app/test/debugger/debugger_screen_call_stack_test.dart b/packages/devtools_app/test/debugger/debugger_screen_call_stack_test.dart index 22ee58d7118..d2b2e95c29c 100644 --- a/packages/devtools_app/test/debugger/debugger_screen_call_stack_test.dart +++ b/packages/devtools_app/test/debugger/debugger_screen_call_stack_test.dart @@ -41,8 +41,9 @@ void main() { ); setGlobal(PreferencesController, PreferencesController()); fakeServiceConnection.consoleService.ensureServiceInitialized(); - when(fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger')) - .thenReturn(ValueNotifier(0)); + when( + fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger'), + ).thenReturn(ValueNotifier(0)); debuggerController = createMockDebuggerControllerWithDefaults(); }); @@ -51,173 +52,173 @@ void main() { DebuggerController controller, ) async { await tester.pumpWidget( - wrapWithControllers( - const DebuggerWindows(), - debugger: controller, - ), + wrapWithControllers(const DebuggerWindows(), debugger: controller), ); } - testWidgetsWithWindowSize( - 'Call Stack shows items', - windowSize, - (WidgetTester tester) async { - final stackFrames = [ - Frame( - index: 0, - code: CodeRef( - name: 'testCodeRef', - id: 'testCodeRef', - kind: CodeKind.kDart, - ), - location: SourceLocation( - script: - ScriptRef(uri: 'package:test/script.dart', id: 'script.dart'), - tokenPos: 10, - ), - kind: FrameKind.kRegular, + testWidgetsWithWindowSize('Call Stack shows items', windowSize, ( + WidgetTester tester, + ) async { + final stackFrames = [ + Frame( + index: 0, + code: CodeRef( + name: 'testCodeRef', + id: 'testCodeRef', + kind: CodeKind.kDart, ), - Frame( - index: 1, - location: SourceLocation( - script: - ScriptRef(uri: 'package:test/script1.dart', id: 'script1.dart'), - tokenPos: 10, - ), - kind: FrameKind.kRegular, + location: SourceLocation( + script: ScriptRef(uri: 'package:test/script.dart', id: 'script.dart'), + tokenPos: 10, ), - Frame( - index: 2, - code: CodeRef( - name: '[Unoptimized] testCodeRef2', - id: 'testCodeRef2', - kind: CodeKind.kDart, - ), - location: SourceLocation( - script: - ScriptRef(uri: 'package:test/script2.dart', id: 'script2.dart'), - tokenPos: 10, + kind: FrameKind.kRegular, + ), + Frame( + index: 1, + location: SourceLocation( + script: ScriptRef( + uri: 'package:test/script1.dart', + id: 'script1.dart', ), - kind: FrameKind.kRegular, + tokenPos: 10, ), - Frame( - index: 3, - code: CodeRef( - name: 'testCodeRef3.', - id: 'testCodeRef3.closure', - kind: CodeKind.kDart, - ), - location: SourceLocation( - script: - ScriptRef(uri: 'package:test/script3.dart', id: 'script3.dart'), - tokenPos: 10, + kind: FrameKind.kRegular, + ), + Frame( + index: 2, + code: CodeRef( + name: '[Unoptimized] testCodeRef2', + id: 'testCodeRef2', + kind: CodeKind.kDart, + ), + location: SourceLocation( + script: ScriptRef( + uri: 'package:test/script2.dart', + id: 'script2.dart', ), - kind: FrameKind.kRegular, + tokenPos: 10, + ), + kind: FrameKind.kRegular, + ), + Frame( + index: 3, + code: CodeRef( + name: 'testCodeRef3.', + id: 'testCodeRef3.closure', + kind: CodeKind.kDart, ), - Frame( - index: 4, - location: SourceLocation( - script: - ScriptRef(uri: 'package:test/script4.dart', id: 'script4.dart'), - tokenPos: 10, + location: SourceLocation( + script: ScriptRef( + uri: 'package:test/script3.dart', + id: 'script3.dart', ), - kind: FrameKind.kAsyncSuspensionMarker, + tokenPos: 10, ), - Frame( - index: 5, - code: CodeRef( - name: '_createTimer', - id: 'testJsCodeRefId', - kind: CodeKind.kNative, + kind: FrameKind.kRegular, + ), + Frame( + index: 4, + location: SourceLocation( + script: ScriptRef( + uri: 'package:test/script4.dart', + id: 'script4.dart', ), - location: SourceLocation( - script: ScriptRef( - uri: 'http://localhost:63691/dwds/src/injected/client.js', - id: 'jsScriptId', - ), - tokenPos: 12, + tokenPos: 10, + ), + kind: FrameKind.kAsyncSuspensionMarker, + ), + Frame( + index: 5, + code: CodeRef( + name: '_createTimer', + id: 'testJsCodeRefId', + kind: CodeKind.kNative, + ), + location: SourceLocation( + script: ScriptRef( + uri: 'http://localhost:63691/dwds/src/injected/client.js', + id: 'jsScriptId', ), - kind: FrameKind.kRegular, + tokenPos: 12, ), - ]; + kind: FrameKind.kRegular, + ), + ]; - final stackFramesWithLocation = - stackFrames.map((frame) { - return StackFrameAndSourcePosition( - frame, - position: SourcePosition( - line: stackFrames.indexOf(frame), - column: 10, - ), - ); - }).toList(); + final stackFramesWithLocation = + stackFrames.map((frame) { + return StackFrameAndSourcePosition( + frame, + position: SourcePosition( + line: stackFrames.indexOf(frame), + column: 10, + ), + ); + }).toList(); - when(debuggerController.stackFramesWithLocation) - .thenReturn(ValueNotifier(stackFramesWithLocation)); - final codeViewController = debuggerController.codeViewController; - when(codeViewController.showFileOpener).thenReturn(ValueNotifier(false)); - await pumpDebuggerScreen(tester, debuggerController); + when( + debuggerController.stackFramesWithLocation, + ).thenReturn(ValueNotifier(stackFramesWithLocation)); + final codeViewController = debuggerController.codeViewController; + when(codeViewController.showFileOpener).thenReturn(ValueNotifier(false)); + await pumpDebuggerScreen(tester, debuggerController); - expect(find.text('Call Stack'), findsOneWidget); + expect(find.text('Call Stack'), findsOneWidget); - // Stack frame 0 - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is RichText && - widget.text.toPlainText().contains('testCodeRef script.dart:0'), - ), - findsOneWidget, - ); + // Stack frame 0 + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is RichText && + widget.text.toPlainText().contains('testCodeRef script.dart:0'), + ), + findsOneWidget, + ); - // verify that the frame has a tooltip - expect( - find.byTooltip('testCodeRef script.dart:0'), - findsOneWidget, - ); + // verify that the frame has a tooltip + expect(find.byTooltip('testCodeRef script.dart:0'), findsOneWidget); - // Stack frame 1 - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is RichText && - widget.text.toPlainText().contains(' script1.dart:1'), - ), - findsOneWidget, - ); - // Stack frame 2 - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is RichText && - widget.text.toPlainText().contains('testCodeRef2 script2.dart:2'), - ), - findsOneWidget, - ); - // Stack frame 3 - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is RichText && - widget.text - .toPlainText() - .contains('testCodeRef3. script3.dart:3'), - ), - findsOneWidget, - ); - // Stack frame 4 - expect(find.text(''), findsOneWidget); - // Stack frame 5 - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is RichText && - widget.text - .toPlainText() - .contains(' client.js'), - ), - findsOneWidget, - ); - }, - ); + // Stack frame 1 + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is RichText && + widget.text.toPlainText().contains(' script1.dart:1'), + ), + findsOneWidget, + ); + // Stack frame 2 + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is RichText && + widget.text.toPlainText().contains('testCodeRef2 script2.dart:2'), + ), + findsOneWidget, + ); + // Stack frame 3 + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is RichText && + widget.text.toPlainText().contains( + 'testCodeRef3. script3.dart:3', + ), + ), + findsOneWidget, + ); + // Stack frame 4 + expect(find.text(''), findsOneWidget); + // Stack frame 5 + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is RichText && + widget.text.toPlainText().contains( + ' client.js', + ), + ), + findsOneWidget, + ); + }); } diff --git a/packages/devtools_app/test/debugger/debugger_screen_dap_variables_test.dart b/packages/devtools_app/test/debugger/debugger_screen_dap_variables_test.dart index 275e9aa6130..389c77f7365 100644 --- a/packages/devtools_app/test/debugger/debugger_screen_dap_variables_test.dart +++ b/packages/devtools_app/test/debugger/debugger_screen_dap_variables_test.dart @@ -45,15 +45,14 @@ void main() { ); setGlobal(PreferencesController, PreferencesController()); fakeServiceConnection.consoleService.ensureServiceInitialized(); - when(fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger')) - .thenReturn(ValueNotifier(0)); + when( + fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger'), + ).thenReturn(ValueNotifier(0)); debuggerController = createMockDebuggerControllerWithDefaults(); }); tearDown(() { - fakeServiceConnection.appState.setDapVariables( - [], - ); + fakeServiceConnection.appState.setDapVariables([]); }); Future pumpDebuggerScreen( @@ -61,90 +60,75 @@ void main() { DebuggerController controller, ) async { await tester.pumpWidget( - wrapWithControllers( - const DebuggerWindows(), - debugger: controller, - ), + wrapWithControllers(const DebuggerWindows(), debugger: controller), ); } - testWidgetsWithWindowSize( - 'Shows non-expandable variables', - windowSize, - (WidgetTester tester) async { - final node = DapObjectNode( - service: vmService, - variable: dap.Variable( - name: 'myInt', - value: '10', - variablesReference: 0, - ), - ); + testWidgetsWithWindowSize('Shows non-expandable variables', windowSize, ( + WidgetTester tester, + ) async { + final node = DapObjectNode( + service: vmService, + variable: dap.Variable(name: 'myInt', value: '10', variablesReference: 0), + ); - fakeServiceConnection.appState.setDapVariables( - [node], - ); - await pumpDebuggerScreen(tester, debuggerController); - expect(find.text('Variables'), findsOneWidget); - - // Variables should include the int. - final intFinder = find.text('myInt: 10'); - expect(intFinder, findsOneWidget); - - // The int is not expandable. - final expandArrowFinder = find.byIcon(Icons.keyboard_arrow_down); - expect(expandArrowFinder, findsNothing); - }, - ); - - testWidgetsWithWindowSize( - 'Shows expandable variables', - windowSize, - (WidgetTester tester) async { - when(vmService.dapVariablesRequest(any)).thenAnswer((_) async { - return dap.VariablesResponseBody( - variables: [ - dap.Variable( - name: 'myString', - value: '"myString"', - variablesReference: 0, - ), - ], - ); - }); - - final node = DapObjectNode( - service: vmService, - variable: dap.Variable( - name: 'myList', - value: 'List (1 item)', - variablesReference: 1, - ), - ); - await node.fetchChildren(); + fakeServiceConnection.appState.setDapVariables([node]); + await pumpDebuggerScreen(tester, debuggerController); + expect(find.text('Variables'), findsOneWidget); + + // Variables should include the int. + final intFinder = find.text('myInt: 10'); + expect(intFinder, findsOneWidget); + + // The int is not expandable. + final expandArrowFinder = find.byIcon(Icons.keyboard_arrow_down); + expect(expandArrowFinder, findsNothing); + }); - fakeServiceConnection.appState.setDapVariables( - [node], + testWidgetsWithWindowSize('Shows expandable variables', windowSize, ( + WidgetTester tester, + ) async { + when(vmService.dapVariablesRequest(any)).thenAnswer((_) async { + return dap.VariablesResponseBody( + variables: [ + dap.Variable( + name: 'myString', + value: '"myString"', + variablesReference: 0, + ), + ], ); - await pumpDebuggerScreen(tester, debuggerController); - expect(find.text('Variables'), findsOneWidget); - - // Variables should include the list. - final listFinder = find.text('myList: List (1 item)'); - expect(listFinder, findsOneWidget); - - // Initially the string is not visible. - final stringFinder = find.text('myString: "myString"'); - expect(stringFinder, findsNothing); - - // Expand the list. - final expandArrowFinder = find.byIcon(Icons.keyboard_arrow_down); - expect(expandArrowFinder, findsOneWidget); - await tester.tap(expandArrowFinder.first); - await tester.pump(); - - // String is now visible. - expect(stringFinder, findsOneWidget); - }, - ); + }); + + final node = DapObjectNode( + service: vmService, + variable: dap.Variable( + name: 'myList', + value: 'List (1 item)', + variablesReference: 1, + ), + ); + await node.fetchChildren(); + + fakeServiceConnection.appState.setDapVariables([node]); + await pumpDebuggerScreen(tester, debuggerController); + expect(find.text('Variables'), findsOneWidget); + + // Variables should include the list. + final listFinder = find.text('myList: List (1 item)'); + expect(listFinder, findsOneWidget); + + // Initially the string is not visible. + final stringFinder = find.text('myString: "myString"'); + expect(stringFinder, findsNothing); + + // Expand the list. + final expandArrowFinder = find.byIcon(Icons.keyboard_arrow_down); + expect(expandArrowFinder, findsOneWidget); + await tester.tap(expandArrowFinder.first); + await tester.pump(); + + // String is now visible. + expect(stringFinder, findsOneWidget); + }); } diff --git a/packages/devtools_app/test/debugger/debugger_screen_explorer_visibility_test.dart b/packages/devtools_app/test/debugger/debugger_screen_explorer_visibility_test.dart index c4073220ba1..83a728373ef 100644 --- a/packages/devtools_app/test/debugger/debugger_screen_explorer_visibility_test.dart +++ b/packages/devtools_app/test/debugger/debugger_screen_explorer_visibility_test.dart @@ -23,104 +23,94 @@ void main() { ScriptRef(uri: 'package:test/script.dart', id: 'test-script'), ]; - group( - 'FileExplorer', - () { - setUp(() { - fakeServiceConnection = FakeServiceConnectionManager(); - scriptManager = MockScriptManager(); - mockConnectedApp( - fakeServiceConnection.serviceManager.connectedApp!, - isFlutterApp: true, - isProfileBuild: false, - isWebApp: false, - ); - setGlobal(ServiceConnectionManager, fakeServiceConnection); - setGlobal(IdeTheme, IdeTheme()); - setGlobal(NotificationService, NotificationService()); - setGlobal(ScriptManager, scriptManager); - setGlobal(BreakpointManager, BreakpointManager()); - setGlobal( - DevToolsEnvironmentParameters, - ExternalDevToolsEnvironmentParameters(), - ); - setGlobal(PreferencesController, PreferencesController()); - fakeServiceConnection.consoleService.ensureServiceInitialized(); - when( - fakeServiceConnection.errorBadgeManager - .errorCountNotifier('debugger'), - ).thenReturn(ValueNotifier(0)); - final mockProgramExplorerController = - createMockProgramExplorerControllerWithDefaults(); - mockCodeViewController = createMockCodeViewControllerWithDefaults( - programExplorerController: mockProgramExplorerController, - ); - debuggerController = createMockDebuggerControllerWithDefaults( - codeViewController: mockCodeViewController, - ); + group('FileExplorer', () { + setUp(() { + fakeServiceConnection = FakeServiceConnectionManager(); + scriptManager = MockScriptManager(); + mockConnectedApp( + fakeServiceConnection.serviceManager.connectedApp!, + isFlutterApp: true, + isProfileBuild: false, + isWebApp: false, + ); + setGlobal(ServiceConnectionManager, fakeServiceConnection); + setGlobal(IdeTheme, IdeTheme()); + setGlobal(NotificationService, NotificationService()); + setGlobal(ScriptManager, scriptManager); + setGlobal(BreakpointManager, BreakpointManager()); + setGlobal( + DevToolsEnvironmentParameters, + ExternalDevToolsEnvironmentParameters(), + ); + setGlobal(PreferencesController, PreferencesController()); + fakeServiceConnection.consoleService.ensureServiceInitialized(); + when( + fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger'), + ).thenReturn(ValueNotifier(0)); + final mockProgramExplorerController = + createMockProgramExplorerControllerWithDefaults(); + mockCodeViewController = createMockCodeViewControllerWithDefaults( + programExplorerController: mockProgramExplorerController, + ); + debuggerController = createMockDebuggerControllerWithDefaults( + codeViewController: mockCodeViewController, + ); - when(scriptManager.sortedScripts).thenReturn(ValueNotifier(scripts)); + when(scriptManager.sortedScripts).thenReturn(ValueNotifier(scripts)); - when(mockProgramExplorerController.rootObjectNodes).thenReturn( - ValueNotifier( - [ - VMServiceObjectNode( - mockCodeViewController.programExplorerController, - 'package:test', - null, - ), - ], + when(mockProgramExplorerController.rootObjectNodes).thenReturn( + ValueNotifier([ + VMServiceObjectNode( + mockCodeViewController.programExplorerController, + 'package:test', + null, ), - ); - when(mockCodeViewController.showFileOpener) - .thenReturn(ValueNotifier(false)); - }); + ]), + ); + when( + mockCodeViewController.showFileOpener, + ).thenReturn(ValueNotifier(false)); + }); - Future pumpDebuggerScreen( - WidgetTester tester, - DebuggerController controller, - ) async { - await tester.pumpWidget( - wrapWithControllers( - DebuggerSourceAndControls( - shownFirstScript: () => true, - setShownFirstScript: (_) {}, - ), - debugger: controller, + Future pumpDebuggerScreen( + WidgetTester tester, + DebuggerController controller, + ) async { + await tester.pumpWidget( + wrapWithControllers( + DebuggerSourceAndControls( + shownFirstScript: () => true, + setShownFirstScript: (_) {}, ), - ); - } + debugger: controller, + ), + ); + } - testWidgetsWithWindowSize( - 'visible', - windowSize, - (WidgetTester tester) async { - // File Explorer view is shown - when(mockCodeViewController.fileExplorerVisible) - .thenReturn(ValueNotifier(true)); - await pumpDebuggerScreen(tester, debuggerController); - // One for the button and one for the title of the File Explorer view. - expect(find.text('File Explorer'), findsNWidgets(2)); + testWidgetsWithWindowSize('visible', windowSize, ( + WidgetTester tester, + ) async { + // File Explorer view is shown + when( + mockCodeViewController.fileExplorerVisible, + ).thenReturn(ValueNotifier(true)); + await pumpDebuggerScreen(tester, debuggerController); + // One for the button and one for the title of the File Explorer view. + expect(find.text('File Explorer'), findsNWidgets(2)); - // test for items in the libraries tree - expect( - find.text(scripts.first.uri!.split('/').first), - findsOneWidget, - ); - }, - ); + // test for items in the libraries tree + expect(find.text(scripts.first.uri!.split('/').first), findsOneWidget); + }); - testWidgetsWithWindowSize( - 'hidden', - windowSize, - (WidgetTester tester) async { - // File Explorer view is hidden - when(mockCodeViewController.fileExplorerVisible) - .thenReturn(ValueNotifier(false)); - await pumpDebuggerScreen(tester, debuggerController); - expect(find.text('File Explorer'), findsOneWidget); - }, - ); - }, - ); + testWidgetsWithWindowSize('hidden', windowSize, ( + WidgetTester tester, + ) async { + // File Explorer view is hidden + when( + mockCodeViewController.fileExplorerVisible, + ).thenReturn(ValueNotifier(false)); + await pumpDebuggerScreen(tester, debuggerController); + expect(find.text('File Explorer'), findsOneWidget); + }); + }); } diff --git a/packages/devtools_app/test/debugger/debugger_screen_paused_test.dart b/packages/devtools_app/test/debugger/debugger_screen_paused_test.dart index 55f65f6e664..897c4f2f9aa 100644 --- a/packages/devtools_app/test/debugger/debugger_screen_paused_test.dart +++ b/packages/devtools_app/test/debugger/debugger_screen_paused_test.dart @@ -47,23 +47,23 @@ void main() { ); setGlobal(PreferencesController, PreferencesController()); fakeServiceConnection.consoleService.ensureServiceInitialized(); - when(fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger')) - .thenReturn(ValueNotifier(0)); + when( + fakeServiceConnection.errorBadgeManager.errorCountNotifier('debugger'), + ).thenReturn(ValueNotifier(0)); debuggerController = createMockDebuggerControllerWithDefaults(); final codeViewController = debuggerController.codeViewController; final scriptsHistory = ScriptsHistory(); scriptsHistory.pushEntry(mockScript!); when(codeViewController.scriptsHistory).thenReturn(scriptsHistory); - when(debuggerController.stackFramesWithLocation).thenReturn( - ValueNotifier([ - _stackFrame1, - _stackFrame2, - ]), - ); - when(codeViewController.currentScriptRef) - .thenReturn(ValueNotifier(mockScriptRef)); - when(codeViewController.currentParsedScript) - .thenReturn(ValueNotifier(mockParsedScript)); + when( + debuggerController.stackFramesWithLocation, + ).thenReturn(ValueNotifier([_stackFrame1, _stackFrame2])); + when( + codeViewController.currentScriptRef, + ).thenReturn(ValueNotifier(mockScriptRef)); + when( + codeViewController.currentParsedScript, + ).thenReturn(ValueNotifier(mockParsedScript)); when(codeViewController.navigationInProgress).thenReturn(false); }); @@ -79,55 +79,50 @@ void main() { ); } - testWidgetsWithWindowSize( - 'debugger controls paused', - windowSize, - (WidgetTester tester) async { - await pumpDebuggerScreen(tester); + testWidgetsWithWindowSize('debugger controls paused', windowSize, ( + WidgetTester tester, + ) async { + await pumpDebuggerScreen(tester); - (serviceConnection.serviceManager.isolateManager as FakeIsolateManager) - .setMainIsolatePausedState(true); - await tester.pump(); + (serviceConnection.serviceManager.isolateManager as FakeIsolateManager) + .setMainIsolatePausedState(true); + await tester.pump(); - expect( - findDebuggerButtonWithIcon(Codicons.debugPause), - findsOneWidget, - ); - final pause = getWidgetFromFinder( - findDebuggerButtonWithIcon(Codicons.debugPause), - ); - expect(pause.onPressed, isNull); + expect(findDebuggerButtonWithIcon(Codicons.debugPause), findsOneWidget); + final pause = getWidgetFromFinder( + findDebuggerButtonWithIcon(Codicons.debugPause), + ); + expect(pause.onPressed, isNull); - expect( - findDebuggerButtonWithIcon(Codicons.debugContinue), - findsOneWidget, - ); - final resume = getWidgetFromFinder( - findDebuggerButtonWithIcon(Codicons.debugContinue), - ); - expect(resume.onPressed, isNotNull); - }, - ); + expect(findDebuggerButtonWithIcon(Codicons.debugContinue), findsOneWidget); + final resume = getWidgetFromFinder( + findDebuggerButtonWithIcon(Codicons.debugContinue), + ); + expect(resume.onPressed, isNotNull); + }); testWidgetsWithWindowSize( 'selecting stackframe scrolls the frame location into view', windowSize, (WidgetTester tester) async { final stackFrameNotifier = ValueNotifier(_stackFrame1); - when(debuggerController.selectedStackFrame) - .thenReturn(stackFrameNotifier); + when( + debuggerController.selectedStackFrame, + ).thenReturn(stackFrameNotifier); await pumpDebuggerScreen(tester); await tester.pumpAndSettle(); // The first stack frame is visible: - final firstStackFrame = - findStackFrameWithText('firstCodeRef main.dart:1'); + final firstStackFrame = findStackFrameWithText( + 'firstCodeRef main.dart:1', + ); expect(firstStackFrame, findsOneWidget); // The second stack frame is visible: - final secondStackFrame = - findStackFrameWithText('secondCodeRef main.dart:85'); + final secondStackFrame = findStackFrameWithText( + 'secondCodeRef main.dart:85', + ); expect(secondStackFrame, findsOneWidget); // The first stack frame's line is visible: @@ -159,9 +154,7 @@ final _stackFrame1 = StackFrameAndSourcePosition( id: 'firstCodeRef', kind: CodeKind.kDart, ), - location: SourceLocation( - script: mockScriptRef, - ), + location: SourceLocation(script: mockScriptRef), kind: FrameKind.kRegular, ), position: const SourcePosition(line: _stackFrame1Line, column: 1), @@ -177,25 +170,25 @@ final _stackFrame2 = StackFrameAndSourcePosition( id: 'secondCodeRef', kind: CodeKind.kDart, ), - location: SourceLocation( - script: mockScriptRef, - ), + location: SourceLocation(script: mockScriptRef), kind: FrameKind.kRegular, ), position: const SourcePosition(line: _stackFrame2Line, column: 1), ); Finder findStackFrameWithText(String text) => find.byWidgetPredicate( - (Widget widget) => - widget is RichText && widget.text.toPlainText().contains(text), - ); + (Widget widget) => + widget is RichText && widget.text.toPlainText().contains(text), +); bool gutterItemForLineIsVisible(int lineNumber) { final gutterItems = find.byType(GutterItem); final firstGutterItem = getWidgetFromFinder(gutterItems.first); final lastGutterItem = getWidgetFromFinder(gutterItems.last); - final lineRange = - Range(firstGutterItem.lineNumber, lastGutterItem.lineNumber); + final lineRange = Range( + firstGutterItem.lineNumber, + lastGutterItem.lineNumber, + ); return lineRange.contains(lineNumber); } diff --git a/packages/devtools_app/test/debugger/debugger_screen_test.dart b/packages/devtools_app/test/debugger/debugger_screen_test.dart index 8e8f3a1a6c4..de473d5f11c 100644 --- a/packages/devtools_app/test/debugger/debugger_screen_test.dart +++ b/packages/devtools_app/test/debugger/debugger_screen_test.dart @@ -34,9 +34,9 @@ void main() { setUp(() async { final fakeServiceConnection = FakeServiceConnectionManager(); final scriptManager = MockScriptManager(); - when(scriptManager.getScript(any)).thenAnswer( - (_) => Future