diff --git a/analysis_options.yaml b/analysis_options.yaml index 110a84eb9dc..0a80ce17770 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,7 +1,4 @@ analyzer: - #strong-mode: - #implicit-casts: false # 367 issues - #implicit-dynamic: false # 169 issues #language: #strict-inference: true # 34 issues #strict-raw-types: true # 103 issues @@ -144,3 +141,96 @@ linter: # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review - valid_regexps # - void_checks # not yet tested + +dart_code_metrics: + metrics: + cyclomatic-complexity: 20 + number-of-parameters: 4 + maximum-nesting-level: 5 + metrics-exclude: + - test/** + rules: +# - arguments-ordering Too strict + - avoid-banned-imports + - avoid-cascade-after-if-null + - avoid-collection-methods-with-unrelated-types + - avoid-duplicate-exports + - avoid-dynamic +# - avoid-global-state TODO(jacobr): bunch of false positives around boolean flags. +# - avoid-ignoring-return-values +# - avoid-late-keyword + - avoid-missing-enum-constant-in-map + - avoid-nested-conditional-expressions +# - avoid-non-ascii-symbols TODO(jacobr): probably worth enabling. +# - avoid-non-null-assertion +# - avoid-passing-async-when-sync-expected TODO(jacobr): consider re-enabliing. + - avoid-redundant-async + - avoid-throw-in-catch-block + +# - avoid-top-level-members-in-tests Doesn't seem to match our style. + - avoid-unnecessary-type-assertions + - avoid-unnecessary-type-casts + - avoid-unrelated-type-assertions + - avoid-unused-parameters + - ban-name + # - binary-expression-operand-order Some nice catches but too many false positives to enable. + - double-literal-format + # - format-comment TODO(jacobr): enable this one after fixing violations. + # TODO(jacobr): enable member-ordering. This catches a bunch of real style + # issues but would be alot of work to migrate. + # - member-ordering + # - newline-before-return TODO(jacobr): should be in the formatter if it was a rule to adopt. + - no-boolean-literal-compare + # - no-empty-block Too many false positives. However it does flag a bunch of code smells so possibly worth re-enabling. + # This one seems interesting but has too many false positives. Gave it a try. + # - no-equal-arguments: + # ignored-parameters: + # - height + # - width + # - double-literal-format + # - defaultSortColumn + # - left + # - right + # - top + # - bottom + # - bottomLeft + # - topLeft + # - enabledBorder + - no-equal-then-else + # - no-magic-number + # - no-object-declaration Too difficult to use along with avoiding dynamic particular for JSON decoding logic. + # - prefer-async-await TODO(jacobr): evaluate enabling. + - prefer-commenting-analyzer-ignores + # - prefer-conditional-expressions Too many false positives involving large conditional expressions. + # - prefer-correct-identifier-length Too many false positives with fine names like i and id. + # - prefer-correct-test-file-name TODO(jacobr): enable and fix violations. + - prefer-correct-type-name + # - prefer-enums-by-name Cannot able unless lint adds a special case for orElse + # - prefer-first TODO(jacobr): enable as a follow up PR. + # - prefer-immediate-return TODO(jacobr): enable as a follow up PR. + - prefer-iterable-of + - prefer-last + # - prefer-match-file-name + # TODO(jacobr): consider enabling or enabling to periodically audit. + # This one has a lot of false positives but is also quite nice. + # - prefer-moving-to-variable: + # allowed-duplicated-chains: 2 + # - prefer-static-class + # TODO(jacobr): enable this one as a follow up CL. This one has a lot + # of violations but generally the style is aligned with DevTools. + # - prefer-trailing-comma + - tag-name + - 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. + - avoid-shrink-wrap-in-lists + - avoid-unnecessary-setstate + - avoid-expanded-as-spacer + - avoid-wrapping-in-padding + - check-for-equals-in-render-object-setters + - consistent-update-render-object + # - prefer-const-border-radius TODO(jacobr): enable. + - prefer-correct-edge-insets-constructor + # - prefer-extracting-callbacks I'm not clear this is always a good idea. Seems like a workaround. + # - prefer-single-widget-per-file + - prefer-using-list-view \ No newline at end of file diff --git a/packages/devtools_app/analysis_options.yaml b/packages/devtools_app/analysis_options.yaml index 923a2719f6b..b90b4817ad2 100644 --- a/packages/devtools_app/analysis_options.yaml +++ b/packages/devtools_app/analysis_options.yaml @@ -10,3 +10,8 @@ analyzer: # these files if you want to ensure code is not invalid except where # expected. - test/test_infra/test_data/syntax_highlighting/** + +dart_code_metrics: + metrics-exclude: + - test/** + - test/test_infra/test_data/** diff --git a/packages/devtools_app/integration_test/test_infra/test_app_driver.dart b/packages/devtools_app/integration_test/test_infra/test_app_driver.dart index bb0e15607e8..380893aa1ac 100644 --- a/packages/devtools_app/integration_test/test_infra/test_app_driver.dart +++ b/packages/devtools_app/integration_test/test_infra/test_app_driver.dart @@ -109,7 +109,7 @@ abstract class _TestApp with IOMixin { await started; } - Future killGracefully() async { + Future killGracefully() { _debugPrint('Sending SIGTERM to $runProcessId..'); Process.killPid(runProcessId); @@ -119,7 +119,7 @@ abstract class _TestApp with IOMixin { return killFuture; } - Future _killForcefully() async { + Future _killForcefully() { _debugPrint('Sending SIGKILL to $runProcessId..'); Process.killPid(runProcessId, ProcessSignal.sigkill); @@ -141,7 +141,7 @@ abstract class _TestApp with IOMixin { int? id, Duration? timeout, bool ignoreAppStopEvent = false, - }) async { + }) { final response = Completer>(); late StreamSubscription sub; sub = stdoutController.stream.listen( diff --git a/packages/devtools_app/lib/src/app.dart b/packages/devtools_app/lib/src/app.dart index 7543582474c..954e1547a13 100644 --- a/packages/devtools_app/lib/src/app.dart +++ b/packages/devtools_app/lib/src/app.dart @@ -112,21 +112,21 @@ class DevToolsAppState extends State with AutoDisposeMixin { }); _isDarkThemeEnabled = preferences.darkModeTheme.value; - preferences.darkModeTheme.addListener(() { + addAutoDisposeListener(preferences.darkModeTheme, () { setState(() { _isDarkThemeEnabled = preferences.darkModeTheme.value; }); }); _vmDeveloperModeEnabled = preferences.vmDeveloperModeEnabled.value; - preferences.vmDeveloperModeEnabled.addListener(() { + addAutoDisposeListener(preferences.vmDeveloperModeEnabled, () { setState(() { _vmDeveloperModeEnabled = preferences.vmDeveloperModeEnabled.value; }); }); _denseModeEnabled = preferences.denseModeEnabled.value; - preferences.denseModeEnabled.addListener(() { + addAutoDisposeListener(preferences.denseModeEnabled, () { setState(() { _denseModeEnabled = preferences.denseModeEnabled.value; }); @@ -191,10 +191,10 @@ class DevToolsAppState extends State with AutoDisposeMixin { } Widget _buildTabbedPage( - BuildContext context, + BuildContext _, String? page, Map params, - DevToolsNavigationState? state, + DevToolsNavigationState? __, ) { final vmServiceUri = params['uri']; @@ -234,7 +234,8 @@ class DevToolsAppState extends State with AutoDisposeMixin { .where((p) => !hide.contains(p.screenId)) .toList(); if (screens.isEmpty) return child ?? const SizedBox.shrink(); - return _providedControllers( + return MultiProvider( + providers: _providedControllers(), child: DevToolsScaffold( embed: embed, ideTheme: ideTheme, @@ -277,8 +278,8 @@ class DevToolsAppState extends State with AutoDisposeMixin { return DevToolsScaffold.withChild( key: UniqueKey(), ideTheme: ideTheme, - child: _providedControllers( - offline: true, + child: MultiProvider( + providers: _providedControllers(offline: true), child: SnapshotScreenBody(snapshotArgs, _screens), ), ); @@ -292,7 +293,8 @@ class DevToolsAppState extends State with AutoDisposeMixin { ReportFeedbackButton(), OpenAboutAction(), ], - child: _providedControllers( + child: MultiProvider( + providers: _providedControllers(), child: const AppSizeBody(), ), ); @@ -308,18 +310,13 @@ class DevToolsAppState extends State with AutoDisposeMixin { List _visibleScreens() => _screens.where(shouldShowScreen).toList(); - Widget _providedControllers({required Widget child, bool offline = false}) { - final _providers = widget.screens + List _providedControllers({bool offline = false}) { + return widget.screens .where( (s) => s.providesController && (offline ? s.supportsOffline : true), ) .map((s) => s.controllerProvider(routerDelegate)) .toList(); - - return MultiProvider( - providers: _providers, - child: child, - ); } @override @@ -456,7 +453,7 @@ class OpenSettingsAction extends StatelessWidget { return DevToolsTooltip( message: 'Settings', child: InkWell( - onTap: () async { + onTap: () { unawaited( showDialog( context: context, @@ -505,7 +502,8 @@ class SettingsDialog extends StatelessWidget { CheckboxSetting( label: const Text('Enable analytics'), listenable: analyticsController.analyticsEnabled, - toggle: analyticsController.toggleAnalyticsEnabled, + toggle: (enable) => + unawaited(analyticsController.toggleAnalyticsEnabled(enable)), gaItem: gac.analytics, ), CheckboxSetting( @@ -537,7 +535,7 @@ class CheckboxSetting extends StatelessWidget { final ValueListenable listenable; - final Function(bool) toggle; + final void Function(bool) toggle; final String gaItem; diff --git a/packages/devtools_app/lib/src/framework/about_dialog.dart b/packages/devtools_app/lib/src/framework/about_dialog.dart index e36f067722d..3cf3b1cf595 100644 --- a/packages/devtools_app/lib/src/framework/about_dialog.dart +++ b/packages/devtools_app/lib/src/framework/about_dialog.dart @@ -140,7 +140,7 @@ class OpenAboutAction extends StatelessWidget { return DevToolsTooltip( message: 'About DevTools', child: InkWell( - onTap: () async { + onTap: () { unawaited( showDialog( context: context, 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 0c4fbeb8c0a..4ad192ff585 100644 --- a/packages/devtools_app/lib/src/framework/app_error_handling.dart +++ b/packages/devtools_app/lib/src/framework/app_error_handling.dart @@ -21,7 +21,9 @@ import '../shared/config_specific/logger/logger.dart'; /// application. void setupErrorHandling(Future Function() appStartCallback) { // First, run all our code in a new zone. - return runZonedGuarded(() async { + return runZonedGuarded( + // ignore: avoid-passing-async-when-sync-expected this ignore should be fixed. + () async { WidgetsFlutterBinding.ensureInitialized(); final FlutterExceptionHandler? oldHandler = FlutterError.onError; diff --git a/packages/devtools_app/lib/src/framework/framework_core.dart b/packages/devtools_app/lib/src/framework/framework_core.dart index 08df171bc04..7c4fd89cc4f 100644 --- a/packages/devtools_app/lib/src/framework/framework_core.dart +++ b/packages/devtools_app/lib/src/framework/framework_core.dart @@ -19,8 +19,9 @@ import '../shared/primitives/utils.dart'; import '../shared/scripts/script_manager.dart'; import '../shared/survey.dart'; -typedef ErrorReporter = void Function(String title, dynamic error); +typedef ErrorReporter = void Function(String title, Object error); +// TODO(jacobr): refactor this class to not use static members. // ignore: avoid_classes_with_only_static_members class FrameworkCore { static void initGlobals() { diff --git a/packages/devtools_app/lib/src/framework/landing_screen.dart b/packages/devtools_app/lib/src/framework/landing_screen.dart index 1e1cc8fcc67..71df6b77729 100644 --- a/packages/devtools_app/lib/src/framework/landing_screen.dart +++ b/packages/devtools_app/lib/src/framework/landing_screen.dart @@ -130,29 +130,9 @@ class _ConnectDialogState extends State @override Widget build(BuildContext context) { - return LandingScreenSection( - title: 'Connect', - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Connect to a Running App', - style: Theme.of(context).textTheme.titleMedium, - ), - const SizedBox(height: denseRowSpacing), - Text( - 'Enter a URL to a running Dart or Flutter application', - style: Theme.of(context).textTheme.bodySmall, - ), - const Padding(padding: EdgeInsets.only(top: 20.0)), - _buildConnectInput(), - ], - ), - ); - } + final textTheme = Theme.of(context).textTheme; - Widget _buildConnectInput() { - return Column( + final connectorInput = Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( @@ -177,7 +157,7 @@ class _ConnectDialogState extends State ), const SizedBox(width: defaultSpacing), ElevatedButton( - onPressed: actionInProgress ? null : _connect, + onPressed: actionInProgress ? null : () => unawaited(_connect()), child: const Text('Connect'), ), ], @@ -192,6 +172,26 @@ class _ConnectDialogState extends State ), ], ); + + return LandingScreenSection( + title: 'Connect', + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Connect to a Running App', + style: textTheme.titleMedium, + ), + const SizedBox(height: denseRowSpacing), + Text( + 'Enter a URL to a running Dart or Flutter application', + style: textTheme.bodySmall, + ), + const Padding(padding: EdgeInsets.only(top: 20.0)), + connectorInput, + ], + ), + ); } Future _connect() async { @@ -251,6 +251,7 @@ class ImportFileInstructions extends StatelessWidget { @override Widget build(BuildContext context) { + final textTheme = Theme.of(context).textTheme; return LandingScreenSection( title: 'Load DevTools Data', child: Column( @@ -258,13 +259,13 @@ class ImportFileInstructions extends StatelessWidget { children: [ Text( 'Import a data file to use DevTools without an app connection.', - style: Theme.of(context).textTheme.titleMedium, + style: textTheme.titleMedium, ), const SizedBox(height: denseRowSpacing), Text( 'At this time, DevTools only supports importing files that were originally' ' exported from DevTools.', - style: Theme.of(context).textTheme.bodySmall, + style: textTheme.bodySmall, ), const SizedBox(height: defaultSpacing), ElevatedButton( @@ -300,6 +301,7 @@ class AppSizeToolingInstructions extends StatelessWidget { @override Widget build(BuildContext context) { + final textTheme = Theme.of(context).textTheme; return LandingScreenSection( title: 'App Size Tooling', child: Column( @@ -307,13 +309,13 @@ class AppSizeToolingInstructions extends StatelessWidget { children: [ Text( 'Analyze and view diffs for your app\'s size', - style: Theme.of(context).textTheme.titleMedium, + style: textTheme.titleMedium, ), const SizedBox(height: denseRowSpacing), Text( 'Load Dart AOT snapshots or app size analysis files to ' 'track down size issues in your app.', - style: Theme.of(context).textTheme.bodySmall, + style: textTheme.bodySmall, ), const SizedBox(height: defaultSpacing), ElevatedButton( diff --git a/packages/devtools_app/lib/src/framework/notifications_view.dart b/packages/devtools_app/lib/src/framework/notifications_view.dart index 9272834f58e..7a3dfabf388 100644 --- a/packages/devtools_app/lib/src/framework/notifications_view.dart +++ b/packages/devtools_app/lib/src/framework/notifications_view.dart @@ -64,7 +64,7 @@ class _NotificationsState extends State<_Notifications> with AutoDisposeMixin { if (_overlayEntry == null) { _overlayEntry = OverlayEntry( maintainState: true, - builder: _buildOverlay, + builder: (_) => _NotificationOverlay(notifications: _notifications), ); SchedulerBinding.instance.scheduleFrameCallback((_) { Overlay.of(context).insert(_overlayEntry!); @@ -114,7 +114,7 @@ class _NotificationsState extends State<_Notifications> with AutoDisposeMixin { bool didDismiss = false; // Make a copy so we do not remove a notification from [_notifications] // while iterating over it. - final notifications = List<_Notification>.from(_notifications); + final notifications = List<_Notification>.of(_notifications); for (final notification in notifications) { if (notification.message.text == message) { _notifications.remove(notification); @@ -139,7 +139,21 @@ class _NotificationsState extends State<_Notifications> with AutoDisposeMixin { }); } - Widget _buildOverlay(BuildContext context) { + @override + Widget build(BuildContext context) { + return widget.child; + } +} + +class _NotificationOverlay extends StatelessWidget { + const _NotificationOverlay({ + required List<_Notification> notifications, + }) : _notifications = notifications; + + final List<_Notification> _notifications; + + @override + Widget build(BuildContext context) { return Align( alignment: Alignment.bottomRight, child: Padding( @@ -162,11 +176,6 @@ class _NotificationsState extends State<_Notifications> with AutoDisposeMixin { ), ); } - - @override - Widget build(BuildContext context) { - return widget.child; - } } class _Notification extends StatefulWidget { @@ -245,9 +254,9 @@ class _NotificationState extends State<_Notification> child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildMessage(), + _NotificationMessage(widget: widget, context: context), const SizedBox(height: defaultSpacing), - _buildActions(), + _NotificationActions(widget: widget), ], ), ), @@ -256,8 +265,19 @@ class _NotificationState extends State<_Notification> ), ); } +} - Widget _buildMessage() { +class _NotificationMessage extends StatelessWidget { + const _NotificationMessage({ + required this.widget, + required this.context, + }); + + final _Notification widget; + final BuildContext context; + + @override + Widget build(BuildContext context) { return Text( widget.message.text, style: Theme.of(context).textTheme.bodyLarge, @@ -265,13 +285,22 @@ class _NotificationState extends State<_Notification> maxLines: 6, ); } +} + +class _NotificationActions extends StatelessWidget { + const _NotificationActions({ + required this.widget, + }); - Widget _buildActions() { - if (widget.message.actions.isEmpty) return const SizedBox(); + final _Notification widget; + + @override + Widget build(BuildContext context) { + final actions = widget.message.actions; + if (actions.isEmpty) return const SizedBox(); return Row( mainAxisAlignment: MainAxisAlignment.end, - children: - widget.message.actions.joinWith(const SizedBox(width: denseSpacing)), + children: actions.joinWith(const SizedBox(width: denseSpacing)), ); } } 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 8fd6688ce05..31e47a3a01b 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 @@ -166,8 +166,7 @@ class ReleaseNotes extends AnimatedWidget { : Expanded( child: Markdown( data: markdownData!, - onTapLink: (_, href, __) => - unawaited(launchUrl(href!, context)), + onTapLink: (_, href, __) => unawaited(launchUrl(href!)), ), ), ], 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 a8d1194401d..b6ad92d9319 100644 --- a/packages/devtools_app/lib/src/framework/report_feedback_button.dart +++ b/packages/devtools_app/lib/src/framework/report_feedback_button.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; + import 'package:flutter/material.dart'; import '../shared/analytics/analytics.dart' as ga; @@ -17,14 +19,15 @@ class ReportFeedbackButton extends StatelessWidget { return DevToolsTooltip( message: 'Report feedback', child: InkWell( - onTap: () async { + onTap: () { ga.select( gac.devToolsMain, gac.feedbackButton, ); - await launchUrl( - devToolsExtensionPoints.issueTrackerLink().url, - context, + unawaited( + launchUrl( + devToolsExtensionPoints.issueTrackerLink().url, + ), ); }, child: Container( diff --git a/packages/devtools_app/lib/src/framework/scaffold.dart b/packages/devtools_app/lib/src/framework/scaffold.dart index 6d7502e732c..cfb811dca7c 100644 --- a/packages/devtools_app/lib/src/framework/scaffold.dart +++ b/packages/devtools_app/lib/src/framework/scaffold.dart @@ -164,7 +164,7 @@ class DevToolsScaffoldState extends State ); // This needs to be called at the scaffold level because we need an instance // of Notifications above this context. - surveyService.maybeShowSurveyPrompt(context); + surveyService.maybeShowSurveyPrompt(); } @override @@ -336,7 +336,9 @@ class DevToolsScaffoldState extends State child: Scaffold( appBar: widget.embed ? null - : _buildAppBar(scaffoldTitle) as PreferredSizeWidget?, + : + // ignore: avoid-returning-widgets as that would make code more verbose for no clear benefit in this case. + _buildAppBar(scaffoldTitle), body: (serviceManager.connectedAppInitialized && !serviceManager.connectedApp!.isProfileBuildNow! && !offlineController.offlineMode.value && @@ -371,7 +373,7 @@ class DevToolsScaffoldState extends State /// Builds an [AppBar] with the [TabBar] placed on the side or the bottom, /// depending on the screen width. - Widget _buildAppBar(String title) { + PreferredSizeWidget _buildAppBar(String title) { Widget? flexibleSpace; late final Size preferredSize; TabBar tabBar; 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 e69e21a6915..17e1f5b99bc 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 @@ -503,10 +503,10 @@ class AppSizeController { _diffTreeMap = _generateDiffTrees(diffMap); if (isDeferredApp.value) { - // For main only: + // For main only. _mainDiffTreeMap = _generateDiffTrees(mainDiffMap!); - // For deferred only: + // For deferred only. _deferredDiffTreeMap = _generateDiffTrees(deferredDiffMap!); } @@ -577,9 +577,9 @@ class AppSizeController { return compareProgramInfo(oldApkProgramInfo, newApkProgramInfo); } - Map _wrapInArtificialRoot(Map json) { + Map _wrapInArtificialRoot(Map json) { json['n'] = _mainNodeName; - return { + return { 'n': _artificialRootNodeName, 'children': [json], }; @@ -598,8 +598,8 @@ class AppSizeController { ); if (!isLeafNode) { - final List rawChildren = json['children'] as List; - for (final childJson in rawChildren.cast>()) { + final rawChildren = json['children'] as List; + for (final childJson in rawChildren.cast>()) { _apkJsonToProgramInfo(program: program, parent: node, json: childJson); } } else { @@ -747,9 +747,9 @@ extension AppSizeJsonFileExtension on DevToolsJsonFile { ]; bool get isAnalyzeSizeFile { - if (data is Map) { - final dataMap = data as Map; - final type = dataMap['type']; + final data = this.data; + if (data is Map) { + final type = data['type'] as String?; return AppSizeJsonFileExtension._supportedAnalyzeSizePlatforms .contains(type); } 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 563df1ee677..d2c92ec73c0 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,7 +19,7 @@ class AppSizeAnalysisTable extends StatelessWidget { }) { final treeColumn = _NameColumn( currentRootLevel: controller.isDeferredApp.value - ? rootNode.children[0].level + ? rootNode.children.first.level : rootNode.level, ); final sizeColumn = _SizeColumn(); @@ -110,7 +110,7 @@ class _SizeColumn extends ColumnData { ); @override - dynamic getValue(TreemapNode dataObject) => dataObject.byteSize; + Comparable getValue(TreemapNode dataObject) => dataObject.byteSize; @override String getDisplayValue(TreemapNode dataObject) { @@ -220,7 +220,7 @@ class _DiffColumn extends ColumnData { // Ensure sort by absolute size. @override - dynamic getValue(TreemapNode dataObject) => dataObject.unsignedByteSize; + int getValue(TreemapNode dataObject) => dataObject.unsignedByteSize; // TODO(peterdjlee): Add up or down arrows indicating increase or decrease for display value. @override 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 a13c6ff74d8..54c42e47700 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 @@ -115,40 +115,7 @@ class _CallGraphViewState extends State { @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return Stack( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Flexible( - child: _buildFromTable(), - ), - Container( - height: constraints.maxHeight, - width: densePadding, - color: Theme.of(context).titleSolidBackgroundColor, - ), - Flexible( - child: _buildToTable(), - ), - ], - ), - Positioned( - top: 0, - width: constraints.maxWidth, - child: _buildMainNode(), - ), - ], - ); - }, - ); - } - - Widget _buildFromTable() { - return FlatTable( + final fromTable = FlatTable( key: CallGraphView.fromTableKey, keyFactory: (CallGraphNode node) => ValueKey(node), data: selectedNode.pred, @@ -158,10 +125,8 @@ class _CallGraphViewState extends State { defaultSortColumn: _fromColumn, defaultSortDirection: SortDirection.descending, ); - } - Widget _buildToTable() { - return FlatTable( + final toTable = FlatTable( key: CallGraphView.toTableKey, keyFactory: (CallGraphNode node) => ValueKey(node), data: selectedNode.succ, @@ -171,10 +136,8 @@ class _CallGraphViewState extends State { defaultSortColumn: _toColumn, defaultSortDirection: SortDirection.descending, ); - } - Widget _buildMainNode() { - return Row( + final mainNode = Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Padding( @@ -197,6 +160,37 @@ class _CallGraphViewState extends State { ), ], ); + + return LayoutBuilder( + builder: (context, constraints) { + return Stack( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + child: fromTable, + ), + Container( + height: constraints.maxHeight, + width: densePadding, + color: Theme.of(context).titleSolidBackgroundColor, + ), + Flexible( + child: toTable, + ), + ], + ), + Positioned( + top: 0, + width: constraints.maxWidth, + child: mainNode, + ), + ], + ); + }, + ); } void _selectMainNode(CallGraphNode node) { 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 a2c85d14e68..a616cb37a96 100644 --- a/packages/devtools_app/lib/src/screens/debugger/breakpoint_manager.dart +++ b/packages/devtools_app/lib/src/screens/debugger/breakpoint_manager.dart @@ -22,15 +22,13 @@ class BreakpointManager extends Disposer { final _breakPositionsMap = >{}; - final _breakpoints = ValueNotifier>([]); - ValueListenable> get breakpoints => _breakpoints; - - final _breakpointsWithLocation = - ValueNotifier>([]); + final _breakpoints = ValueNotifier>([]); ValueListenable> get breakpointsWithLocation => _breakpointsWithLocation; + final _breakpointsWithLocation = + ValueNotifier>([]); IsolateRef? _isolateRef; @@ -103,14 +101,15 @@ class BreakpointManager extends Disposer { _service.removeBreakpoint(_isolateRefId, breakpoint.id!); Future toggleBreakpoint(ScriptRef script, int line) async { - if (serviceManager.isolateManager.selectedIsolate.value == null) { + final selectedIsolate = serviceManager.isolateManager.selectedIsolate.value; + if (selectedIsolate == null) { // Can't toggle breakpoints if we don't have an isolate. return; } // The VM doesn't support debugging for system isolates and will crash on // a failed assert in debug mode. Disable the toggle breakpoint // functionality for system isolates. - if (serviceManager.isolateManager.selectedIsolate.value!.isSystemIsolate!) { + if (selectedIsolate.isSystemIsolate!) { return; } @@ -130,7 +129,7 @@ class BreakpointManager extends Disposer { } void _updateAfterIsolateReload( - Event reloadEvent, + Event _, ) async { // TODO(devoncarew): We need to coordinate this with other debugger clients // as well as pause before re-setting the breakpoints. @@ -138,10 +137,10 @@ class BreakpointManager extends Disposer { 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 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 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 edcbd17761d..27e9e01ee8f 100644 --- a/packages/devtools_app/lib/src/screens/debugger/call_stack.dart +++ b/packages/devtools_app/lib/src/screens/debugger/call_stack.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; - import 'package:flutter/material.dart' hide Stack; import 'package:vm_service/vm_service.dart'; @@ -55,9 +53,11 @@ class _CallStackState extends State Widget child; - final asyncMarker = frame.frame.kind == FrameKind.kAsyncSuspensionMarker; - final asyncFrame = frame.frame.kind == FrameKind.kAsyncActivation || - frame.frame.kind == FrameKind.kAsyncSuspensionMarker; + final frameKind = frame.frame.kind; + + final asyncMarker = frameKind == FrameKind.kAsyncSuspensionMarker; + final asyncFrame = frameKind == FrameKind.kAsyncActivation || + frameKind == FrameKind.kAsyncSuspensionMarker; final noLineInfo = frame.line == null; final frameDescription = frame.description; @@ -103,7 +103,7 @@ class _CallStackState extends State final result = Material( color: selected ? theme.colorScheme.selectedRowColor : null, child: InkWell( - onTap: () => unawaited(_onStackFrameSelected(frame)), + onTap: () => _onStackFrameSelected(frame), child: Container( padding: const EdgeInsets.symmetric(horizontal: densePadding), alignment: Alignment.centerLeft, @@ -123,7 +123,7 @@ class _CallStackState extends State ); } - Future _onStackFrameSelected(StackFrameAndSourcePosition frame) async { + void _onStackFrameSelected(StackFrameAndSourcePosition frame) { controller.selectStackFrame(frame); } } diff --git a/packages/devtools_app/lib/src/screens/debugger/codeview.dart b/packages/devtools_app/lib/src/screens/debugger/codeview.dart index 90cf4f688db..df4f648dbb0 100644 --- a/packages/devtools_app/lib/src/screens/debugger/codeview.dart +++ b/packages/devtools_app/lib/src/screens/debugger/codeview.dart @@ -112,9 +112,18 @@ class _CodeViewState extends State super.initState(); verticalController = LinkedScrollControllerGroup(); + // TODO(jacobr): this lint does not understand that some methods have side + // effects. + // ignore: prefer-moving-to-variable gutterController = verticalController.addAndGet(); + // TODO(jacobr): this lint does not understand that some methods have side + // effects. + // ignore: prefer-moving-to-variable textController = verticalController.addAndGet(); if (widget.codeViewController.showProfileInformation.value) { + // TODO(jacobr): this lint does not understand that some methods have side + // effects. + // ignore: prefer-moving-to-variable profileController = verticalController.addAndGet(); } horizontalController = ScrollController(); @@ -139,15 +148,17 @@ class _CodeViewState extends State // gutter and code view when the widget is toggled on/off. If we don't do // this, the profile information gutter will always be at position 0 when // first enabled until the user scrolls. - addAutoDisposeListener(widget.codeViewController.showProfileInformation, - () { - if (widget.codeViewController.showProfileInformation.value) { - profileController = verticalController.addAndGet(); - } else { - profileController!.dispose(); - profileController = null; - } - }); + addAutoDisposeListener( + widget.codeViewController.showProfileInformation, + () { + if (widget.codeViewController.showProfileInformation.value) { + profileController = verticalController.addAndGet(); + } else { + profileController!.dispose(); + profileController = null; + } + }, + ); } @override @@ -265,7 +276,7 @@ class _CodeViewState extends State return Stack( children: [ scriptRef == null - ? buildEmptyState(context) + ? CodeViewEmptyState(widget: widget, context: context) : buildCodeArea(context), if (showFileOpener) Positioned( @@ -492,22 +503,6 @@ class _CodeViewState extends State ); } - Widget buildEmptyState(BuildContext context) { - final theme = Theme.of(context); - - return Center( - child: ElevatedButton( - autofocus: true, - onPressed: () => - widget.codeViewController.toggleFileOpenerVisibility(true), - child: Text( - 'Open a file ($openFileKeySetDescription)', - style: theme.textTheme.titleMedium, - ), - ), - ); - } - List> _buildScriptMenuFromHistory( BuildContext context, ) { @@ -540,6 +535,34 @@ class _CodeViewState extends State } } +class CodeViewEmptyState extends StatelessWidget { + const CodeViewEmptyState({ + super.key, + required this.widget, + required this.context, + }); + + final CodeView widget; + final BuildContext context; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Center( + child: ElevatedButton( + autofocus: true, + onPressed: () => + widget.codeViewController.toggleFileOpenerVisibility(true), + child: Text( + 'Open a file ($openFileKeySetDescription)', + style: theme.textTheme.titleMedium, + ), + ), + ); + } +} + class ProfileInformationGutter extends StatelessWidget { const ProfileInformationGutter({ required this.scrollController, @@ -1116,6 +1139,9 @@ class _LineItemState extends State with ProvidedControllerMixin { Future _generateHoverCardData({ required PointerEvent event, + // TODO(jacobr): this needs to be ignored as this method is passed as a + // callback. + // ignore: avoid-unused-parameters required bool Function() isHoverStale, }) async { if (!controller.isPaused.value) return null; @@ -1196,7 +1222,7 @@ class _LineItemState extends State // to allow us to render this as a proper overlay as similar // functionality exists to render the selection handles properly. Opacity( - opacity: .5, + opacity: 0.5, child: RichText( text: truncateTextSpan(widget.lineContents, column - 1), ), @@ -1352,7 +1378,7 @@ class _LineItemState extends State ) { final searchMatches = widget.searchMatches; if (searchMatches == null || searchMatches.isEmpty) return startingContents; - final searchMatchesToFind = List.from(searchMatches) + final searchMatchesToFind = List.of(searchMatches) ..remove(widget.activeSearchMatch); var contentsWithMatch = startingContents; @@ -1472,10 +1498,12 @@ final copyPackagePathOption = ScriptPopupMenuOption( final copyFilePathOption = ScriptPopupMenuOption( label: 'Copy file path', icon: Icons.content_copy, - onSelected: (_, controller) async { - return Clipboard.setData( - ClipboardData(text: await fetchScriptLocationFullFilePath(controller)), - ); + onSelected: (_, controller) { + unawaited(() async { + await Clipboard.setData( + ClipboardData(text: await fetchScriptLocationFullFilePath(controller)), + ); + }()); }, ); @@ -1520,7 +1548,7 @@ final goToLineOption = ScriptPopupMenuOption( onSelected: showGoToLineDialog, ); -void showFileOpener(BuildContext context, CodeViewController controller) { +void showFileOpener(BuildContext _, CodeViewController controller) { controller.toggleFileOpenerVisibility(true); } 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 698c8c21791..3023d975868 100644 --- a/packages/devtools_app/lib/src/screens/debugger/codeview_controller.dart +++ b/packages/devtools_app/lib/src/screens/debugger/codeview_controller.dart @@ -122,7 +122,12 @@ class CodeViewController extends DisposableController /// connecting to low-end devices. Future maybeSetupProgramExplorer() async { await _maybeSetUpProgramExplorer(); - addAutoDisposeListener(currentScriptRef, _maybeSetUpProgramExplorer); + addAutoDisposeListener( + currentScriptRef, + () => unawaited( + _maybeSetUpProgramExplorer(), + ), + ); } Future _maybeSetUpProgramExplorer() async { diff --git a/packages/devtools_app/lib/src/screens/debugger/controls.dart b/packages/devtools_app/lib/src/screens/debugger/controls.dart index 0bce4e2c7fc..c912286d947 100644 --- a/packages/devtools_app/lib/src/screens/debugger/controls.dart +++ b/packages/devtools_app/lib/src/screens/debugger/controls.dart @@ -79,7 +79,9 @@ class _DebuggingControlsState extends State icon: Codicons.debugPause, autofocus: true, // Disable when paused or selected isolate is a system isolate. - onPressed: (isPaused || isSystemIsolate) ? null : controller.pause, + onPressed: (isPaused || isSystemIsolate) + ? null + : () => unawaited(controller.pause()), ), LeftBorder( child: DebuggerButton( @@ -88,7 +90,7 @@ class _DebuggingControlsState extends State // Enable while paused + not resuming and selected isolate is not // a system isolate. onPressed: ((isPaused && !resuming) && !isSystemIsolate) - ? controller.resume + ? () => unawaited(controller.resume()) : null, ), ), @@ -104,20 +106,20 @@ class _DebuggingControlsState extends State DebuggerButton( title: 'Step Over', icon: Codicons.debugStepOver, - onPressed: canStep ? controller.stepOver : null, + onPressed: canStep ? () => unawaited(controller.stepOver()) : null, ), LeftBorder( child: DebuggerButton( title: 'Step In', icon: Codicons.debugStepInto, - onPressed: canStep ? controller.stepIn : null, + onPressed: canStep ? () => unawaited(controller.stepIn()) : null, ), ), LeftBorder( child: DebuggerButton( title: 'Step Out', icon: Codicons.debugStepOut, - onPressed: canStep ? controller.stepOut : null, + onPressed: canStep ? () => unawaited(controller.stepOut()) : null, ), ), ], @@ -195,7 +197,10 @@ class CodeStatisticsControls extends StatelessWidget { tooltip: 'Refresh statistics', outlined: false, onPressed: showCodeCoverage || showProfileInformation - ? controller.codeViewController.refreshCodeStatistics + ? () => unawaited( + controller.codeViewController + .refreshCodeStatistics(), + ) : null, minScreenWidthForTextBeforeScaling: 20000, icon: Icons.refresh, 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 2d312a531c9..5ddb8f3cfad 100644 --- a/packages/devtools_app/lib/src/screens/debugger/debugger_controller.dart +++ b/packages/devtools_app/lib/src/screens/debugger/debugger_controller.dart @@ -301,7 +301,7 @@ class DebuggerController extends DisposableController /// stack frame, or the top frame if there is no current selection. /// /// This will fail if the application is not currently paused. - Future evalAtCurrentFrame(String expression) async { + Future evalAtCurrentFrame(String expression) { if (!isPaused.value) { return Future.error( RPCError.withDetails( @@ -348,7 +348,7 @@ class DebuggerController extends DisposableController Future retrieveFullStringValue( InstanceRef stringRef, { String onUnavailable(String? truncatedValue)?, - }) async { + }) { return _service.retrieveFullStringValue( _isolateRefId, stringRef, @@ -431,8 +431,14 @@ class DebuggerController extends DisposableController final currentScriptRefs = await scriptManager.retrieveAndSortScripts(isolateRef!); final removedScripts = + // There seems to be a bug in how this lint is working with type + // inference. + // ignore: avoid-collection-methods-with-unrelated-types Set.of(previousScriptRefs).difference(Set.of(currentScriptRefs)); final addedScripts = + // There seems to be a bug in how this lint is working with type + // inference. + // ignore: avoid-collection-methods-with-unrelated-types Set.of(currentScriptRefs).difference(Set.of(previousScriptRefs)); // TODO(devoncarew): Show a message in the logging view. @@ -654,8 +660,10 @@ class DebuggerController extends DisposableController final variables = frame.vars!.map((v) => DartObjectNode.create(v, isolateRef)).toList(); + // TODO(jacobr): would be nice to be able to remove this call to unawaited + // but it would require a significant refactor. variables - ..forEach(buildVariablesTree) + ..forEach((v) => unawaited(buildVariablesTree(v))) ..sort((a, b) => sortFieldsByName(a.name!, b.name!)); return variables; } 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 501e9e86f7f..957fc87a133 100644 --- a/packages/devtools_app/lib/src/screens/debugger/debugger_model.dart +++ b/packages/devtools_app/lib/src/screens/debugger/debugger_model.dart @@ -399,6 +399,7 @@ class FileNode extends TreeNode { } } +// TODO(jacobr): refactor this code. // ignore: avoid_classes_with_only_static_members class ScriptRefUtils { static String fileName(ScriptRef scriptRef) => 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 d0e9b0190a3..7aa5df7de98 100644 --- a/packages/devtools_app/lib/src/screens/debugger/debugger_screen.dart +++ b/packages/devtools_app/lib/src/screens/debugger/debugger_screen.dart @@ -138,11 +138,13 @@ class DebuggerScreenBodyState extends State child: ValueListenableBuilder( valueListenable: codeViewController.fileExplorerVisible, builder: (context, visible, child) { + // Conditional expression + // ignore: prefer-conditional-expression if (visible) { // TODO(devoncarew): Animate this opening and closing. return Split( axis: Axis.horizontal, - initialFractions: const [0.70, 0.30], + initialFractions: const [0.7, 0.3], children: [ child!, OutlineDecoration( @@ -184,7 +186,9 @@ class DebuggerScreenBodyState extends State debuggerController: controller, scriptRef: scriptRef, parsedScript: parsedScript, - onSelected: breakpointManager.toggleBreakpoint, + onSelected: (script, line) => unawaited( + breakpointManager.toggleBreakpoint(script, line), + ), ); }, ), @@ -211,7 +215,7 @@ class DebuggerScreenBodyState extends State builder: (context, constraints) { return FlexSplitColumn( totalHeight: constraints.maxHeight, - initialFractions: const [0.40, 0.40, 0.20], + initialFractions: const [0.4, 0.4, 0.2], minSizes: const [0.0, 0.0, 0.0], headers: [ AreaPaneHeader( @@ -264,7 +268,7 @@ class DebuggerScreenBodyState extends State child: ToolbarAction( icon: Icons.delete, onPressed: breakpoints.isNotEmpty - ? breakpointManager.clearBreakpoints + ? () => unawaited(breakpointManager.clearBreakpoints()) : null, ), ), @@ -359,9 +363,14 @@ class _DebuggerStatusState extends State with AutoDisposeMixin { void initState() { super.initState(); - addAutoDisposeListener(widget.controller.isPaused, _updateStatus); + addAutoDisposeListener( + widget.controller.isPaused, + () => unawaited( + _updateStatus(), + ), + ); - _updateStatus(); + unawaited(_updateStatus()); } @override @@ -369,7 +378,12 @@ class _DebuggerStatusState extends State with AutoDisposeMixin { super.didUpdateWidget(oldWidget); // todo: should we check that widget.controller != oldWidget.controller? - addAutoDisposeListener(widget.controller.isPaused, _updateStatus); + addAutoDisposeListener( + widget.controller.isPaused, + () => unawaited( + _updateStatus(), + ), + ); } @override @@ -381,7 +395,7 @@ class _DebuggerStatusState extends State with AutoDisposeMixin { ); } - void _updateStatus() async { + Future _updateStatus() async { final status = await _computeStatus(); if (status != _status) { setState(() { @@ -402,14 +416,15 @@ class _DebuggerStatusState extends State with AutoDisposeMixin { final reason = event.kind == EventKind.kPauseException ? ' on exception' : ''; - final scriptUri = frame?.location?.script?.uri; + final location = frame?.location; + final scriptUri = location?.script?.uri; if (scriptUri == null) { return 'paused$reason'; } final fileName = ' at ' + scriptUri.split('/').last; - final tokenPos = frame?.location?.tokenPos; - final scriptRef = frame?.location?.script; + final tokenPos = location?.tokenPos; + final scriptRef = location?.script; if (tokenPos == null || scriptRef == null) { return 'paused$reason$fileName'; } diff --git a/packages/devtools_app/lib/src/screens/debugger/evaluate.dart b/packages/devtools_app/lib/src/screens/debugger/evaluate.dart index d3bd54033d1..c12b5ad91ac 100644 --- a/packages/devtools_app/lib/src/screens/debugger/evaluate.dart +++ b/packages/devtools_app/lib/src/screens/debugger/evaluate.dart @@ -294,7 +294,7 @@ class ExpressionEvalFieldState extends State void _handleExpressionEval() async { final expressionText = searchTextFieldController.value.text.trim(); - updateSearchField(_autoCompleteController, newValue: '', caretPosition: 0); + updateSearchField(newValue: '', caretPosition: 0); clearSearchField(_autoCompleteController, force: true); if (expressionText.isEmpty) return; @@ -342,7 +342,6 @@ class ExpressionEvalFieldState extends State void _emitToConsole(String text) { serviceManager.consoleService.appendStdio( ' ${text.replaceAll('\n', '\n ')}\n', - forceScrollIntoView: true, ); } 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 082cb6ddd57..60061c5c6ee 100644 --- a/packages/devtools_app/lib/src/screens/debugger/program_explorer.dart +++ b/packages/devtools_app/lib/src/screens/debugger/program_explorer.dart @@ -90,7 +90,6 @@ class _ProgramExplorerRow extends StatelessWidget { final func = node.object as Func; final isInstanceMethod = func.owner is ClassRef; final subtext = _buildFunctionTypeText( - func.name, func.signature!, isInstanceMethod: isInstanceMethod, ); @@ -136,7 +135,6 @@ class _ProgramExplorerRow extends StatelessWidget { /// - Baz(String, [int]) -> void /// - Faz(String, {String? bar, required int baz}) -> int String _buildFunctionTypeText( - String? functionName, InstanceRef signature, { bool isInstanceMethod = false, }) { @@ -174,7 +172,7 @@ class _ProgramExplorerRow extends StatelessWidget { if (paramType != null) { final paramTypeName = param.parameterType?.name; if (paramTypeName == null) { - buffer.write(_buildFunctionTypeText('Function', paramType)); + buffer.write(_buildFunctionTypeText(paramType)); } else { buffer.write(paramTypeName); } @@ -201,7 +199,7 @@ class _ProgramExplorerRow extends StatelessWidget { if (returnType != null) { final returnTypeName = signature.returnType?.name; if (returnTypeName == null) { - buffer.write(_buildFunctionTypeText('Function', returnType)); + buffer.write(_buildFunctionTypeText(returnType)); } else { buffer.write(returnTypeName); } 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 690deae5882..7b31f6e207f 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 @@ -356,7 +356,7 @@ class ProgramExplorerController extends DisposableController await service.getObject(isolateId, targetScript.id!) as Script; final LibraryRef targetLib = scriptObj.library!; - // Search targetLib only on the root level nodes + // Search targetLib only on the root level nodes. final libNode = _searchRootObjectNodes(targetLib)!; // If the object's owning script URI is the same as the target library URI, 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 aacc387f98e..930f615844b 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 @@ -342,11 +342,19 @@ class VMServiceObjectNode extends TreeNode { } ScriptRef? scriptRef = script; int? tokenPos = 0; - if (object != null && - (object is FieldRef || object is FuncRef || object is ClassRef)) { - final location = (object as dynamic).location; - tokenPos = location.tokenPos; - scriptRef = location.script; + final object = this.object; + + SourceLocation? sourceLocation; + if (object is FieldRef) { + sourceLocation = object.location; + } else if (object is FuncRef) { + sourceLocation = object.location; + } else if (object is ClassRef) { + sourceLocation = object.location; + } + if (sourceLocation != null) { + tokenPos = sourceLocation.tokenPos; + scriptRef = sourceLocation.script; } if (scriptRef != null) { 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 559be877949..6f9e85a3e07 100644 --- a/packages/devtools_app/lib/src/screens/debugger/span_parser.dart +++ b/packages/devtools_app/lib/src/screens/debugger/span_parser.dart @@ -8,6 +8,7 @@ import 'dart:convert'; import 'package:collection/collection.dart'; import 'package:string_scanner/string_scanner.dart'; +//TODO(jacobr): cleanup. // ignore: avoid_classes_with_only_static_members abstract class SpanParser { /// Takes a TextMate [Grammar] and a [String] and outputs a list of @@ -707,7 +708,7 @@ class ScopeStack { endLocation: end, ); // Replace the last span with this one. - spans[spans.length - 1] = span; + spans.last = span; } else { final span = ScopeSpan( scopes: newScopes, diff --git a/packages/devtools_app/lib/src/screens/debugger/variables.dart b/packages/devtools_app/lib/src/screens/debugger/variables.dart index 53f4c2b644d..c8e4c2ccdd4 100644 --- a/packages/devtools_app/lib/src/screens/debugger/variables.dart +++ b/packages/devtools_app/lib/src/screens/debugger/variables.dart @@ -37,13 +37,12 @@ class Variables extends StatelessWidget { dataRootsListenable: controller.variables, dataDisplayProvider: (variable, onPressed) => displayProvider(context, variable, onPressed, controller), - onItemSelected: (variable) async => onItemPressed(variable, controller), + onItemSelected: onItemPressed, ); } Future onItemPressed( DartObjectNode v, - DebuggerController controller, ) async { // On expansion, lazily build the variables tree for performance reasons. if (v.isExpanded) { @@ -79,14 +78,12 @@ class ExpandableVariable extends StatelessWidget { shrinkWrap: true, dataDisplayProvider: (variable, onPressed) => displayProvider(context, variable, onPressed, debuggerController), - onItemSelected: (variable) async => - onItemPressed(variable, debuggerController), + onItemSelected: onItemPressed, ); } Future onItemPressed( DartObjectNode v, - DebuggerController controller, ) async { // On expansion, lazily build the variables tree for performance reasons. if (v.isExpanded) { diff --git a/packages/devtools_app/lib/src/screens/inspector/diagnostics.dart b/packages/devtools_app/lib/src/screens/inspector/diagnostics.dart index 68a2a7c0d35..66c32b7b386 100644 --- a/packages/devtools_app/lib/src/screens/inspector/diagnostics.dart +++ b/packages/devtools_app/lib/src/screens/inspector/diagnostics.dart @@ -161,7 +161,6 @@ class DiagnosticsNodeDescription extends StatelessWidget { Widget buildDescription({ required String description, required TextStyle textStyle, - required BuildContext context, required ColorScheme colorScheme, RemoteDiagnosticsNode? diagnostic, String? searchValue, @@ -331,7 +330,6 @@ class DiagnosticsNodeDescription extends StatelessWidget { child: buildDescription( description: description, textStyle: descriptionTextStyle, - context: context, colorScheme: colorScheme, diagnostic: diagnostic, searchValue: searchValue, @@ -389,7 +387,6 @@ class DiagnosticsNodeDescription extends StatelessWidget { var diagnosticDescription = buildDescription( description: diagnosticLocal.description ?? '', textStyle: descriptionTextStyle, - context: context, colorScheme: colorScheme, diagnostic: diagnostic, searchValue: searchValue, diff --git a/packages/devtools_app/lib/src/screens/inspector/diagnostics_node.dart b/packages/devtools_app/lib/src/screens/inspector/diagnostics_node.dart index 4126601e7b2..4a3ed1bef5d 100644 --- a/packages/devtools_app/lib/src/screens/inspector/diagnostics_node.dart +++ b/packages/devtools_app/lib/src/screens/inspector/diagnostics_node.dart @@ -171,7 +171,7 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { bool? _isLocalClass; @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (other is! RemoteDiagnosticsNode) return false; return dartDiagnosticRef == other.dartDiagnosticRef; } @@ -283,7 +283,7 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { /// /// Only applies to IterableProperty. List? get values { - final rawValues = json['values'] as List?; + final rawValues = json['values'] as List?; if (rawValues == null) { return null; } @@ -297,7 +297,7 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { /// interactive object debugger view to get more information on what the value /// is. List? get primitiveValues { - final rawValues = json['primitiveValues'] as List?; + final rawValues = json['primitiveValues'] as List?; if (rawValues == null) { return null; } @@ -520,7 +520,7 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { // that indicates the node should have no children in the tree while if the // 'children' property is not specified it means we do not know whether // there is a list of children and need to query the server to find out. - final children = json['children'] as List?; + final children = json['children'] as List?; if (children != null) { return children.isNotEmpty; } @@ -574,7 +574,7 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { } } - Future> _getChildrenHelper() async { + Future> _getChildrenHelper() { return inspectorService!.getChildren( dartDiagnosticRef, isSummaryTree, 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 e54820191d2..fa671616dc9 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_breadcrumbs.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_breadcrumbs.dart @@ -93,7 +93,7 @@ class _InspectorBreadcrumb extends StatelessWidget { static const BorderRadius _borderRadius = BorderRadius.all(Radius.circular(defaultBorderRadius)); - static const _iconScale = .75; + static const _iconScale = 0.75; final _InspectorBreadcrumbData data; final VoidCallback onTap; 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 7d4ed150fbb..b769dd899ce 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart @@ -110,19 +110,20 @@ class InspectorController extends DisposableController } autoDisposeStreamSubscription( - serviceManager.onConnectionAvailable.listen(_handleConnectionStart), + serviceManager.onConnectionAvailable + .listen((_) => _handleConnectionStart()), ); if (serviceManager.connectedAppInitialized) { - _handleConnectionStart(serviceManager.service!); + _handleConnectionStart(); } autoDisposeStreamSubscription( - serviceManager.onConnectionClosed.listen(_handleConnectionStop), + serviceManager.onConnectionClosed.listen((_) => _handleConnectionStop()), ); serviceManager.consoleService.ensureServiceInitialized(); } - void _handleConnectionStart(VmService service) { + void _handleConnectionStart() { // Clear any existing badge/errors for older errors that were collected. // Do this in a post frame callback so that we are not trying to clear the // error notifiers for this screen while the framework is already in the @@ -135,7 +136,7 @@ class InspectorController extends DisposableController filterErrors(); } - void _handleConnectionStop(dynamic event) { + void _handleConnectionStop() { setActivate(false); if (isSummaryTree) { dispose(); @@ -895,6 +896,8 @@ class InspectorController extends DisposableController } } + // TODO(jacobr): implement this method and use the parameter. + // ignore: avoid-unused-parameters void _navigateTo(RemoteDiagnosticsNode diagnostic) { // TODO(jacobr): dispatch an event over the inspectorService requesting a // navigate operation. @@ -946,7 +949,7 @@ class InspectorController extends DisposableController ); } - Future collapseDetailsToSelected() async { + void collapseDetailsToSelected() { final detailsLocal = details!; detailsLocal.inspectorTree.collapseToSelected(); detailsLocal.animateTo(detailsLocal.inspectorTree.selection); 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 20c9ada9937..72efabb0c71 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 @@ -297,7 +297,7 @@ extension MainAxisAlignmentExtension on MainAxisAlignment { } } -/// TODO(albertusangga): Move this to [RemoteDiagnosticsNode] once dart:html app is removed +/// TODO(albertusangga): Move this to [RemoteDiagnosticsNode] once dart:html app is removed. class FlexLayoutProperties extends LayoutProperties { FlexLayoutProperties({ required Size size, @@ -382,7 +382,7 @@ class FlexLayoutProperties extends LayoutProperties { static FlexLayoutProperties _buildNode(RemoteDiagnosticsNode node) { final Map renderObjectJson = node.renderObject!.json; - final properties = renderObjectJson['properties'] as List; + final properties = renderObjectJson['properties'] as List; final data = Map.fromIterable( properties, key: (property) => property['name'], diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_screen.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_screen.dart index 5a4b994a993..635b82f7cc2 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_screen.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_screen.dart @@ -352,7 +352,7 @@ class FlutterInspectorSettingsDialog extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ ...dialogSubHeader( - Theme.of(context), + theme, 'General', ), CheckboxSetting( @@ -364,7 +364,7 @@ class FlutterInspectorSettingsDialog extends StatelessWidget { gaItem: gac.inspectorHoverEvalMode, ), const SizedBox(height: denseSpacing), - ...dialogSubHeader(Theme.of(context), 'Package Directories'), + ...dialogSubHeader(theme, 'Package Directories'), Text( 'Widgets in these directories will show up in your summary tree.', style: theme.subtleTextStyle, 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 c87aae7464d..6b666ed1158 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 @@ -122,14 +122,10 @@ class _InspectorExpandCollapseButtonsState } void _onCollapseClick() { - unawaited( - blockWhileInProgress(() async { - ga.select( - gac.inspector, - gac.collapseAll, - ); - await widget.controller.collapseDetailsToSelected(); - }), + ga.select( + gac.inspector, + gac.collapseAll, ); + widget.controller.collapseDetailsToSelected(); } } diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_service.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_service.dart index 1ad62b06c24..7aa92811bee 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_service.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_service.dart @@ -133,7 +133,7 @@ abstract class InspectorServiceBase extends DisposableController String methodName, [ List? args, ]) { - final Map params = {}; + final Map params = {}; if (args != null) { for (int i = 0; i < args.length; ++i) { params['arg$i'] = args[i]; @@ -153,7 +153,7 @@ abstract class InspectorServiceBase extends DisposableController Future invokeServiceMethodDaemonNoGroup( String methodName, { - Map? args, + Map? args, }) async { final callMethodName = '$serviceExtensionPrefix.$methodName'; if (!serviceManager.serviceExtensionManager @@ -343,7 +343,7 @@ class InspectorService extends InspectorServiceBase { // third_party/dart_src/long/package/name (package:long.package.name) // so its path should be at minimum depth 3. const minThirdPartyPathDepth = 3; - if (packageParts[0] == 'third_party' && + if (packageParts.first == 'third_party' && packageParts.length >= minThirdPartyPathDepth) { assert(packageParts[1] == 'dart' || packageParts[1] == 'dart_src'); packageParts = packageParts.sublist(2); @@ -359,7 +359,8 @@ class InspectorService extends InspectorServiceBase { await _updateLocalClasses(); } - Future _updateLocalClasses() async { + Future _updateLocalClasses() { + return Future.value(); // TODO(https://github.com/flutter/devtools/issues/4393) // localClasses.clear(); // if (_rootDirectories.value.isNotEmpty) { @@ -434,7 +435,7 @@ class InspectorService extends InspectorServiceBase { 'getPubRootDirectories', ); - if (response is! List) { + if (response is! List) { return []; } @@ -850,7 +851,7 @@ abstract class ObjectGroupBase implements Disposable { final instanceRef = await instanceRefFuture; if (disposed || instanceRefFuture == null) return []; return parseDiagnosticsNodesHelper( - await instanceRefToJson(instanceRef) as List?, + await instanceRefToJson(instanceRef) as List?, parent, isProperty, ); 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 dee2a016fef..fd96986a441 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 @@ -26,7 +26,7 @@ class BoxLayoutExplorerWidget extends LayoutExplorerWidget { Key? key, }) : super(inspectorController, key: key); - static bool shouldDisplay(RemoteDiagnosticsNode node) { + static bool shouldDisplay(RemoteDiagnosticsNode _) { // Pretend this layout explorer is always available. This layout explorer // will gracefully fall back to an error message if the required properties // are not needed. @@ -386,7 +386,7 @@ class BoxChildVisualizer extends StatelessWidget { final renderSize = renderProperties.size; final renderOffset = renderProperties.offset; - Widget buildEntranceAnimation(BuildContext context, Widget? child) { + Widget buildEntranceAnimation(BuildContext _, Widget? child) { final size = renderSize; // TODO(jacobr): does this entrance animation really add value. return Opacity( @@ -409,7 +409,6 @@ class BoxChildVisualizer extends StatelessWidget { child: InkWell( onTap: () => unawaited(state.onTap(propertiesLocal)), onDoubleTap: () => state.onDoubleTap(propertiesLocal), - onLongPress: () => state.onDoubleTap(propertiesLocal), child: SizedBox( width: safePositiveDouble(renderSize.width), height: safePositiveDouble(renderSize.height), 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 72bb0bbb674..b04ddccc739 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 @@ -223,15 +223,13 @@ 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; - if (axis == direction) { - changedProperties = propertiesLocal.copyWith( - mainAxisAlignment: newSelection as MainAxisAlignment?, - ); - } else { - changedProperties = 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( @@ -707,7 +705,7 @@ class FlexChildVisualizer extends StatelessWidget { final propertiesLocal = properties; final rootLocal = root; - Widget buildEntranceAnimation(BuildContext context, Widget? child) { + Widget buildEntranceAnimation(BuildContext _, Widget? child) { final vertical = rootLocal.isMainAxisVertical; final horizontal = rootLocal.isMainAxisHorizontal; 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 5cb709c2cc2..0ea220e5480 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 @@ -135,7 +135,6 @@ class ArrowWrapper extends StatelessWidget { class ArrowWidget extends StatelessWidget { ArrowWidget({ this.color = defaultArrowColor, - // ignore: always_require_non_null_named_parameters required this.headSize, Key? key, this.shouldDrawHead = true, @@ -176,7 +175,6 @@ class ArrowWidget extends StatelessWidget { class _ArrowPainter extends CustomPainter { _ArrowPainter({ - // ignore: always_require_non_null_named_parameters required this.headSize, this.strokeWidth = defaultArrowStrokeWidth, this.color = defaultArrowColor, 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 18159ffefb6..2e0fe604db7 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 @@ -181,7 +181,7 @@ class WidgetVisualizer extends StatelessWidget { boxShadow: isSelected ? [ BoxShadow( - color: Colors.black.withOpacity(.5), + color: Colors.black.withOpacity(0.5), blurRadius: 20, ), ] 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 96e58d8ffb8..18396f6aad7 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart @@ -238,7 +238,7 @@ class LoggingController extends DisposableController serviceManager.errorBadgeManager.clearErrors(LoggingScreen.id); } - void _handleConnectionStart(VmServiceWrapper service) async { + void _handleConnectionStart(VmServiceWrapper service) { // Log stdout events. final _StdoutEventHandler stdoutHandler = _StdoutEventHandler(this, 'stdout'); @@ -395,7 +395,7 @@ class LoggingController extends DisposableController '${e.json!['reason']} collection in $time ms • ' '${printMB(usedBytes, includeUnit: true)} used of ${printMB(capacityBytes, includeUnit: true)}'; - final event = { + final event = { 'reason': e.json!['reason'], 'new': newSpace.json, 'old': oldSpace.json, @@ -496,10 +496,10 @@ class LoggingController extends DisposableController ); } - void _handleConnectionStop(dynamic event) {} + void _handleConnectionStop(Object? _) {} void log(LogData log) { - List currentLogs = List.from(data); + List currentLogs = List.of(data); // Insert the new item and clamped the list to kMaxLogItemsLength. currentLogs.add(log); @@ -967,5 +967,5 @@ class ServiceExtensionStateChangedInfo { } final String? extension; - final dynamic value; + final Object value; } diff --git a/packages/devtools_app/lib/src/screens/memory/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/memory_controller.dart index 0188faa90c3..7105a2be55c 100644 --- a/packages/devtools_app/lib/src/screens/memory/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/memory_controller.dart @@ -214,7 +214,7 @@ class MemoryController extends DisposableController .value; } - void _handleConnectionStart(ServiceConnectionManager serviceManager) async { + void _handleConnectionStart(ServiceConnectionManager serviceManager) { _refreshShouldShowLeaksTab(); if (_memoryTracker == null) { _memoryTracker = MemoryTracker(this); @@ -298,7 +298,7 @@ class MemoryController extends DisposableController isOfflineAndAndroidData || isConnectedToAndroidAndAndroidEnabled; } - void _handleConnectionStop(dynamic event) { + void _handleConnectionStop(Object? _) { _memoryTracker?.stop(); _memoryTrackerController.add(_memoryTracker); @@ -306,7 +306,7 @@ class MemoryController extends DisposableController hasStopped = true; } - Future startTimeline() async { + void startTimeline() { addAutoDisposeListener( serviceManager.isolateManager.selectedIsolate, _handleIsolateChanged, diff --git a/packages/devtools_app/lib/src/screens/memory/panes/allocation_profile/allocation_profile_table_view.dart b/packages/devtools_app/lib/src/screens/memory/panes/allocation_profile/allocation_profile_table_view.dart index f500c3959e3..3fa6211bad2 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/allocation_profile/allocation_profile_table_view.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/allocation_profile/allocation_profile_table_view.dart @@ -78,7 +78,7 @@ class _FieldInstanceCountColumn extends ColumnData { final _HeapGeneration heap; @override - dynamic getValue(AllocationProfileRecord dataObject) { + int? getValue(AllocationProfileRecord dataObject) { switch (heap) { case _HeapGeneration.newSpace: return dataObject.newSpaceInstances; @@ -102,7 +102,7 @@ class _FieldExternalSizeColumn extends _FieldSizeColumn { ); @override - dynamic getValue(AllocationProfileRecord dataObject) { + int? getValue(AllocationProfileRecord dataObject) { switch (heap) { case _HeapGeneration.newSpace: return dataObject.newSpaceExternalSize; @@ -122,7 +122,7 @@ class _FieldDartHeapSizeColumn extends _FieldSizeColumn { ); @override - dynamic getValue(AllocationProfileRecord dataObject) { + int? getValue(AllocationProfileRecord dataObject) { switch (heap) { case _HeapGeneration.newSpace: return dataObject.newSpaceDartHeapSize; @@ -157,7 +157,7 @@ class _FieldSizeColumn extends ColumnData { final _HeapGeneration heap; @override - dynamic getValue(AllocationProfileRecord dataObject) { + int? getValue(AllocationProfileRecord dataObject) { switch (heap) { case _HeapGeneration.newSpace: return dataObject.newSpaceSize; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/chart_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/chart_pane.dart index ed1ee227c72..eb26f8a23bf 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/chart_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/chart_pane.dart @@ -176,7 +176,7 @@ class _MemoryChartPaneState extends State await serviceManager.onServiceAvailable; if (!controller.hasStarted) { - await controller.startTimeline(); + controller.startTimeline(); // TODO(terry): Need to set the initial state of buttons. /* @@ -347,7 +347,7 @@ class _MemoryChartPaneState extends State left: xPosition, height: totalHoverHeight, child: Container( - padding: const EdgeInsets.fromLTRB(0, 5, 0, 8), + padding: const EdgeInsets.only(top: 5, bottom: 8), decoration: BoxDecoration( color: colorScheme.defaultBackgroundColor, border: Border.all( @@ -391,15 +391,14 @@ class _MemoryChartPaneState extends State if (firstWidget != null) results.add(firstWidget); for (var entry in dataToDisplay.entries) { - final image = entry.value.keys.contains(renderImage) + final keys = entry.value.keys; + final image = keys.contains(renderImage) ? entry.value[renderImage] as String? : null; - final color = entry.value.keys.contains(renderLine) - ? entry.value[renderLine] as Color? - : null; - final dashedLine = entry.value.keys.contains(renderDashed) - ? entry.value[renderDashed] - : false; + final color = + keys.contains(renderLine) ? entry.value[renderLine] as Color? : null; + final dashedLine = + keys.contains(renderDashed) ? entry.value[renderDashed] : false; results.add( _hoverRow( @@ -424,7 +423,6 @@ class _MemoryChartPaneState extends State bool bold = true, bool hasNumeric = false, bool scaleImage = false, - double leftPadding = 5.0, }) { final theme = Theme.of(context); final hoverTitleEntry = theme.hoverTextStyle; @@ -436,7 +434,6 @@ class _MemoryChartPaneState extends State String? image, Color? colorPatch, bool dashed = false, - double leftEdge = 5.0, }) { String displayName = name; // Empty string overflows, default value space. @@ -455,12 +452,11 @@ class _MemoryChartPaneState extends State } Widget traceColor; + // Logic would be hard to read as a conditional expression. + // ignore: prefer-conditional-expression if (colorPatch != null) { - if (dashed) { - traceColor = createDashWidget(colorPatch); - } else { - traceColor = createSolidLine(colorPatch); - } + traceColor = + dashed ? createDashWidget(colorPatch) : createSolidLine(colorPatch); } else { traceColor = image == null ? const SizedBox() @@ -493,11 +489,10 @@ class _MemoryChartPaneState extends State image: image, colorPatch: colorPatch, dashed: dashed, - leftEdge: leftPadding, ), ); return Container( - padding: const EdgeInsets.fromLTRB(5, 0, 0, 2), + margin: const EdgeInsets.only(left: 5, bottom: 2), child: Row( children: rowChildren, ), @@ -532,7 +527,6 @@ class _MemoryChartPaneState extends State _listItem( allEvents: chartsValues.extensionEvents, title: entry.key, - icon: Icons.dashboard, ), ], ), @@ -544,7 +538,7 @@ class _MemoryChartPaneState extends State /// Pull out the event name, and custom values. final output = _displayEvent(null, chartsValues.extensionEvents.first).trim(); - widgets.add(_hoverRow(name: output, bold: false, leftPadding: 0.0)); + widgets.add(_hoverRow(name: output, bold: false)); } } return widgets; @@ -567,7 +561,6 @@ class _MemoryChartPaneState extends State Widget _listItem({ required List> allEvents, required String title, - IconData? icon, }) { final widgets = []; var index = 1; @@ -591,7 +584,7 @@ class _MemoryChartPaneState extends State tilePadding: EdgeInsets.zero, childrenPadding: EdgeInsets.zero, leading: Container( - padding: const EdgeInsets.fromLTRB(5, 4, 0, 0), + padding: const EdgeInsets.only(left: 5, top: 4), child: Image( image: allEvents.length > 1 ? const AssetImage(eventsLegend) @@ -613,23 +606,21 @@ class _MemoryChartPaneState extends State final hoverValueEntry = theme.hoverSmallValueTextStyle; final expandedGradient = colorScheme.verticalGradient; - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Container( - width: _hoverWidth, - decoration: BoxDecoration( - gradient: expandedGradient, - ), - child: Row( - children: [ - const SizedBox(width: 10), - Text( - value, - overflow: TextOverflow.ellipsis, - style: hoverValueEntry, - ), - ], - ), + return Container( + margin: const EdgeInsets.only(bottom: 8), + width: _hoverWidth, + decoration: BoxDecoration( + gradient: expandedGradient, + ), + child: Row( + children: [ + const SizedBox(width: 10), + Text( + value, + overflow: TextOverflow.ellipsis, + style: hoverValueEntry, + ), + ], ), ); } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/legend.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/legend.dart index 9d2722bd421..800a84f5559 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/legend.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/legend.dart @@ -20,7 +20,7 @@ late final _legendHeight1Chart = scaleByFontFactor(200.0); late final _legendHeight2Charts = scaleByFontFactor(323.0); /// Padding for each title in the legend. -const _legendTitlePadding = EdgeInsets.fromLTRB(5, 0, 0, 4); +const _legendTitlePadding = EdgeInsets.only(left: 5, bottom: 4); class MemoryChartLegend extends StatelessWidget { const MemoryChartLegend({ @@ -194,7 +194,7 @@ class LegendRow extends StatelessWidget { return Expanded( child: Container( - padding: const EdgeInsets.fromLTRB(10, 0, 0, 2), + padding: const EdgeInsets.only(left: 10, bottom: 2), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: rowChildren, diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_android_chart.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_android_chart.dart index 00fb331d2a1..79704fce003 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_android_chart.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_android_chart.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; import '../../../../shared/charts/chart.dart'; import '../../../../shared/charts/chart_controller.dart'; import '../../../../shared/charts/chart_trace.dart' as trace; +import '../../../../shared/charts/chart_trace.dart' show ChartSymbol, ChartType; import '../../../../shared/primitives/auto_dispose.dart'; import '../../../../shared/theme.dart'; import '../../../../shared/utils.dart'; @@ -243,10 +244,10 @@ class MemoryAndroidChartState extends State // Stack trace final stackIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: stackColor, - symbol: trace.ChartSymbol.disc, + symbol: ChartSymbol.disc, diameter: 1.5, ), stacked: true, @@ -260,10 +261,10 @@ class MemoryAndroidChartState extends State // Java heap trace. final javaHeapIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: javaColor, - symbol: trace.ChartSymbol.disc, + symbol: ChartSymbol.disc, diameter: 1.5, ), stacked: true, @@ -277,10 +278,10 @@ class MemoryAndroidChartState extends State // Code trace final codeIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: codeColor, - symbol: trace.ChartSymbol.disc, + symbol: ChartSymbol.disc, diameter: 1.5, ), stacked: true, @@ -294,10 +295,10 @@ class MemoryAndroidChartState extends State // Graphics Trace final graphicIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: graphicColor, - symbol: trace.ChartSymbol.disc, + symbol: ChartSymbol.disc, diameter: 1.5, ), stacked: true, @@ -311,10 +312,10 @@ class MemoryAndroidChartState extends State // Native heap trace. final nativeHeapIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: nativeHeapColor, - symbol: trace.ChartSymbol.disc, + symbol: ChartSymbol.disc, diameter: 1.5, ), stacked: true, @@ -328,10 +329,10 @@ class MemoryAndroidChartState extends State // Other trace final otherIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: otherColor, - symbol: trace.ChartSymbol.disc, + symbol: ChartSymbol.disc, diameter: 1.5, ), stacked: true, @@ -345,10 +346,10 @@ class MemoryAndroidChartState extends State // System trace final systemIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: systemColor, - symbol: trace.ChartSymbol.disc, + symbol: ChartSymbol.disc, diameter: 1.5, ), stacked: true, @@ -365,7 +366,7 @@ class MemoryAndroidChartState extends State trace.ChartType.line, trace.PaintCharacteristics( color: totalColor, - symbol: trace.ChartSymbol.dashedLine, + symbol: ChartSymbol.dashedLine, strokeWidth: 2, ), name: AndroidTraceName.total.toString(), diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_events_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_events_pane.dart index 37a306e74b1..bc50569172f 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_events_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_events_pane.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; import '../../../../shared/charts/chart.dart'; import '../../../../shared/charts/chart_controller.dart'; import '../../../../shared/charts/chart_trace.dart' as trace; +import '../../../../shared/charts/chart_trace.dart' show ChartType; import '../../../../shared/primitives/auto_dispose.dart'; import '../../../../shared/theme.dart'; import '../../../../shared/utils.dart'; @@ -280,6 +281,9 @@ class MemoryEventsPaneState extends State } final extensionEventsIndex = _chartController.createTrace( + // TODO(jacobr): prefer-moving-to-variable doesn't understand that enum + // entries don't need to be moved to variables. + // ignore: prefer-moving-to-variable trace.ChartType.symbol, trace.PaintCharacteristics( color: Colors.purpleAccent[100]!, @@ -299,6 +303,9 @@ class MemoryEventsPaneState extends State ); final snapshotIndex = _chartController.createTrace( + // TODO(jacobr): prefer-moving-to-variable doesn't understand that enum + // entries don't need to be moved to variables. + // ignore: prefer-moving-to-variable trace.ChartType.symbol, trace.PaintCharacteristics( color: Colors.green, @@ -317,7 +324,7 @@ class MemoryEventsPaneState extends State // Auto-snapshot final autoSnapshotIndex = _chartController.createTrace( - trace.ChartType.symbol, + ChartType.symbol, trace.PaintCharacteristics( color: Colors.red, strokeWidth: 3, @@ -335,7 +342,7 @@ class MemoryEventsPaneState extends State // Manual GC final manualGCIndex = _chartController.createTrace( - trace.ChartType.symbol, + ChartType.symbol, trace.PaintCharacteristics( color: Colors.blue, strokeWidth: 3, @@ -356,7 +363,7 @@ class MemoryEventsPaneState extends State // Monitor final monitorIndex = _chartController.createTrace( - trace.ChartType.symbol, + ChartType.symbol, trace.PaintCharacteristics( color: mainMonitorColor, strokeWidth: 3, @@ -373,7 +380,7 @@ class MemoryEventsPaneState extends State ); final monitorResetIndex = _chartController.createTrace( - trace.ChartType.symbol, + ChartType.symbol, trace.PaintCharacteristics.concentric( color: Colors.grey[600]!, strokeWidth: 4, @@ -393,7 +400,7 @@ class MemoryEventsPaneState extends State // VM GC final gcIndex = _chartController.createTrace( - trace.ChartType.symbol, + ChartType.symbol, trace.PaintCharacteristics( color: Colors.blue, symbol: trace.ChartSymbol.disc, diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_vm_chart.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_vm_chart.dart index 669b52a2e1f..25b7a38dfb6 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_vm_chart.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/memory_vm_chart.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; import '../../../../shared/charts/chart.dart'; import '../../../../shared/charts/chart_controller.dart'; import '../../../../shared/charts/chart_trace.dart' as trace; +import '../../../../shared/charts/chart_trace.dart' show ChartType, ChartSymbol; import '../../../../shared/primitives/auto_dispose.dart'; import '../../../../shared/theme.dart'; import '../../../../shared/utils.dart'; @@ -198,7 +199,7 @@ class MemoryVMChartState extends State } final externalIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: externalColor, symbol: trace.ChartSymbol.disc, @@ -215,7 +216,7 @@ class MemoryVMChartState extends State // Used Heap final usedIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: usedColor, symbol: trace.ChartSymbol.disc, @@ -232,11 +233,11 @@ class MemoryVMChartState extends State // Heap Capacity final capacityIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: capacityColor, diameter: 0.0, - symbol: trace.ChartSymbol.dashedLine, + symbol: ChartSymbol.dashedLine, ), name: VmTraceName.capacity.toString(), ); @@ -248,10 +249,10 @@ class MemoryVMChartState extends State // RSS final rSSIndex = _chartController.createTrace( - trace.ChartType.line, + ChartType.line, trace.PaintCharacteristics( color: rssColor, - symbol: trace.ChartSymbol.dashedLine, + symbol: ChartSymbol.dashedLine, strokeWidth: 2, ), name: VmTraceName.rSS.toString(), 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 ffc6d5915d6..dad98de3b4d 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 @@ -77,7 +77,7 @@ class DiffPaneController extends DisposableController { derived._updateValues(); } - Future clearSnapshots() async { + void clearSnapshots() { final snapshots = core._snapshots; for (var i = 1; i < snapshots.value.length; i++) { snapshots.value[i].dispose(); 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 eb409105814..71c45cce3cf 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 @@ -66,12 +66,12 @@ class _ListControlPane extends StatelessWidget { icon: Icons.block, tooltip: 'Clear all snapshots', onPressed: clearAllEnabled - ? () async { + ? () { ga.select( gac.memory, gac.MemoryEvent.diffClearSnapshots, ); - unawaited(controller.clearSnapshots()); + controller.clearSnapshots(); } : null, ) @@ -153,7 +153,7 @@ class _SnapshotListItems extends StatefulWidget { class _SnapshotListItemsState extends State<_SnapshotListItems> with AutoDisposeMixin { - final _headerHeight = 1.20 * defaultRowHeight; + final _headerHeight = 1.2 * defaultRowHeight; late final ScrollController _scrollController; @override diff --git a/packages/devtools_app/lib/src/screens/memory/panes/leaks/diagnostics/model.dart b/packages/devtools_app/lib/src/screens/memory/panes/leaks/diagnostics/model.dart index c37f465f9c8..6b070f38342 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/leaks/diagnostics/model.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/leaks/diagnostics/model.dart @@ -37,13 +37,14 @@ class NotGCedAnalyzerTask { required this.reports, }); - factory NotGCedAnalyzerTask.fromJson(Map json) => + factory NotGCedAnalyzerTask.fromJson(Map json) => NotGCedAnalyzerTask( - reports: (json[_JsonFields.reports] as List) - .cast>() - .map((e) => LeakReport.fromJson(e)) + reports: (json[_JsonFields.reports] as List) + .map((e) => LeakReport.fromJson((e as Map).cast())) .toList(), - heap: AdaptedHeapData.fromJson(json[_JsonFields.heap]), + heap: AdaptedHeapData.fromJson( + json[_JsonFields.heap] as Map, + ), ); static Future fromSnapshot( @@ -59,7 +60,7 @@ class NotGCedAnalyzerTask { final AdaptedHeapData heap; final List reports; - Map toJson() => { + Map toJson() => { _JsonFields.reports: reports.map((e) => e.toJson()).toList(), _JsonFields.heap: heap.toJson(), }; diff --git a/packages/devtools_app/lib/src/screens/memory/shared/heap/model.dart b/packages/devtools_app/lib/src/screens/memory/shared/heap/model.dart index 55aef99bad8..144ebb4efa8 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/heap/model.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/heap/model.dart @@ -39,8 +39,8 @@ class AdaptedHeapData { final createdJson = json[_JsonFields.created]; return AdaptedHeapData( - (json[_JsonFields.objects] as List) - .map((e) => AdaptedHeapObject.fromJson(e)) + (json[_JsonFields.objects] as List) + .map((e) => AdaptedHeapObject.fromJson(e as Map)) .toList(), created: createdJson == null ? null : DateTime.parse(createdJson), rootIndex: json[_JsonFields.rootIndex] ?? _defaultRootIndex, @@ -238,21 +238,21 @@ class AdaptedHeapObject { factory AdaptedHeapObject.fromHeapSnapshotObject(HeapSnapshotObject object) { return AdaptedHeapObject( code: object.identityHashCode, - references: List.from(object.references), + references: List.of(object.references), heapClass: HeapClassName.fromHeapSnapshotClass(object.klass), shallowSize: object.shallowSize, ); } - factory AdaptedHeapObject.fromJson(Map json) => + factory AdaptedHeapObject.fromJson(Map json) => AdaptedHeapObject( - code: json[_JsonFields.code], - references: (json[_JsonFields.references] as List).cast(), + code: json[_JsonFields.code] as int, + references: (json[_JsonFields.references] as List).cast(), heapClass: HeapClassName( - className: json[_JsonFields.klass], + className: json[_JsonFields.klass] as String, library: json[_JsonFields.library], ), - shallowSize: json[_JsonFields.shallowSize] ?? 0, + shallowSize: (json[_JsonFields.shallowSize] ?? 0) as int, ); final List references; 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 e6d7769bdb3..f4f64c27952 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 @@ -25,13 +25,11 @@ Widget createDashWidget(Color color) { } Widget createSolidLine(Color color) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 1.0), - child: Container( - height: 6, - width: 20, - color: color, - ), + return Container( + height: 6, + width: 20, + color: color, + margin: const EdgeInsets.symmetric(horizontal: 1.0), ); } 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 2065cfb5712..72d993de16b 100644 --- a/packages/devtools_app/lib/src/screens/network/network_controller.dart +++ b/packages/devtools_app/lib/src/screens/network/network_controller.dart @@ -10,7 +10,7 @@ import 'package:vm_service/vm_service.dart'; import '../../shared/config_specific/logger/allowed_error.dart'; import '../../shared/globals.dart'; import '../../shared/http/http_request_data.dart'; -import '../../shared/http/http_service.dart'; +import '../../shared/http/http_service.dart' as http_service; import '../../shared/primitives/utils.dart'; import '../../shared/ui/filter.dart'; import '../../shared/ui/search.dart'; @@ -149,7 +149,7 @@ class NetworkController sockets, httpRequests, _timelineMicrosOffset, - currentValues: List.from(requests.value.requests), + currentValues: List.of(requests.value.requests), invalidRequests: [], outstandingRequestsMap: Map.from(requests.value.outstandingHttpRequests), ); @@ -205,7 +205,7 @@ class NetworkController // TODO(kenz): only call these if http logging and socket profiling are not // already enabled. Listen to service manager streams for this info. await Future.wait([ - HttpService.toggleHttpRequestLogging(true), + http_service.toggleHttpRequestLogging(true), networkService.toggleSocketProfiling(true), ]); togglePolling(true); 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 4d503a11c92..0e160062337 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 @@ -53,33 +53,6 @@ class HttpRequestHeadersView extends StatelessWidget { final DartIOHttpRequestData data; - Widget _buildRow( - BuildContext context, - String key, - dynamic value, - BoxConstraints constraints, - ) { - return Container( - width: constraints.minWidth, - padding: _rowPadding, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SelectableText( - '$key: ', - style: Theme.of(context).textTheme.titleSmall, - ), - Expanded( - child: SelectableText( - value, - minLines: 1, - ), - ), - ], - ), - ); - } - @override Widget build(BuildContext context) { final general = data.general; @@ -93,14 +66,7 @@ class HttpRequestHeadersView extends StatelessWidget { 'General', [ for (final entry in general.entries) - _buildRow( - context, - // TODO(kenz): ensure the default case of `entry.key` looks - // fine. - entry.key, - entry.value.toString(), - constraints, - ), + _Row(entry: entry, constraints: constraints), ], key: generalKey, ), @@ -109,12 +75,7 @@ class HttpRequestHeadersView extends StatelessWidget { [ if (responseHeaders != null) for (final entry in responseHeaders.entries) - _buildRow( - context, - entry.key, - entry.value.toString(), - constraints, - ), + _Row(entry: entry, constraints: constraints), ], key: responseHeadersKey, ), @@ -123,12 +84,7 @@ class HttpRequestHeadersView extends StatelessWidget { [ if (requestHeaders != null) for (final entry in requestHeaders.entries) - _buildRow( - context, - entry.key, - entry.value.toString(), - constraints, - ), + _Row(entry: entry, constraints: constraints), ], key: requestHeadersKey, ) @@ -139,6 +95,39 @@ class HttpRequestHeadersView extends StatelessWidget { } } +class _Row extends StatelessWidget { + const _Row({ + required this.entry, + required this.constraints, + }); + + final MapEntry entry; + final BoxConstraints constraints; + + @override + Widget build(BuildContext context) { + return Container( + width: constraints.minWidth, + padding: _rowPadding, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SelectableText( + '${entry.key}: ', + style: Theme.of(context).textTheme.titleSmall, + ), + Expanded( + child: SelectableText( + '${entry.value}', + minLines: 1, + ), + ), + ], + ), + ); + } +} + class HttpRequestView extends StatelessWidget { const HttpRequestView(this.data); @@ -513,9 +502,8 @@ class NetworkRequestOverviewView extends StatelessWidget { _buildRow( context: context, title: 'Timing', - child: data is WebSocket - ? _buildSocketTimeGraph(context) - : _buildHttpTimeGraph(context), + child: + data is WebSocket ? _buildSocketTimeGraph() : _buildHttpTimeGraph(), ), const SizedBox(height: denseSpacing), _buildRow( @@ -565,7 +553,7 @@ class NetworkRequestOverviewView extends StatelessWidget { ); } - Widget _buildHttpTimeGraph(BuildContext context) { + Widget _buildHttpTimeGraph() { final data = this.data as DartIOHttpRequestData; if (data.duration == null || data.instantEvents.isEmpty) { return Container( @@ -666,7 +654,7 @@ class NetworkRequestOverviewView extends StatelessWidget { ]; } - Widget _buildSocketTimeGraph(BuildContext context) { + Widget _buildSocketTimeGraph() { return Container( key: socketTimingGraphKey, height: _timingGraphHeight, 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 442f121352c..67a94b3673c 100644 --- a/packages/devtools_app/lib/src/screens/network/network_screen.dart +++ b/packages/devtools_app/lib/src/screens/network/network_screen.dart @@ -384,7 +384,7 @@ class UriColumn extends ColumnData ); @override - dynamic getValue(NetworkRequest dataObject) { + String getValue(NetworkRequest dataObject) { return dataObject.uri; } @@ -413,7 +413,7 @@ class MethodColumn extends ColumnData { MethodColumn() : super('Method', fixedWidthPx: scaleByFontFactor(70)); @override - dynamic getValue(NetworkRequest dataObject) { + String getValue(NetworkRequest dataObject) { return dataObject.method; } } @@ -436,11 +436,11 @@ class ActionsColumn extends ColumnData bool get includeHeader => false; @override - dynamic getValue(NetworkRequest dataObject) { + String getValue(NetworkRequest dataObject) { return ''; } - List _buildOptions(BuildContext context, NetworkRequest data) { + List _buildOptions(NetworkRequest data) { return [ if (data is DartIOHttpRequestData) ...[ PopupMenuItem( @@ -450,7 +450,6 @@ class ActionsColumn extends ColumnData copyToClipboard( data.uri, 'Copied the URL to the clipboard', - context, ), ); }, @@ -462,7 +461,6 @@ class ActionsColumn extends ColumnData copyToClipboard( CurlCommand.from(data).toString(), 'Copied the cURL command to the clipboard', - context, ), ); }, @@ -478,7 +476,7 @@ class ActionsColumn extends ColumnData bool isRowSelected = false, VoidCallback? onPressed, }) { - final options = _buildOptions(context, data); + final options = _buildOptions(data); // Only show the actions button when there are options and the row is // currently selected. @@ -504,7 +502,7 @@ class StatusColumn extends ColumnData ); @override - dynamic getValue(NetworkRequest dataObject) { + String? getValue(NetworkRequest dataObject) { return dataObject.status; } @@ -539,7 +537,7 @@ class TypeColumn extends ColumnData { ); @override - dynamic getValue(NetworkRequest dataObject) { + String getValue(NetworkRequest dataObject) { return dataObject.type; } @@ -558,7 +556,7 @@ class DurationColumn extends ColumnData { ); @override - dynamic getValue(NetworkRequest dataObject) { + int? getValue(NetworkRequest dataObject) { return dataObject.duration?.inMilliseconds; } @@ -583,7 +581,7 @@ class TimestampColumn extends ColumnData { ); @override - dynamic getValue(NetworkRequest dataObject) { + DateTime? getValue(NetworkRequest dataObject) { return dataObject.startTimestamp; } 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 e8905760a21..aaa4758f976 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 @@ -206,6 +206,8 @@ class _TrackWidgetBuildsSettingState extends State assert(!(trackAllWidgets && trackUserWidgets)); _tracked.value = trackUserWidgets || trackAllWidgets; + // Double nested conditinoal expressions are hard to read. + // ignore: prefer-conditional-expression if (_tracked.value) { _selectedScope.value = trackUserWidgets ? TrackWidgetBuildsScope.userCreated 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 55e70e31e2d..a715125a4d8 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 @@ -73,7 +73,7 @@ class TimelineStreamSettings extends StatelessWidget { style: theme.subtleTextStyle, ), ), - ..._timelineStreams(theme, advanced: false), + ..._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 // the distinction, however. @@ -98,12 +98,11 @@ class TimelineStreamSettings extends StatelessWidget { style: theme.subtleTextStyle, ), ), - ..._timelineStreams(theme, advanced: true), + ..._timelineStreams(advanced: true), ]; } - List _timelineStreams( - ThemeData theme, { + List _timelineStreams({ required bool advanced, }) { final streams = advanced 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 ccb3126bcbc..59341bce09d 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 @@ -28,6 +28,7 @@ import 'flutter_frame_model.dart'; import 'flutter_frames_controller.dart'; // Turn this flag on to see when flutter frames are linked with timeline events. +// ignore: avoid-global-state bool debugFrames = false; class FlutterFramesChart extends StatelessWidget { @@ -443,11 +444,11 @@ class FlutterFramesChartItem extends StatelessWidget { if (debugFrames) { if (frame.timelineEventData.uiEvent == null) { - uiColor = uiColor.darken(.5); + uiColor = uiColor.darken(0.5); } if (frame.timelineEventData.rasterEvent == null) { - rasterColor = rasterColor.darken(.5); - shaderColor = shaderColor.darken(.5); + rasterColor = rasterColor.darken(0.5); + shaderColor = shaderColor.darken(0.5); } } @@ -461,17 +462,16 @@ class FlutterFramesChartItem extends StatelessWidget { color: uiColor, ); - final shaderToRasterRatio = - frame.shaderDuration.inMilliseconds / frame.rasterTime.inMilliseconds; + final shaderDuration = frame.shaderDuration.inMilliseconds; + final rasterTime = frame.rasterTime.inMilliseconds; + final shaderToRasterRatio = shaderDuration / rasterTime; final raster = Column( children: [ Container( key: Key('frame ${frame.id} - raster'), width: defaultFrameWidth / 2, - height: ((frame.rasterTime.inMilliseconds - - frame.shaderDuration.inMilliseconds) / - msPerPx) + height: ((frame.rasterTime.inMilliseconds - shaderDuration) / msPerPx) .clamp(0.0, availableChartHeight * (1 - shaderToRasterRatio)), color: rasterColor, ), @@ -479,7 +479,7 @@ class FlutterFramesChartItem extends StatelessWidget { Container( key: Key('frame ${frame.id} - shaders'), width: defaultFrameWidth / 2, - height: (frame.shaderDuration.inMilliseconds / msPerPx) + height: (shaderDuration / msPerPx) .clamp(0.0, availableChartHeight * shaderToRasterRatio), color: shaderColor, ), 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 744363bfd82..edab8b77499 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 @@ -225,4 +225,9 @@ class FlutterFramesController extends PerformanceFeatureController { _displayRefreshRate.value = offlineData.displayRefreshRate; } + + @override + Future onBecomingActive() { + return Future.value(); + } } diff --git a/packages/devtools_app/lib/src/screens/performance/panes/raster_stats/raster_stats_controller.dart b/packages/devtools_app/lib/src/screens/performance/panes/raster_stats/raster_stats_controller.dart index 078358d76ce..ccfa3b6cab9 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/raster_stats/raster_stats_controller.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/raster_stats/raster_stats_controller.dart @@ -68,4 +68,14 @@ class RasterStatsController extends PerformanceFeatureController { void clearData() { setData(null); } + + @override + Future init() { + return Future.value(); + } + + @override + Future onBecomingActive() { + return Future.value(); + } } diff --git a/packages/devtools_app/lib/src/screens/performance/panes/raster_stats/raster_stats_model.dart b/packages/devtools_app/lib/src/screens/performance/panes/raster_stats/raster_stats_model.dart index 1a4bf49da15..aa5eddbd263 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/raster_stats/raster_stats_model.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/raster_stats/raster_stats_model.dart @@ -117,7 +117,7 @@ class LayerSnapshot { (json[_topKey] as num).toDouble(), ); final imageBytes = Uint8List.fromList( - (json[_snapshotJsonKey] as List).cast(), + (json[_snapshotJsonKey] as List).cast(), ); return LayerSnapshot( id: id, 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 c2c4cdf9c3e..a67b353b923 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 @@ -96,8 +96,8 @@ class LocationMap { return location; } - Map toJson() { - final json = {}; + Map toJson() { + final json = {}; final pathToLocations = >{}; for (var location in _locationMap.values) { if (location.isResolved) { @@ -181,11 +181,11 @@ class LocationMap { class RebuildCountModel { RebuildCountModel(); - RebuildCountModel.parse(Map json) { + RebuildCountModel.parse(Map json) { if (json.isEmpty) return; - locationMap.processLocationMap(json[_locationsKey]); + locationMap.processLocationMap(json[_locationsKey] as Map); final frames = - (json[_framesKey] as List).cast>(); + (json[_framesKey] as List).cast>(); frames.forEach(processRebuildsForFrame); } @@ -211,12 +211,12 @@ class RebuildCountModel { bool get isNotEmpty => _rebuildsForFrame.isNotEmpty; - Map? toJson() { + Map? toJson() { if (_rebuildsForFrame.isEmpty) { // No need to encode data unless there were actually rebuilds reported. return null; } - final frames = []; + final frames = []; _rebuildsForFrame.forEach((id, rebuilds) { final events = []; @@ -227,7 +227,7 @@ class RebuildCountModel { } frames.add({_frameNumberKey: id, _eventsKey: events}); }); - return { + return { _locationsKey: locationMap.toJson(), _framesKey: frames, }; diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/event_details.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/event_details.dart index fba6fd977ba..b0d3cbca1c9 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/event_details.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/event_details.dart @@ -193,7 +193,7 @@ class EventSummary extends StatelessWidget { if (event.isAsyncEvent) Flexible( fit: FlexFit.tight, - child: _asyncIdTile(context), + child: _asyncIdTile(), ), Flexible( fit: FlexFit.tight, @@ -212,35 +212,33 @@ class EventSummary extends StatelessWidget { ], ), ), - if (_connectedEvents.isNotEmpty) _buildConnectedEvents(context), - if (_eventArgs.isNotEmpty) _buildArguments(context), + if (_connectedEvents.isNotEmpty) _buildConnectedEvents(), + if (_eventArgs.isNotEmpty) _buildArguments(), ], ); } - Widget _asyncIdTile(BuildContext context) { + Widget _asyncIdTile() { late final String asyncId; - if (event is OfflineTimelineEvent) { - asyncId = event.traceEvents.first.event.id; - } else { - asyncId = (event as AsyncTimelineEvent).asyncId; - } + asyncId = event is OfflineTimelineEvent + ? event.traceEvents.first.event.id as String + : (event as AsyncTimelineEvent).asyncId; return EventMetaData( title: 'Async id', inlineValue: asyncId, ); } - Widget _buildConnectedEvents(BuildContext context) { + Widget _buildConnectedEvents() { return ExpandingEventMetaData( title: 'Connected events', children: [ - for (var e in _connectedEvents) _buildConnectedEvent(context, e), + for (var e in _connectedEvents) _buildConnectedEvent(e), ], ); } - Widget _buildConnectedEvent(BuildContext context, TimelineEvent e) { + Widget _buildConnectedEvent(TimelineEvent e) { final eventArgs = { 'startTime': msText(e.time.start! - event.time.start!), 'args': e.traceEvents.first.event.args, @@ -254,7 +252,7 @@ class EventSummary extends StatelessWidget { ); } - Widget _buildArguments(BuildContext context) { + Widget _buildArguments() { return ExpandingEventMetaData( title: 'Arguments', children: [ diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/legacy_event_processor.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/legacy_event_processor.dart index f9c6e23cdad..7b8f1ece204 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/legacy_event_processor.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/legacy_event_processor.dart @@ -137,6 +137,8 @@ class LegacyEventProcessor extends BaseTraceEventProcessor { (a, b) => a.time.start!.inMicroseconds.compareTo(b.time.start!.inMicroseconds), ); + // This logic is a little clearer written with if, else. + // ignore: prefer-conditional-expression if (_data.timelineEvents.isNotEmpty) { _data.time = TimeRange() // We process trace events in timestamp order, so we can ensure the first diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/timeline_flame_chart.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/timeline_flame_chart.dart index eeb1d2f27a7..d223c500f23 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/timeline_flame_chart.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/timeline_flame_chart.dart @@ -194,9 +194,18 @@ class TimelineFlameChartState @override void initState() { super.initState(); + // addAndGet has crucial side effects so moving to a variable is not + // feasible. + // ignore: prefer-moving-to-variable _groupLabelScrollController = verticalControllerGroup.addAndGet(); _previousInGroupButtonsScrollController = + // addAndGet has crucial side effects so moving to a variable is not + // feasible. + // ignore: prefer-moving-to-variable verticalControllerGroup.addAndGet(); + // addAndGet has crucial side effects so moving to a variable is not + // feasible. + // ignore: prefer-moving-to-variable _nextInGroupButtonsScrollController = verticalControllerGroup.addAndGet(); } @@ -450,7 +459,7 @@ class TimelineFlameChartState rect: Rect.fromLTRB(left, flameChartNodeTop, right, rowHeight), colorPair: ThemedColorPair.from(colorPair), data: event, - onSelected: (dynamic event) => widget.onDataSelected(event), + onSelected: widget.onDataSelected, sectionIndex: section, ); chartNodesByEvent[event] = node; 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 04298c1e9c1..0e2bc480e4b 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 @@ -106,6 +106,8 @@ class PerfettoControllerImpl extends PerfettoController { ..height = '100%' ..width = '100%'; + // This ignore is required due to + // https://github.com/flutter/flutter/issues/41563 // ignore: undefined_prefixed_name final registered = ui.platformViewRegistry.registerViewFactory( viewId, @@ -130,11 +132,11 @@ class PerfettoControllerImpl extends PerfettoController { @override void loadTrace(List devToolsTraceEvents) { if (!timelineEventsController.isActiveFeature) { - pendingTraceEventsToLoad = List.from(devToolsTraceEvents); + pendingTraceEventsToLoad = List.of(devToolsTraceEvents); return; } pendingTraceEventsToLoad = null; - _activeTraceEvents.value = List.from(devToolsTraceEvents); + _activeTraceEvents.value = List.of(devToolsTraceEvents); } @override 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 174f717c27c..588a55ce82c 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 @@ -53,9 +53,7 @@ class _PerfettoState extends State with AutoDisposeMixin { } void _loadActiveTrace() { - unawaited( - _viewController._loadTrace(_perfettoController.activeTraceEvents.value), - ); + _viewController._loadTrace(_perfettoController.activeTraceEvents.value); } void _scrollToActiveTimeRange() { @@ -168,7 +166,7 @@ class _PerfettoViewController extends DisposableController } } - Future _loadTrace(List devToolsTraceEvents) async { + void _loadTrace(List devToolsTraceEvents) { final encodedJson = jsonEncode({ 'traceEvents': devToolsTraceEvents .map((eventWrapper) => eventWrapper.event.json) @@ -221,7 +219,7 @@ class _PerfettoViewController extends DisposableController ); } - void _postMessage(dynamic message) async { + void _postMessage(Object message) async { await _perfettoIFrameReady.future; assert( perfettoController.perfettoIFrame.contentWindow != null, @@ -236,10 +234,10 @@ class _PerfettoViewController extends DisposableController void _postMessageWithId( String id, { - Map args = const {}, + Map args = const {}, bool perfettoIgnore = false, }) { - final message = { + final message = { 'msgId': id, if (perfettoIgnore) 'perfettoIgnore': true, }..addAll(args); diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto_controller.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto_controller.dart index 000aed379dd..60ce523adb2 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto_controller.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto_controller.dart @@ -35,11 +35,11 @@ abstract class PerfettoController extends DisposableController { void init() {} - void onBecomingActive() async {} + void onBecomingActive() {} - void loadTrace(List devToolsTraceEvents) async {} + void loadTrace(List devToolsTraceEvents) {} - void scrollToTimeRange(TimeRange timeRange) async {} + void scrollToTimeRange(TimeRange timeRange) {} - void clear() async {} + void clear() {} } diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto_event_processor.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto_event_processor.dart index f0d1070a28a..1b9d40d523e 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto_event_processor.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/perfetto_event_processor.dart @@ -96,7 +96,7 @@ extension FrameIdentifierExtension on TraceEventWrapper { /// Returns the flutter frame number for this trace event, or null if it does /// not exist. int? get flutterFrameNumber { - final frameNumber = event.args?[TraceEvent.frameNumberArg]; + final frameNumber = event.args?[TraceEvent.frameNumberArg] as String?; if (frameNumber == null) return null; return int.tryParse(frameNumber); } 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 d51234fcdd6..876b4b40229 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 @@ -15,7 +15,7 @@ import '../../../../shared/config_specific/logger/logger.dart'; import '../../../../shared/feature_flags.dart'; import '../../../../shared/future_work_tracker.dart'; import '../../../../shared/globals.dart'; -import '../../../../shared/http/http_service.dart'; +import '../../../../shared/http/http_service.dart' as http_service; import '../../../../shared/primitives/auto_dispose.dart'; import '../../../../shared/primitives/trace_event.dart'; import '../../../../shared/primitives/trees.dart'; @@ -139,7 +139,6 @@ class TimelineEventsController extends PerformanceFeatureController if (_perfettoMode) { perfettoController.onBecomingActive(); } - await super.onBecomingActive(); } Future _initForServiceConnection() async { @@ -226,7 +225,7 @@ class TimelineEventsController extends PerformanceFeatureController int? uiThreadId; int? rasterThreadId; for (TraceEvent event in threadNameEvents) { - final name = event.args!['name']; + final name = event.args!['name'] as String; if (isFlutterApp && isInitialUpdate) { // Android: "1.ui (12652)" @@ -470,7 +469,7 @@ class TimelineEventsController extends PerformanceFeatureController } Future toggleHttpRequestLogging(bool state) async { - await HttpService.toggleHttpRequestLogging(state); + await http_service.toggleHttpRequestLogging(state); _httpTimelineLoggingEnabled.value = state; } @@ -772,7 +771,7 @@ class LegacyTimelineEventsController with SearchControllerMixin { } } } else { - final events = List.from(data!.timelineEvents); + final events = List.of(data!.timelineEvents); for (final event in events) { breadthFirstTraversal( event, 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 2b5b5b926cb..cf86bc77d28 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_controller.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_controller.dart @@ -261,11 +261,11 @@ abstract class PerformanceFeatureController extends DisposableController { } } - Future onBecomingActive() async {} + Future onBecomingActive(); - Future init() async {} + Future init(); - FutureOr setOfflineData(PerformanceData offlineData); + Future setOfflineData(PerformanceData offlineData); FutureOr clearData(); 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 2528dbf66e5..2408980e554 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_model.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_model.dart @@ -188,7 +188,7 @@ class TimelineEventGroup { bool _timestampsInitialized = false; List get sortedEventRoots => - _sortedEventRoots ??= List.from(rowIndexForEvent.keys) + _sortedEventRoots ??= List.of(rowIndexForEvent.keys) .where((event) => event.isRoot) .toList() ..sort( @@ -254,12 +254,14 @@ class TimelineEventGroup { for (int i = 0; i < event.displayDepth; i++) { final displayRow = event.displayRows[i]; for (var e in displayRow) { + final timeStart = e.time.start!.inMicroseconds; + final timeEnd = e.time.end!.inMicroseconds; earliestTimestampMicros = _timestampsInitialized - ? math.min(e.time.start!.inMicroseconds, earliestTimestampMicros) - : e.time.start!.inMicroseconds; + ? math.min(timeStart, earliestTimestampMicros) + : timeEnd; latestTimestampMicros = _timestampsInitialized - ? math.max(e.time.end!.inMicroseconds, latestTimestampMicros) - : e.time.end!.inMicroseconds; + ? math.max(timeEnd, latestTimestampMicros) + : timeEnd; _timestampsInitialized = true; rows[row + i].events.add(e); @@ -316,12 +318,12 @@ class OfflinePerformanceData extends PerformanceData { .cast>(); final Map cpuProfileJson = - json[PerformanceData.cpuProfileKey] ?? {}; + json[PerformanceData.cpuProfileKey] ?? {}; final CpuProfileData? cpuProfileData = cpuProfileJson.isNotEmpty ? CpuProfileData.parse(cpuProfileJson) : null; final Map rasterStatsJson = - json[PerformanceData.rasterStatsKey] ?? {}; + json[PerformanceData.rasterStatsKey] ?? {}; final RasterStats? rasterStats = rasterStatsJson.isNotEmpty ? RasterStats.parse(rasterStatsJson) : null; @@ -343,7 +345,7 @@ class OfflinePerformanceData extends PerformanceData { final OfflineTimelineEvent? selectedEvent = selectedEventJson.isNotEmpty ? OfflineTimelineEvent( (selectedEventJson[TimelineEvent.firstTraceKey] ?? {}) - .cast(), + .cast(), ) : null; @@ -504,7 +506,7 @@ abstract class TimelineEvent extends TreeNode String? get name => traceEvents.first.event.name; - String? get groupKey => traceEvents.first.event.args!['filterKey']; + String? get groupKey => traceEvents.first.event.args!['filterKey'] as String?; Map get beginTraceEventJson => traceEvents.first.json; @@ -632,7 +634,7 @@ abstract class TimelineEvent extends TreeNode void removeChild(TimelineEvent childToRemove) { assert(children.contains(childToRemove)); - final List newChildren = List.from(childToRemove.children); + final List newChildren = List.of(childToRemove.children); newChildren.forEach(_addChild); children.remove(childToRemove); } @@ -774,7 +776,7 @@ class SyncTimelineEvent extends TimelineEvent { final frameNumber = traceEvents.first.event.args![TraceEvent.frameNumberArg]; return _flutterFrameNumber = - frameNumber != null ? int.tryParse(frameNumber) : null; + frameNumber != null ? int.tryParse(frameNumber as String) : null; } int? _flutterFrameNumber; @@ -861,7 +863,7 @@ class SyncTimelineEvent extends TimelineEvent { // code. class AsyncTimelineEvent extends TimelineEvent { AsyncTimelineEvent(TraceEventWrapper firstTraceEvent) - : _parentId = firstTraceEvent.event.args![parentIdKey], + : _parentId = firstTraceEvent.event.args![parentIdKey] as String?, super(firstTraceEvent) { type = TimelineEventType.async; } 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 a91665ceda7..4bc15437002 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_screen.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_screen.dart @@ -119,13 +119,13 @@ class PerformanceScreenBodyState extends State controller.offlinePerformanceData != null && controller.offlinePerformanceData!.frames.isNotEmpty; + final offlineMode = offlineController.offlineMode.value; final performanceScreen = Column( children: [ - if (!offlineController.offlineMode.value) _buildPerformanceControls(), + if (!offlineMode) _buildPerformanceControls(), const SizedBox(height: denseRowSpacing), if (isOfflineFlutterApp || - (!offlineController.offlineMode.value && - serviceManager.connectedApp!.isFlutterAppNow!)) + (!offlineMode && serviceManager.connectedApp!.isFlutterAppNow!)) FlutterFramesChart(controller.flutterFramesController), const Expanded(child: TabbedPerformanceView()), ], @@ -256,7 +256,7 @@ class SecondaryPerformanceControls extends StatelessWidget { OutlinedIconButton( icon: Icons.file_download, tooltip: 'Export data', - onPressed: () => _exportPerformanceData(context), + onPressed: _exportPerformanceData, ), const SizedBox(width: denseSpacing), SettingsOutlinedButton( @@ -266,7 +266,7 @@ class SecondaryPerformanceControls extends StatelessWidget { ); } - void _exportPerformanceData(BuildContext context) { + void _exportPerformanceData() { ga.select(gac.performance, gac.export); controller.exportData(); // TODO(kenz): investigate if we need to do any error handling here. Is the diff --git a/packages/devtools_app/lib/src/screens/performance/performance_utils.dart b/packages/devtools_app/lib/src/screens/performance/performance_utils.dart index 9fc81ca01b7..17bb050763f 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_utils.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_utils.dart @@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart'; import '../../shared/primitives/utils.dart'; import 'performance_model.dart'; +// TODO(jacobr): make this a top level method. // ignore: avoid_classes_with_only_static_members class PerformanceUtils { static String computeEventGroupKey( diff --git a/packages/devtools_app/lib/src/screens/performance/timeline_streams.dart b/packages/devtools_app/lib/src/screens/performance/timeline_streams.dart index 414cfb30665..41327eba73a 100644 --- a/packages/devtools_app/lib/src/screens/performance/timeline_streams.dart +++ b/packages/devtools_app/lib/src/screens/performance/timeline_streams.dart @@ -102,7 +102,7 @@ class TimelineStreamManager extends Disposer { /// This method is responsible for updating the value of /// [TimelineStream.recorded] for each stream to match the value on the VM. @visibleForTesting - void handleTimelineEvent(Event event) async { + void handleTimelineEvent(Event event) { if (event.kind == EventKind.kTimelineStreamSubscriptionsUpdate) { final newRecordedStreams = event.updatedStreams ?? []; for (final stream in _streams.values) { diff --git a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_columns.dart b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_columns.dart index 1ea5b3571ea..c1270811697 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_columns.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_columns.dart @@ -40,8 +40,7 @@ class SelfTimeColumn extends ColumnData { } @override - dynamic getValue(CpuStackFrame dataObject) => - dataObject.selfTime.inMicroseconds; + int getValue(CpuStackFrame dataObject) => dataObject.selfTime.inMicroseconds; @override String getDisplayValue(CpuStackFrame dataObject) { @@ -74,8 +73,7 @@ class TotalTimeColumn extends ColumnData { } @override - dynamic getValue(CpuStackFrame dataObject) => - dataObject.totalTime.inMicroseconds; + int getValue(CpuStackFrame dataObject) => dataObject.totalTime.inMicroseconds; @override String getDisplayValue(CpuStackFrame dataObject) { @@ -90,7 +88,7 @@ class TotalTimeColumn extends ColumnData { class MethodNameColumn extends TreeColumnData { MethodNameColumn() : super('Method'); @override - dynamic getValue(CpuStackFrame dataObject) => dataObject.name; + String getValue(CpuStackFrame dataObject) => dataObject.name; @override String getDisplayValue(CpuStackFrame dataObject) { @@ -110,7 +108,7 @@ class SourceColumn extends ColumnData SourceColumn() : super.wide('Source', alignment: ColumnAlignment.right); @override - dynamic getValue(CpuStackFrame dataObject) => + String getValue(CpuStackFrame dataObject) => dataObject.packageUriWithSourceLine; @override diff --git a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_controller.dart b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_controller.dart index 5c8c8975165..342e28f2b0a 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_controller.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_controller.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; -import 'package:vm_service/vm_service.dart'; +import 'package:vm_service/vm_service.dart' hide Error; import '../../service/vm_flags.dart' as vm_flags; import '../../shared/analytics/analytics.dart' as ga; @@ -166,7 +166,7 @@ class CpuProfilerController ? true : profilerFlagNotifier?.value.valueAsString == 'true'; - Future enableCpuProfiler() { + Future enableCpuProfiler() { return serviceManager.service!.enableCpuProfiler(); } @@ -231,8 +231,6 @@ class CpuProfilerController required String processId, required bool storeAsUserTagNone, required bool shouldApplyFilters, - required bool shouldRefreshSearchMatches, - required bool isCodeProfile, }) async { await cpuProfiles.process( transformer: transformer, @@ -285,8 +283,6 @@ class CpuProfilerController processId: processId, storeAsUserTagNone: storeAsUserTagNone, shouldApplyFilters: shouldApplyFilters, - shouldRefreshSearchMatches: shouldRefreshSearchMatches, - isCodeProfile: type == CpuProfilerViewType.code, ).then((p) => p.getActive(type)); _dataNotifier.value = cpuProfileData; @@ -458,13 +454,16 @@ class CpuProfilerController _dataNotifier.value = await processDataForTag(tag).then( (e) => e.getActive(viewType.value), ); - } catch (e) { + } catch (e, stackTrace) { // In the event of an error, reset the data to the original CPU profile. final filteredOriginalData = cpuProfileStore.lookupProfile( label: _wrapWithFilterSuffix(userTagNone), )!; _dataNotifier.value = filteredOriginalData.getActive(viewType.value); - throw Exception('Error loading data with tag "$tag": ${e.toString()}'); + Error.throwWithStackTrace( + Exception('Error loading data with tag "$tag": ${e.toString()}'), + stackTrace, + ); } finally { _processingNotifier.value = false; } 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 ebc2b7da776..72de6a9226d 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 @@ -182,24 +182,25 @@ class CpuProfileData { // Initialize all stack frames. final stackFrames = {}; - final Map stackFramesJson = - jsonDecode(jsonEncode(json[stackFramesKey] ?? {})); - for (final MapEntry entry in stackFramesJson.entries) { - final stackFrameJson = entry.value; - final resolvedUrl = stackFrameJson[resolvedUrlKey] ?? ''; - final packageUri = stackFrameJson[resolvedPackageUriKey] ?? resolvedUrl; + final Map stackFramesJson = + jsonDecode(jsonEncode(json[stackFramesKey] ?? {})); + for (final entry in stackFramesJson.entries) { + final stackFrameJson = entry.value as Map; + final resolvedUrl = (stackFrameJson[resolvedUrlKey] as String?) ?? ''; + final packageUri = + (stackFrameJson[resolvedPackageUriKey] as String?) ?? resolvedUrl; final stackFrame = CpuStackFrame( id: entry.key, - name: getSimpleStackFrameName(stackFrameJson[nameKey]), - verboseName: stackFrameJson[nameKey], - category: stackFrameJson[categoryKey], + name: getSimpleStackFrameName(stackFrameJson[nameKey] as String?), + verboseName: stackFrameJson[nameKey] as String?, + category: stackFrameJson[categoryKey] as String?, // If the user is on a version of Flutter where resolvedUrl is not // included in the response, this will be null. If the frame is a native // frame, the this will be the empty string. rawUrl: resolvedUrl, packageUri: packageUri, - sourceLine: stackFrameJson[sourceLineKey], - parentId: stackFrameJson[parentIdKey] ?? rootId, + sourceLine: stackFrameJson[sourceLineKey] as int?, + parentId: (stackFrameJson[parentIdKey] as String?) ?? rootId, profileMetaData: profileMetaData, isTag: false, ); @@ -453,7 +454,7 @@ class CpuProfileData { final filteredCpuSamples = []; void includeSampleOrWalkUp( CpuSampleEvent sample, - Map sampleJson, + Map sampleJson, CpuStackFrame stackFrame, ) { if (includeFilter(stackFrame)) { @@ -472,7 +473,7 @@ class CpuProfileData { } for (final sample in originalData.cpuSamples) { - final sampleJson = Map.from(sample.json); + final sampleJson = Map.from(sample.json); final leafStackFrame = originalData.stackFrames[sample.leafId]!; includeSampleOrWalkUp(sample, sampleJson, leafStackFrame); } @@ -560,7 +561,7 @@ class CpuProfileData { // of all stacks, regardless of entrypoint. This should never be seen in the // final output from this method. const int kRootId = 0; - final traceObject = { + final traceObject = { CpuProfileData.sampleCountKey: cpuSamples.sampleCount, CpuProfileData.samplePeriodKey: cpuSamples.samplePeriod, CpuProfileData.stackDepthKey: cpuSamples.maxStackDepth, @@ -584,7 +585,7 @@ class CpuProfileData { if (tree.frameId == kRootId) { continue; } - traceObject[CpuProfileData.traceEventsKey].add({ + (traceObject[CpuProfileData.traceEventsKey]! as List).add({ 'ph': 'P', // kind = sample event 'name': '', // Blank to keep about:tracing happy 'pid': cpuSamples.pid, @@ -763,8 +764,8 @@ class CpuProfileData { bool get isEmpty => profileMetaData.sampleCount == 0; @visibleForTesting - Map get stackFramesJson { - final framesJson = {}; + Map get stackFramesJson { + final framesJson = {}; for (final sf in stackFrames.values) { framesJson.addAll(sf.toJson); } @@ -1036,7 +1037,7 @@ class CpuStackFrame extends TreeNode category == other.category && sourceLine == other.sourceLine; - Map get toJson => { + Map get toJson => { id: { CpuProfileData.nameKey: verboseName, CpuProfileData.categoryKey: category, @@ -1084,7 +1085,7 @@ int stackFrameIdCompare(String a, String b) { final int aId = int.parse(a.substring(aDashIndex + 1)); final int bId = int.parse(b.substring(bDashIndex + 1)); return aId.compareTo(bId); - } catch (e) { + } catch (e, stackTrace) { String error = 'invalid stack frame '; if (aDashIndex == -1 && bDashIndex != -1) { error += 'id [$a]'; @@ -1093,7 +1094,7 @@ int stackFrameIdCompare(String a, String b) { } else { error += 'ids [$a, $b]'; } - throw error; + Error.throwWithStackTrace(error, stackTrace); } } @@ -1223,16 +1224,22 @@ class _CpuProfileTimelineTree { final bool isCodeTree; int frameId = kNoFrameId; - dynamic get _function { + vm_service.FuncRef? get _function { if (isCodeTree) { return _code.function!; } - return samples.functions![index].function; + final function = samples.functions![index].function; + if (function is vm_service.FuncRef) { + // TODO(jacobr): is this really anything else? The VMService API isn't + // clear. + return function; + } + return null; } vm_service.CodeRef get _code => samples.codes[index].code!; - String? get name => isCodeTree ? _code.name : _function.name; + String? get name => isCodeTree ? _code.name : _function?.name; String? get className { if (isCodeTree) return null; @@ -1251,13 +1258,13 @@ class _CpuProfileTimelineTree { // 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.location?.script!.uri + _function?.location?.script!.uri : samples.functions![index].resolvedUrl; int? get sourceLine { final function = _function; try { - return function.location?.line; + return function?.location?.line; } catch (_) { // Fail gracefully if `function` has no getter `location` (for example, if // the function is an instance of [NativeFunction]) or generally if @@ -1303,7 +1310,7 @@ extension CpuSamplesExtension on vm_service.CpuSamples { int kRootId = 0, bool buildCodeTree = false, }) { - final traceObject = {}; + final traceObject = {}; int nextId = kRootId; String? nameForStackFrame(_CpuProfileTimelineTree current) { 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 8ca49560acb..54b505d4c44 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 @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:vm_service/vm_service.dart'; + import '../../service/vm_flags.dart' as vm_flags; import '../../service/vm_service_wrapper.dart'; import '../../shared/globals.dart'; @@ -74,11 +76,11 @@ extension CpuProfilerExtension on VmServiceWrapper { ); } - Future setProfilePeriod(String value) { + Future setProfilePeriod(String value) { return serviceManager.service!.setFlag(vm_flags.profilePeriod, value); } - Future enableCpuProfiler() async { + Future enableCpuProfiler() async { return await 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 9a404b938a3..e04fa70a4fc 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 @@ -180,7 +180,7 @@ class CpuProfileTransformer { void mergeCpuProfileRoots(List roots) { // Loop through a copy of [roots] so that we can remove nodes from [roots] // once we have merged them. - final List rootsCopy = List.from(roots); + final List rootsCopy = List.of(roots); for (CpuStackFrame root in rootsCopy) { if (!roots.contains(root)) { // We have already merged [root] and removed it from [roots]. Do not 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 4e27652401f..3ca10c6cafe 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart @@ -110,9 +110,7 @@ class _CpuProfilerState extends State _initTabController(); } if (widget.data != oldWidget.data) { - setState(() { - data = widget.data; - }); + data = widget.data; } } @@ -501,7 +499,7 @@ class UserTagDropdown extends StatelessWidget { (userTags.length == 1 && userTags.first == UserTag.defaultTag.label) ? null - : (String? tag) => _onUserTagChanged(tag!, context), + : (String? tag) => _onUserTagChanged(tag!), ); }, ), @@ -521,7 +519,7 @@ class UserTagDropdown extends StatelessWidget { ); } - void _onUserTagChanged(String newTag, BuildContext context) async { + void _onUserTagChanged(String newTag) async { try { await controller.loadDataWithTag(newTag); } catch (e) { 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 0b3f98f4936..50ea6b17f5b 100644 --- a/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart +++ b/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart @@ -416,7 +416,7 @@ class _SecondaryControls extends StatelessWidget { gac.cpuProfiler, gac.export, ); - _exportPerformance(context); + _exportPerformance(); } : null, minScreenWidthForTextBeforeScaling: @@ -426,7 +426,7 @@ class _SecondaryControls extends StatelessWidget { ); } - void _exportPerformance(BuildContext context) { + void _exportPerformance() { controller.exportData(); // TODO(kenz): investigate if we need to do any error handling here. Is the // download always successful? diff --git a/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_details.dart b/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_details.dart index 8c294feccbd..56178626749 100644 --- a/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_details.dart +++ b/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_details.dart @@ -139,7 +139,7 @@ class InstanceDetails with _$InstanceDetails { }) = EnumInstance; bool get isExpandable { - bool falsy(Object obj) => false; + bool falsy(Object _) => false; return map( nill: falsy, diff --git a/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_providers.dart b/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_providers.dart index be8fe255540..86bda410b88 100644 --- a/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_providers.dart +++ b/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_providers.dart @@ -370,7 +370,6 @@ final AutoDisposeFutureProviderFamily ref, eval, instance, - classInstance, isAlive: isAlive, appName: appName, ); @@ -397,8 +396,7 @@ String? tryParsePackageName(String uri) { Future> _parseFields( AutoDisposeRef ref, EvalOnDartLibrary eval, - Instance instance, - Class classInstance, { + Instance instance, { required Disposable isAlive, required String? appName, }) async { diff --git a/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_viewer.dart b/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_viewer.dart index 5e9c7f710b7..37b145a9809 100644 --- a/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_viewer.dart +++ b/packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_viewer.dart @@ -36,7 +36,7 @@ final isExpandedProvider = StateProviderFamily((ref, path) { final estimatedChildCountProvider = AutoDisposeProviderFamily((ref, rootPath) { int estimatedChildCount(InstancePath path) { - int one(InstanceDetails instance) => 1; + int one(InstanceDetails _) => 1; int expandableEstimatedChildCount(Iterable keys) { if (!ref.watch(isExpandedProvider(path))) { @@ -118,8 +118,8 @@ class _InstanceViewerState extends ConsumerState { Iterable _buildError( Object error, - StackTrace? stackTrace, - InstancePath path, + StackTrace? _, + InstancePath __, ) { if (error is SentinelException) { final valueAsString = error.sentinel.valueAsString; 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 2152aa6a19f..17c487e8250 100644 --- a/packages/devtools_app/lib/src/screens/provider/provider_screen.dart +++ b/packages/devtools_app/lib/src/screens/provider/provider_screen.dart @@ -158,7 +158,7 @@ void showProviderErrorBanner(BuildContext context) { context, listen: false, ).addMessage( - ProviderUnknownErrorBanner(screenId: ProviderScreen.id).build(context), + ProviderUnknownErrorBanner(screenId: ProviderScreen.id).build(), ); } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view_controller.dart b/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view_controller.dart index 91ce8ef190a..b719b47fa88 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view_controller.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view_controller.dart @@ -85,7 +85,7 @@ class IsolateStatisticsViewController extends DisposableController for (int i = 0; i < counters.length; ++i) { // Ignore tags with empty counts. if (counters[i] == 0) continue; - percentages[names[i]] = counters[i].toDouble(); + percentages[names[i] as String] = counters[i].toDouble(); totalTickCount += counters[i]; } _tags = [ 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 e10fd3cda46..951c915205b 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 @@ -58,7 +58,7 @@ class _ObjectInspectorViewState extends State<_ObjectInspectorView> Widget build(BuildContext context) { return Split( axis: Axis.horizontal, - initialFractions: const [0.20, 0.80], + initialFractions: const [0.2, 0.8], children: [ AnalyticsTabbedView( gaScreen: gac.objectInspectorScreen, 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 d55b832fb71..b99651b561d 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 @@ -39,6 +39,7 @@ class VmFieldDisplay extends StatelessWidget { List> _fieldDataRows( FieldObject field, ) { + final staticValue = field.obj.staticValue; return [ ...vmObjectGeneralDataRows( controller, @@ -48,11 +49,11 @@ class VmFieldDisplay extends StatelessWidget { 'Observed types', _fieldObservedTypes(field), ), - if (field.obj.staticValue is InstanceRef) + if (staticValue is InstanceRef) selectableTextBuilderMapEntry( 'Static Value', - '${field.obj.staticValue.name ?? field.obj.staticValue.classRef.name}: ' - '${field.obj.staticValue.valueAsString ?? 'Unknown value'}', + '${staticValue.name ?? staticValue.classRef?.name}: ' + '${staticValue.valueAsString ?? 'Unknown value'}', ), ]; } 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 a247d9904ac..5e47f83fd45 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 @@ -252,8 +252,12 @@ String? _objectName(ObjRef? objectRef) { String? objectRefName; - if (objectRef is ClassRef || objectRef is FuncRef || objectRef is FieldRef) { - objectRefName = (objectRef as dynamic).name; + if (objectRef is ClassRef) { + objectRefName = objectRef.name; + } else if (objectRef is FuncRef) { + objectRefName = objectRef.name; + } else if (objectRef is FieldRef) { + objectRefName = objectRef.name; } else if (objectRef is LibraryRef) { objectRefName = (objectRef.name?.isEmpty ?? false) ? objectRef.uri : objectRef.name; @@ -415,9 +419,10 @@ class RetainingPathWidget extends StatelessWidget { BuildContext context, RetainingPath retainingPath, ) { + final theme = Theme.of(context); final emptyList = SelectableText( 'No retaining objects', - style: Theme.of(context).fixedFontStyle, + style: theme.fixedFontStyle, ); if (retainingPath.elements == null) return [emptyList]; @@ -425,7 +430,7 @@ class RetainingPathWidget extends StatelessWidget { ? SelectableText( _objectName(retainingPath.elements!.first.value) ?? '', - style: Theme.of(context).fixedFontStyle, + style: theme.fixedFontStyle, ) : emptyList; @@ -442,7 +447,7 @@ class RetainingPathWidget extends StatelessWidget { Flexible( child: SelectableText( _retainingObjectDescription(object), - style: Theme.of(context).fixedFontStyle, + style: theme.fixedFontStyle, ), ), ], @@ -451,7 +456,7 @@ class RetainingPathWidget extends StatelessWidget { children: [ SelectableText( 'Retained by a GC root of type ${retainingPath.gcRootType ?? ''}', - style: Theme.of(context).fixedFontStyle, + style: theme.fixedFontStyle, ), ], ) @@ -774,13 +779,13 @@ class VmObjectDisplayBasicLayout extends StatelessWidget { ); } - void _onExpandRetainingPath(bool expanded) { + void _onExpandRetainingPath(bool _) { if (object.retainingPath.value == null) { unawaited(object.requestRetainingPath()); } } - void _onExpandInboundRefs(bool expanded) { + void _onExpandInboundRefs(bool _) { if (object.inboundReferences.value == null) { unawaited(object.requestInboundsRefs()); } @@ -818,17 +823,29 @@ List> vmObjectGeneralDataRows( requestFunction: object.requestRetainedSize, ), ), - if (object is ClassObject || object is ScriptObject) + if (object is ClassObject) + serviceObjectLinkBuilderMapEntry( + controller: controller, + key: 'Library', + object: object.obj.library!, + ), + if (object is ScriptObject) serviceObjectLinkBuilderMapEntry( controller: controller, key: 'Library', - object: (object.obj as dynamic).library, + object: object.obj.library!, + ), + if (object is FieldObject) + serviceObjectLinkBuilderMapEntry( + controller: controller, + key: 'Owner', + object: object.obj.owner!, ), - if (object is FieldObject || object is FuncObject) + if (object is FuncObject) serviceObjectLinkBuilderMapEntry( controller: controller, key: 'Owner', - object: (object.obj as dynamic).owner, + object: object.obj.owner!, ), if (object is! ScriptObject && object is! LibraryObject) serviceObjectLinkBuilderMapEntry( 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 ad34820f7c3..1303680facd 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 @@ -431,8 +431,8 @@ class ProfileCode { List? ticks; - Map toJson() { - final json = {}; + Map toJson() { + final json = {}; json.addAll({ 'kind': kind ?? '', 'inclusiveTicks': inclusiveTicks ?? -1, 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 3359ee7b17c..74fd7365037 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 @@ -111,11 +111,11 @@ class JsonToServiceCache { /// Recursively inserts fake [Instance] entries in the cache, returning the /// root [Instance] of the JSON object. - Instance insertJsonObject(dynamic json) { + Instance insertJsonObject(Object? json) { if (json is List) { return _insertList(json); } else if (json is Map) { - return _insertMap(json.cast()); + return _insertMap(json.cast()); } return _insertPrimitive(json); } @@ -135,14 +135,11 @@ class JsonToServiceCache { removeJsonObject(entry.value); } } else if (root.kind == InstanceKind.kList) { - // ignore: prefer_foreach - for (final entry in root.elements!) { - removeJsonObject(entry); - } + root.elements!.cast().forEach(removeJsonObject); } } - Instance _insertMap(Map json) { + Instance _insertMap(Map json) { final map = Instance( kind: InstanceKind.kMap, identityHashCode: -1, @@ -154,7 +151,7 @@ class JsonToServiceCache { for (final entry in json.entries) MapAssociation( key: insertJsonObject(entry.key), - value: insertJsonObject(entry.value), + value: insertJsonObject(entry.value!), ), ]; map.length = json.length; @@ -163,7 +160,7 @@ class JsonToServiceCache { return map; } - Instance _insertList(List json) { + Instance _insertList(List json) { final list = Instance( kind: InstanceKind.kList, identityHashCode: -1, @@ -178,7 +175,7 @@ class JsonToServiceCache { return list; } - Instance _insertPrimitive(dynamic json) { + Instance _insertPrimitive(Object? json) { assert( json == null || json is String || diff --git a/packages/devtools_app/lib/src/service/service.dart b/packages/devtools_app/lib/src/service/service.dart index 9959d4e1023..4aae75637e0 100644 --- a/packages/devtools_app/lib/src/service/service.dart +++ b/packages/devtools_app/lib/src/service/service.dart @@ -14,7 +14,7 @@ Future _connectWithSse( Uri uri, void onError(error), Completer finishedCompleter, -) async { +) { final serviceCompleter = Completer(); uri = uri.scheme == 'sse' diff --git a/packages/devtools_app/lib/src/service/service_extension_manager.dart b/packages/devtools_app/lib/src/service/service_extension_manager.dart index 10a5ec4262b..69c725f7d3a 100644 --- a/packages/devtools_app/lib/src/service/service_extension_manager.dart +++ b/packages/devtools_app/lib/src/service/service_extension_manager.dart @@ -110,7 +110,7 @@ class ServiceExtensionManager extends Disposer { ) async { final extension = extensions.serviceExtensionsAllowlist[name]; if (extension != null) { - final dynamic extensionValue = _getExtensionValue(name, encodedValue); + final extensionValue = _getExtensionValue(name, encodedValue); final enabled = extension is extensions.ToggleableServiceExtensionDescription ? extensionValue == extension.enabledValue @@ -128,7 +128,7 @@ class ServiceExtensionManager extends Disposer { } } - dynamic _getExtensionValue(String name, String encodedValue) { + Object? _getExtensionValue(String name, String encodedValue) { final expectedValueType = extensions.serviceExtensionsAllowlist[name]!.values.first.runtimeType; switch (expectedValueType) { @@ -261,6 +261,8 @@ class ServiceExtensionManager extends Disposer { } } + IsolateRef? get _mainIsolate => _isolateManager.mainIsolate.value; + Future _restoreExtensionFromDevice(String name) async { final isolateRef = _isolateManager.mainIsolate.value; if (isolateRef == null) return; @@ -273,14 +275,14 @@ class ServiceExtensionManager extends Disposer { Future restore() async { // The restore request is obsolete if the isolate has changed. - if (isolateRef != _isolateManager.mainIsolate.value) return; + if (isolateRef != _mainIsolate) return; try { final response = await _service!.callServiceExtension( name, isolateId: isolateRef.id, ); - if (isolateRef != _isolateManager.mainIsolate.value) return; + if (isolateRef != _mainIsolate) return; switch (expectedValueType) { case bool: @@ -312,10 +314,10 @@ class ServiceExtensionManager extends Disposer { } } - if (isolateRef != _isolateManager.mainIsolate.value) return; + if (isolateRef != _mainIsolate) return; final Isolate? isolate = await _isolateManager.getIsolateCached(isolateRef); - if (isolateRef != _isolateManager.mainIsolate.value) return; + if (isolateRef != _mainIsolate) return; // Do not try to restore Dart IO extensions for a paused isolate. if (extensions.isDartIoExtension(name) && @@ -326,7 +328,7 @@ class ServiceExtensionManager extends Disposer { } } - Future _maybeRestoreExtension(String name, dynamic value) async { + Future _maybeRestoreExtension(String name, Object? value) async { final extensionDescription = extensions.serviceExtensionsAllowlist[name]; if (extensionDescription is extensions.ToggleableServiceExtensionDescription) { @@ -348,7 +350,7 @@ class ServiceExtensionManager extends Disposer { } } - Future _callServiceExtension(String name, dynamic value) async { + Future _callServiceExtension(String name, Object? value) async { if (_service == null) { return; } @@ -441,7 +443,7 @@ class ServiceExtensionManager extends Disposer { Future setServiceExtensionState( String name, { required bool enabled, - required dynamic value, + required Object? value, bool callExtension = true, }) async { if (callExtension && _serviceExtensions.contains(name)) { @@ -560,7 +562,7 @@ class ServiceExtensionState { // For boolean service extensions, [enabled] should equal [value]. final bool enabled; - final dynamic value; + final Object? value; @override bool operator ==(Object other) { 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 932b1a157e9..fe93e6f53cb 100644 --- a/packages/devtools_app/lib/src/service/service_extension_widgets.dart +++ b/packages/devtools_app/lib/src/service/service_extension_widgets.dart @@ -103,7 +103,6 @@ class _ServiceExtensionButtonGroupState if (!listEquals(oldWidget.extensions, widget.extensions)) { cancelListeners(); _initExtensionState(); - setState(() {}); } super.didUpdateWidget(oldWidget); } @@ -263,7 +262,7 @@ class _RegisteredServiceExtensionButton extends _ServiceExtensionWidget { required this.serviceDescription, required this.action, required String completedText, - required String Function(dynamic error) describeError, + required String Function(Object? error) describeError, }) : super(completedText: completedText, describeError: describeError); /// The service to subscribe to. @@ -346,7 +345,7 @@ class _ServiceExtensionToggle extends _ServiceExtensionWidget { const _ServiceExtensionToggle({ Key? key, required this.service, - required String Function(dynamic) describeError, + required String Function(Object?) describeError, }) : super( key: key, // Don't show messages on success or when this toggle is in progress. @@ -444,7 +443,7 @@ class ServiceExtensionCheckbox extends _ServiceExtensionWidget { ), ); - static String _errorMessage(String extensionName, dynamic error) { + static String _errorMessage(String extensionName, Object? error) { return 'Failed to update $extensionName setting: $error'; } @@ -745,11 +744,11 @@ class _ServiceExtensionCheckboxGroupButtonState ); } - void _mouseEnter(PointerEnterEvent event) { + void _mouseEnter(PointerEnterEvent _) { _overlayHovered = true; } - void _mouseExit(PointerExitEvent event) { + void _mouseExit(PointerExitEvent _) { _overlayHovered = false; } @@ -801,7 +800,8 @@ class _ServiceExtensionCheckboxGroupOverlay extends StatelessWidget { color: theme.focusColor, width: hoverCardBorderWidth, ), - borderRadius: BorderRadius.circular(defaultBorderRadius), + borderRadius: + const BorderRadius.all(Radius.circular(defaultBorderRadius)), ), child: Column( mainAxisSize: MainAxisSize.min, @@ -840,7 +840,7 @@ abstract class _ServiceExtensionWidget extends StatefulWidget { /// Callback that describes any error that occurs. /// /// This will replace the [inProgressText] in a [SnackBar]. - final String Function(dynamic error) describeError; + final String Function(Object? error) describeError; @override _ServiceExtensionMixin<_ServiceExtensionWidget> createState(); @@ -923,7 +923,8 @@ class ServiceExtensionTooltip extends StatelessWidget { color: focusColor, width: hoverCardBorderWidth, ), - borderRadius: BorderRadius.circular(defaultBorderRadius), + borderRadius: + const BorderRadius.all(Radius.circular(defaultBorderRadius)), ), textStyle: textStyle, child: child, diff --git a/packages/devtools_app/lib/src/service/service_manager.dart b/packages/devtools_app/lib/src/service/service_manager.dart index b636f686ac8..78bbdcc4712 100644 --- a/packages/devtools_app/lib/src/service/service_manager.dart +++ b/packages/devtools_app/lib/src/service/service_manager.dart @@ -185,10 +185,14 @@ class ServiceConnectionManager { VmServiceWrapper service, { required Future onClosed, }) async { + // Getting and setting a variable should not count as repeated references. + // ignore: prefer-moving-to-variable if (service == this.service) { // Service already opened. return; } + // Getting and setting a variable should not count as repeated references. + // ignore: prefer-moving-to-variable this.service = service; if (_serviceAvailable.isCompleted) { _serviceAvailable = Completer(); @@ -218,6 +222,8 @@ class ServiceConnectionManager { _inspectorService?.dispose(); _inspectorService = null; + // Value may have changes between repeated references. + // ignore: prefer-moving-to-variable if (service != this.service) { // A different service has been opened. return; @@ -225,6 +231,8 @@ class ServiceConnectionManager { vm = await service.getVM(); + // Value may have changes between repeated references. + // ignore: prefer-moving-to-variable if (service != this.service) { // A different service has been opened. return; @@ -297,6 +305,8 @@ class ServiceConnectionManager { } } } + // Value may have changes between repeated references. + // ignore: prefer-moving-to-variable if (service != this.service) { // A different service has been opened. return; @@ -306,6 +316,8 @@ class ServiceConnectionManager { final isolates = vm?.isolatesForDevToolsMode() ?? []; await isolateManager.init(isolates); + // Value may have changes between repeated references. + // ignore: prefer-moving-to-variable if (service != this.service) { // A different service has been opened. return; @@ -314,6 +326,8 @@ class ServiceConnectionManager { // This needs to be called before calling // `ga.setupUserApplicationDimensions()`. await connectedApp!.initializeValues(); + // Value may have changes between repeated references. + // ignore: prefer-moving-to-variable if (service != this.service) { // A different service has been opened. return; @@ -323,6 +337,8 @@ class ServiceConnectionManager { // Set up analytics dimensions for the connected app. ga.setupUserApplicationDimensions(); + // Value may have changes between repeated references. + // ignore: prefer-moving-to-variable if (service != this.service) { // A different service has been opened. return; @@ -439,8 +455,8 @@ class ServiceConnectionManager { final flutterViewListResponse = await _callServiceExtensionOnMainIsolate( registrations.flutterListViews, ); - final List views = - flutterViewListResponse.json!['views'].cast>(); + final List> views = + flutterViewListResponse.json!['views'].cast>(); // Each isolate should only have one FlutterView. final flutterView = views.firstWhereOrNull( @@ -454,7 +470,7 @@ class ServiceConnectionManager { throw Exception(message); } - return flutterView['id']; + return flutterView['id'] as String; } /// Flutter engine returns estimate how much memory is used by layer/picture raster 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 9a29f03bdf6..adb115c1456 100644 --- a/packages/devtools_app/lib/src/service/vm_service_wrapper.dart +++ b/packages/devtools_app/lib/src/service/vm_service_wrapper.dart @@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Code needs to match API from VmService. +// ignore_for_file: avoid-dynamic +library vm_service_wrapper; + import 'dart:async'; import 'package:collection/collection.dart' show IterableExtension; 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 d7d6cfabcfc..14a560b1bf4 100644 --- a/packages/devtools_app/lib/src/shared/analytics/_analytics_stub.dart +++ b/packages/devtools_app/lib/src/shared/analytics/_analytics_stub.dart @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Avoid unused parameters does not play well with conditional imports. +// ignore_for_file: avoid-unused-parameters +// ignore_for_file: avoid-redundant-async +library _analytics_stub; + import 'dart:async'; import 'analytics_common.dart'; 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 328a888cd50..171b1f12291 100644 --- a/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart +++ b/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart @@ -71,6 +71,8 @@ class GtagEventDevTools extends GtagEvent { int value, bool non_interaction, + // This code is going away so not worth cleaning up to be free of dynamic. + // ignore: avoid-dynamic dynamic custom_map, // NOTE: Do not reorder any of these. Order here must match the order in the @@ -120,7 +122,7 @@ class GtagEventDevTools extends GtagEvent { external bool get non_interaction; @override - external dynamic get custom_map; + external Object get custom_map; // Custom dimensions: external String? get user_app; @@ -650,27 +652,27 @@ bool _userApplicationDimensionsComputed = false; void _computeUserApplicationCustomGTagData() { if (_userApplicationDimensionsComputed) return; - assert(serviceManager.connectedApp!.isFlutterAppNow != null); - assert(serviceManager.connectedApp!.isDartWebAppNow != null); - assert(serviceManager.connectedApp!.isProfileBuildNow != null); + final connectedApp = serviceManager.connectedApp!; + assert(connectedApp.isFlutterAppNow != null); + assert(connectedApp.isDartWebAppNow != null); + assert(connectedApp.isProfileBuildNow != null); const unknownOS = 'unknown'; - if (serviceManager.connectedApp!.isFlutterAppNow!) { + if (connectedApp.isFlutterAppNow!) { userPlatformType = serviceManager.vm?.operatingSystem ?? unknownOS; } - if (serviceManager.connectedApp!.isFlutterWebAppNow) { + if (connectedApp.isFlutterWebAppNow) { userAppType = appTypeFlutterWeb; - } else if (serviceManager.connectedApp!.isFlutterAppNow!) { + } else if (connectedApp.isFlutterAppNow!) { userAppType = appTypeFlutter; - } else if (serviceManager.connectedApp!.isDartWebAppNow!) { + } else if (connectedApp.isDartWebAppNow!) { userAppType = appTypeWeb; } else { userAppType = appTypeDartCLI; } - userBuildType = serviceManager.connectedApp!.isProfileBuildNow! - ? buildTypeProfile - : buildTypeDebug; + userBuildType = + connectedApp.isProfileBuildNow! ? buildTypeProfile : buildTypeDebug; _analyticsComputed = true; } @@ -749,7 +751,7 @@ void waitForDimensionsComputed(String screenName) { // Loading screen from a hash code, can't collect GA (if enabled) until we have // all the dimension data. -void setupAndGaScreen(String screenName) async { +void setupAndGaScreen(String screenName) { if (!_analyticsComputed) { _stillWaiting++; waitForDimensionsComputed(screenName); diff --git a/packages/devtools_app/lib/src/shared/analytics/prompt.dart b/packages/devtools_app/lib/src/shared/analytics/prompt.dart index a7b662097b9..4d625204577 100644 --- a/packages/devtools_app/lib/src/shared/analytics/prompt.dart +++ b/packages/devtools_app/lib/src/shared/analytics/prompt.dart @@ -110,7 +110,6 @@ class _AnalyticsPromptState extends State unawaited( launchUrl( 'https://www.google.com/intl/en/policies/privacy', - context, ), ); }, diff --git a/packages/devtools_app/lib/src/shared/banner_messages.dart b/packages/devtools_app/lib/src/shared/banner_messages.dart index 125d39ece37..6fb4d8a219d 100644 --- a/packages/devtools_app/lib/src/shared/banner_messages.dart +++ b/packages/devtools_app/lib/src/shared/banner_messages.dart @@ -315,12 +315,14 @@ class DebugModePerformanceMessage { } } +// TODO(jacobr): cleanup this class that looks like a Widget but can't quite be +// a widget due to some questionable design choices involving BannerMessage. class ProviderUnknownErrorBanner { const ProviderUnknownErrorBanner({required this.screenId}); final String screenId; - BannerMessage build(BuildContext context) { + BannerMessage build() { return _BannerError( key: Key('ProviderUnknownErrorBanner - $screenId'), screenId: screenId, @@ -470,7 +472,7 @@ class UnsupportedFlutterVersionWarning { final SemanticVersion supportedFlutterVersion; - BannerMessage build(BuildContext context) { + BannerMessage build() { return _BannerWarning( key: Key('UnsupportedFlutterVersionWarning - $screenId'), textSpans: [ @@ -509,7 +511,7 @@ void maybePushUnsupportedFlutterVersionWarning( screenId: screenId, currentFlutterVersion: currentVersion, supportedFlutterVersion: supportedFlutterVersion, - ).build(context), + ).build(), ); } } diff --git a/packages/devtools_app/lib/src/shared/charts/chart.dart b/packages/devtools_app/lib/src/shared/charts/chart.dart index e8ba0ca90ad..5a7f815b277 100644 --- a/packages/devtools_app/lib/src/shared/charts/chart.dart +++ b/packages/devtools_app/lib/src/shared/charts/chart.dart @@ -173,7 +173,6 @@ class ChartPainter extends CustomPainter { (canavas) { drawAxes( canvas, - size, axis, displayX: chartController.displayXAxis, ); @@ -352,7 +351,6 @@ class ChartPainter extends CustomPainter { drawSelection( canvas, xCanvasCoord, - chartController.canvasChartHeight, ); }, ); @@ -446,7 +444,6 @@ class ChartPainter extends CustomPainter { void drawAxes( Canvas canvas, - Size size, Paint axis, { bool displayX = true, bool displayY = true, @@ -474,7 +471,7 @@ class ChartPainter extends CustomPainter { } } - void drawSelection(Canvas canvas, double x, double y) { + void drawSelection(Canvas canvas, double x) { final paint = Paint() ..strokeWidth = 2.0 ..color = colorScheme.hoverSelectionBarColor; 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 380fcc62632..59444b8adc4 100644 --- a/packages/devtools_app/lib/src/shared/charts/flame_chart.dart +++ b/packages/devtools_app/lib/src/shared/charts/flame_chart.dart @@ -903,6 +903,7 @@ extension NodeListExtension on List { } } +// TODO(jacobr): cleanup up this util class with just static members. // ignore: avoid_classes_with_only_static_members class FlameChartUtils { static double leftPaddingForNode( diff --git a/packages/devtools_app/lib/src/shared/charts/treemap.dart b/packages/devtools_app/lib/src/shared/charts/treemap.dart index 3800ca6e3cd..78ca5f21d1f 100644 --- a/packages/devtools_app/lib/src/shared/charts/treemap.dart +++ b/packages/devtools_app/lib/src/shared/charts/treemap.dart @@ -623,12 +623,14 @@ class TreemapNode extends TreeNode { // Trim beginning of the name of [this] if it starts with its parent's name. // If the parent node and the child node's name are exactly the same, // do not trim in order to avoid empty names. - if (parent != null && - displayName.startsWith(parent!.name) && - displayName != parent!.name) { - displayName = displayName.replaceFirst(parent!.name, ''); - if (displayName.startsWith('/')) { - displayName = displayName.replaceFirst('/', ''); + final parent = this.parent; + if (parent != null) { + final parentName = parent.name; + if (displayName.startsWith(parentName) && displayName != parentName) { + displayName = displayName.replaceFirst(parentName, ''); + if (displayName.startsWith('/')) { + displayName = displayName.replaceFirst('/', ''); + } } } diff --git a/packages/devtools_app/lib/src/shared/common_widgets.dart b/packages/devtools_app/lib/src/shared/common_widgets.dart index 106daff6333..d44780f75a5 100644 --- a/packages/devtools_app/lib/src/shared/common_widgets.dart +++ b/packages/devtools_app/lib/src/shared/common_widgets.dart @@ -949,15 +949,15 @@ class AreaPaneHeader extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); + final borderSide = defaultBorderSide(theme); return SizedBox.fromSize( size: preferredSize, child: Container( decoration: BoxDecoration( border: Border( - top: needsTopBorder ? defaultBorderSide(theme) : BorderSide.none, - bottom: - needsBottomBorder ? defaultBorderSide(theme) : BorderSide.none, - left: needsLeftBorder ? defaultBorderSide(theme) : BorderSide.none, + top: needsTopBorder ? borderSide : BorderSide.none, + bottom: needsBottomBorder ? borderSide : BorderSide.none, + left: needsLeftBorder ? borderSide : BorderSide.none, ), color: backgroundColor ?? theme.titleSolidBackgroundColor, ), @@ -1073,7 +1073,7 @@ class InformationButton extends StatelessWidget { message: tooltip, child: IconButton( icon: const Icon(Icons.help_outline), - onPressed: () async => await launchUrl(link, context), + onPressed: () async => await launchUrl(link), ), ); } @@ -1877,7 +1877,7 @@ class MoreInfoLink extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); return InkWell( - onTap: () => _onLinkTap(context), + onTap: _onLinkTap, borderRadius: BorderRadius.circular(defaultBorderRadius), child: Padding( padding: padding ?? const EdgeInsets.all(denseSpacing), @@ -1901,8 +1901,8 @@ class MoreInfoLink extends StatelessWidget { ); } - void _onLinkTap(BuildContext context) { - unawaited(launchUrl(url, context)); + void _onLinkTap() { + unawaited(launchUrl(url)); ga.select(gaScreenName, gaSelectedItemDescription); } } @@ -1921,7 +1921,7 @@ class LinkTextSpan extends TextSpan { link.gaScreenName, link.gaSelectedItemDescription, ); - await launchUrl(link.url, context); + await launchUrl(link.url); }, ); } @@ -2053,7 +2053,7 @@ class CopyToClipboardControl extends StatelessWidget { ga.select(gaScreen!, gaItem!); } unawaited( - copyToClipboard(dataProvider!() ?? '', successMessage, context), + copyToClipboard(dataProvider!() ?? '', successMessage), ); }; diff --git a/packages/devtools_app/lib/src/shared/config_specific/asset/_asset_stub.dart b/packages/devtools_app/lib/src/shared/config_specific/asset/_asset_stub.dart index 7945ffde37a..407b74898f8 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/asset/_asset_stub.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/asset/_asset_stub.dart @@ -11,6 +11,7 @@ /// caller is going to be doing its own caching. (It might not be cached if /// it's set to true either, that depends on the asset bundle /// implementation.) +// ignore: avoid-unused-parameters Future loadStringImpl(String key, {bool cache = true}) { throw Exception('Assets not yet supported in dart:html app'); } diff --git a/packages/devtools_app/lib/src/shared/config_specific/drag_and_drop/_drag_and_drop_web.dart b/packages/devtools_app/lib/src/shared/config_specific/drag_and_drop/_drag_and_drop_web.dart index 2286dc9cb7c..4efabcdfb00 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/drag_and_drop/_drag_and_drop_web.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/drag_and_drop/_drag_and_drop_web.dart @@ -46,7 +46,7 @@ class DragAndDropManagerWeb extends DragAndDropManager { event.dataTransfer.dropEffect = 'move'; } - void _onDragLeave(MouseEvent event) { + void _onDragLeave(MouseEvent _) { dragLeave(); } diff --git a/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/framework_initialize.dart b/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/framework_initialize.dart index 9ba14b50e95..9b17bcc8bda 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/framework_initialize.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/framework_initialize.dart @@ -7,7 +7,7 @@ import '_framework_initialize_stub.dart' if (dart.library.html) '_framework_initialize_web.dart' if (dart.library.io) '_framework_initialize_desktop.dart'; -Future initializeFramework() async { +Future initializeFramework() async { FrameworkCore.initGlobals(); await initializePlatform(); FrameworkCore.init(); diff --git a/packages/devtools_app/lib/src/shared/config_specific/host_platform/host_platform_stub.dart b/packages/devtools_app/lib/src/shared/config_specific/host_platform/host_platform_stub.dart index 6284e5cbccc..0cc6c9f54cb 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/host_platform/host_platform_stub.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/host_platform/host_platform_stub.dart @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. -// ignore: avoid_classes_with_only_static_members class HostPlatform { - // ignore: prefer_const_declarations static late final HostPlatform instance = HostPlatform(); bool get isMacOS => throw UnimplementedError(); diff --git a/packages/devtools_app/lib/src/shared/config_specific/launch_url/_launch_url_desktop.dart b/packages/devtools_app/lib/src/shared/config_specific/launch_url/_launch_url_desktop.dart index 9d6b6acf999..8b2e8553d8a 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/launch_url/_launch_url_desktop.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/launch_url/_launch_url_desktop.dart @@ -2,6 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. -void launchUrlVSCode(String url) { +void launchUrlVSCode(String _) { // Do nothing } diff --git a/packages/devtools_app/lib/src/shared/config_specific/launch_url/_launch_url_stub.dart b/packages/devtools_app/lib/src/shared/config_specific/launch_url/_launch_url_stub.dart index c23bbfc0cd4..8b2e8553d8a 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/launch_url/_launch_url_stub.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/launch_url/_launch_url_stub.dart @@ -2,6 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. -void launchUrlVSCode(String url) async { +void launchUrlVSCode(String _) { // Do nothing } diff --git a/packages/devtools_app/lib/src/shared/config_specific/launch_url/launch_url.dart b/packages/devtools_app/lib/src/shared/config_specific/launch_url/launch_url.dart index 35f01c17f5f..abe81213154 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/launch_url/launch_url.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/launch_url/launch_url.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. -import 'package:flutter/widgets.dart'; import 'package:url_launcher/url_launcher.dart' as url_launcher; import '../../globals.dart'; @@ -10,7 +9,7 @@ import '_launch_url_stub.dart' if (dart.library.html) '_launch_url_web.dart' if (dart.library.io) '_launch_url_desktop.dart'; -Future launchUrl(String url, BuildContext context) async { +Future launchUrl(String url) async { final parsedUrl = Uri.tryParse(url); if (parsedUrl != null && await url_launcher.canLaunchUrl(parsedUrl)) { diff --git a/packages/devtools_app/lib/src/shared/config_specific/server/_server_stub.dart b/packages/devtools_app/lib/src/shared/config_specific/server/_server_stub.dart index ed13bc7d10b..5124ba07421 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/server/_server_stub.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/server/_server_stub.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. +// Avoid unused parameters does not understand conditional imports. +// ignore_for_file: avoid-unused-parameters import 'dart:async'; import '../../primitives/utils.dart'; @@ -11,7 +13,7 @@ const unsupportedMessage = bool get isDevToolsServerAvailable => false; -Future request(String url) async { +Future request(String url) async { throw Exception(unsupportedMessage); } diff --git a/packages/devtools_app/lib/src/shared/config_specific/server/_server_web.dart b/packages/devtools_app/lib/src/shared/config_specific/server/_server_web.dart index 02cfa728c50..12b1dd425e2 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/server/_server_web.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/server/_server_web.dart @@ -285,7 +285,7 @@ Future resetDevToolsFile() async { } } -Future requestBaseAppSizeFile(String path) async { +Future requestBaseAppSizeFile(String path) { return requestFile( api: apiGetBaseAppSizeFile, fileKey: baseAppSizeFilePropertyName, @@ -293,7 +293,7 @@ Future requestBaseAppSizeFile(String path) async { ); } -Future requestTestAppSizeFile(String path) async { +Future requestTestAppSizeFile(String path) { return requestFile( api: apiGetTestAppSizeFile, fileKey: testAppSizeFilePropertyName, diff --git a/packages/devtools_app/lib/src/shared/config_specific/url/_url_stub.dart b/packages/devtools_app/lib/src/shared/config_specific/url/_url_stub.dart index 09e684aca17..9103800db01 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/url/_url_stub.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/url/_url_stub.dart @@ -12,4 +12,6 @@ String? getWebUrl() => null; /// Performs a web redirect using window.location.replace(). /// /// No-op for non-web platforms. +// Unused parameter lint doesn't make sense for stub files. +// ignore: avoid-unused-parameters void webRedirect(String url) {} 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 30ff7715d23..ede048a32de 100644 --- a/packages/devtools_app/lib/src/shared/console/console_service.dart +++ b/packages/devtools_app/lib/src/shared/console/console_service.dart @@ -123,10 +123,7 @@ class ConsoleService extends Disposer { } /// Append to the stdout / stderr buffer. - void appendStdio( - String text, { - bool forceScrollIntoView = false, - }) { + void appendStdio(String text) { const int kMaxLogItemsLowerBound = 5000; const int kMaxLogItemsUpperBound = 5500; diff --git a/packages/devtools_app/lib/src/shared/device_dialog.dart b/packages/devtools_app/lib/src/shared/device_dialog.dart index 0b9535e181e..bde5c2b1300 100644 --- a/packages/devtools_app/lib/src/shared/device_dialog.dart +++ b/packages/devtools_app/lib/src/shared/device_dialog.dart @@ -117,7 +117,7 @@ class _VMFlagsDialogState extends State with AutoDisposeMixin { super.initState(); filterController = TextEditingController(); - filterController.addListener(() { + addAutoDisposeListener(filterController, () { setState(() { _refilter(); }); diff --git a/packages/devtools_app/lib/src/shared/editable_list.dart b/packages/devtools_app/lib/src/shared/editable_list.dart index c5c590ab548..83a56813fc9 100644 --- a/packages/devtools_app/lib/src/shared/editable_list.dart +++ b/packages/devtools_app/lib/src/shared/editable_list.dart @@ -276,7 +276,7 @@ class EditableListCopyDirectoryButton extends StatelessWidget { key: key, padding: EdgeInsets.zero, onPressed: () { - unawaited(copyToClipboard(value, 'Copied to clipboard.', context)); + unawaited(copyToClipboard(value, 'Copied to clipboard.')); }, iconSize: defaultIconSize, splashRadius: defaultIconSize, 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 f0bb74d2bdc..f25f5dcbd6f 100644 --- a/packages/devtools_app/lib/src/shared/error_badge_manager.dart +++ b/packages/devtools_app/lib/src/shared/error_badge_manager.dart @@ -56,7 +56,7 @@ class ErrorBadgeManager extends DisposableController ); } - void _handleExtensionEvent(Event e) async { + void _handleExtensionEvent(Event e) { if (e.extensionKind == 'Flutter.Error') { incrementBadgeCount(LoggingScreen.id); @@ -97,7 +97,7 @@ class ErrorBadgeManager extends DisposableController return InspectableWidgetError(errorMessage, inspectorRef); } - void _handleStdErr(Event e) { + void _handleStdErr(Event _) { incrementBadgeCount(LoggingScreen.id); } diff --git a/packages/devtools_app/lib/src/shared/eval_on_dart_library.dart b/packages/devtools_app/lib/src/shared/eval_on_dart_library.dart index 5d1f45cc871..0544840089b 100644 --- a/packages/devtools_app/lib/src/shared/eval_on_dart_library.dart +++ b/packages/devtools_app/lib/src/shared/eval_on_dart_library.dart @@ -5,10 +5,13 @@ // This code is directly based on src/io/flutter/inspector/EvalOnDartLibrary.java // If you add a method to this class you should also add it to EvalOnDartLibrary.java import 'dart:async'; +import 'dart:core' hide Error; +import 'dart:core' as core; import 'dart:math'; import 'package:flutter/foundation.dart'; -import 'package:vm_service/vm_service.dart'; +import 'package:vm_service/vm_service.dart' hide Error; +import 'package:vm_service/vm_service.dart' as vm_service; import '../screens/inspector/inspector_service.dart'; import '../service/vm_service_wrapper.dart'; @@ -251,18 +254,15 @@ class EvalOnDartLibrary extends DisposableController return null; } - void _handleError(dynamic e, StackTrace stack) { + void _handleError(Object e, StackTrace stack) { if (_disposed) return; - switch (e.runtimeType) { - case RPCError: - log('RPCError: $e', LogLevel.error); - break; - case Error: - log('${e.kind}: ${e.tooltip}', LogLevel.error); - break; - default: - log('Unrecognized error: $e', LogLevel.error); + if (e is RPCError) { + log('RPCError: $e', LogLevel.error); + } else if (e is vm_service.Error) { + log('${e.kind}: ${e.message}', LogLevel.error); + } else { + log('Unrecognized error: $e', LogLevel.error); } log(stack.toString(), LogLevel.error); } @@ -521,7 +521,7 @@ class EvalOnDartLibrary extends DisposableController /// It also removes the need for using `!` once the devtool is migrated to NNBD if (isAlive?.disposed ?? true) { // throw before _handleError as we don't want to log cancellations. - throw CancelledException(); + core.Error.throwWithStackTrace(CancelledException(), stack); } _handleError(err, stack); diff --git a/packages/devtools_app/lib/src/shared/globals.dart b/packages/devtools_app/lib/src/shared/globals.dart index 89b73d7d274..5d1addfe123 100644 --- a/packages/devtools_app/lib/src/shared/globals.dart +++ b/packages/devtools_app/lib/src/shared/globals.dart @@ -20,34 +20,39 @@ bool get isExternalBuild => _isExternalBuild; bool _isExternalBuild = true; void setInternalBuild() => _isExternalBuild = false; -final Map globals = {}; +final Map globals = {}; ServiceConnectionManager get serviceManager => - globals[ServiceConnectionManager]; + globals[ServiceConnectionManager] as ServiceConnectionManager; -ScriptManager get scriptManager => globals[ScriptManager]; +ScriptManager get scriptManager => globals[ScriptManager] as ScriptManager; -MessageBus get messageBus => globals[MessageBus]; +MessageBus get messageBus => globals[MessageBus] as MessageBus; -FrameworkController get frameworkController => globals[FrameworkController]; +FrameworkController get frameworkController => + globals[FrameworkController] as FrameworkController; -Storage get storage => globals[Storage]; +Storage get storage => globals[Storage] as Storage; -SurveyService get surveyService => globals[SurveyService]; +SurveyService get surveyService => globals[SurveyService] as SurveyService; -PreferencesController get preferences => globals[PreferencesController]; +PreferencesController get preferences => + globals[PreferencesController] as PreferencesController; DevToolsExtensionPoints get devToolsExtensionPoints => - globals[DevToolsExtensionPoints]; + globals[DevToolsExtensionPoints] as DevToolsExtensionPoints; -OfflineModeController get offlineController => globals[OfflineModeController]; +OfflineModeController get offlineController => + globals[OfflineModeController] as OfflineModeController; -IdeTheme get ideTheme => globals[IdeTheme]; +IdeTheme get ideTheme => globals[IdeTheme] as IdeTheme; -NotificationService get notificationService => globals[NotificationService]; +NotificationService get notificationService => + globals[NotificationService] as NotificationService; -BreakpointManager get breakpointManager => globals[BreakpointManager]; +BreakpointManager get breakpointManager => + globals[BreakpointManager] as BreakpointManager; -void setGlobal(Type clazz, dynamic instance) { +void setGlobal(Type clazz, Object instance) { globals[clazz] = instance; } diff --git a/packages/devtools_app/lib/src/shared/history_viewport.dart b/packages/devtools_app/lib/src/shared/history_viewport.dart index c86cb1cf7f0..d3442669d3d 100644 --- a/packages/devtools_app/lib/src/shared/history_viewport.dart +++ b/packages/devtools_app/lib/src/shared/history_viewport.dart @@ -58,27 +58,11 @@ class _HistoryViewportState extends State> { @override Widget build(BuildContext context) { final theme = Theme.of(context); - return OutlineDecoration( - child: ValueListenableBuilder( - valueListenable: widget.history.current, - builder: (context, T? current, _) { - return Column( - children: [ - _buildTitle(context, theme), - widget.contentBuilder(context, current), - ], - ); - }, - ), - ); - } - - Widget _buildTitle(BuildContext context, ThemeData theme) { final title = widget.generateTitle == null ? ' ' : widget.generateTitle!(widget.history.current.value); final defaultTitleStyle = theme.textTheme.titleSmall ?? const TextStyle(); - return debuggerSectionTitle( + final titleWidget = debuggerSectionTitle( theme, child: Row( children: [ @@ -151,5 +135,18 @@ class _HistoryViewportState extends State> { ], ), ); + return OutlineDecoration( + child: ValueListenableBuilder( + valueListenable: widget.history.current, + builder: (context, T? current, _) { + return Column( + children: [ + titleWidget, + widget.contentBuilder(context, current), + ], + ); + }, + ), + ); } } diff --git a/packages/devtools_app/lib/src/shared/http/_http_cookies.dart b/packages/devtools_app/lib/src/shared/http/_http_cookies.dart index 8d7673e4ca9..c5fec935772 100644 --- a/packages/devtools_app/lib/src/shared/http/_http_cookies.dart +++ b/packages/devtools_app/lib/src/shared/http/_http_cookies.dart @@ -19,6 +19,7 @@ // ignore_for_file: unused_catch_clause // ignore_for_file: unused_element // ignore_for_file: unused_local_variable +// ignore_for_file: prefer-moving-to-variable part of http; diff --git a/packages/devtools_app/lib/src/shared/http/_http_date.dart b/packages/devtools_app/lib/src/shared/http/_http_date.dart index b74c13e7b87..21719a69f31 100644 --- a/packages/devtools_app/lib/src/shared/http/_http_date.dart +++ b/packages/devtools_app/lib/src/shared/http/_http_date.dart @@ -15,9 +15,12 @@ // ignore_for_file: unnecessary_new // ignore_for_file: unused_catch_clause // ignore_for_file: unused_local_variable +// ignore_for_file: prefer-moving-to-variable +// ignore_for_file: avoid-throw-in-catch-block part of http; +// TODO(jacobr): cleanup this class with only static members. // ignore: avoid_classes_with_only_static_members /// Utility functions for working with dates with HTTP specific date formats. class HttpDate { 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 8f2988b3585..aa5758f38e5 100644 --- a/packages/devtools_app/lib/src/shared/http/curl_command.dart +++ b/packages/devtools_app/lib/src/shared/http/curl_command.dart @@ -95,10 +95,10 @@ class CurlCommand { return "'$content'"; } - static String? _unwrapHeaderValue(dynamic value) { + static String? _unwrapHeaderValue(Object? value) { if (value is String) { return value; - } else if (value is List) { + } else if (value is List) { return value.safeFirst as String?; } 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 026d2db5c46..0dec3fd23f7 100644 --- a/packages/devtools_app/lib/src/shared/http/http_service.dart +++ b/packages/devtools_app/lib/src/shared/http/http_service.dart @@ -5,25 +5,22 @@ import '../globals.dart'; import '../primitives/utils.dart'; -// ignore: avoid_classes_with_only_static_members -class HttpService { - /// Enables or disables HTTP logging for all isolates. - static Future toggleHttpRequestLogging(bool state) async { - await serviceManager.service!.forEachIsolate((isolate) async { - final httpLoggingAvailable = await serviceManager.service! - .isHttpTimelineLoggingAvailable(isolate.id!); - if (httpLoggingAvailable) { - final future = serviceManager.service!.httpEnableTimelineLogging( - 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. - // TODO(jacobr): detect whether the isolate is paused using the vm - // service and handle this case gracefully rather than timing out. - await timeout(future, 500); - } - }); - } +/// Enables or disables HTTP logging for all isolates. +Future toggleHttpRequestLogging(bool state) async { + await serviceManager.service!.forEachIsolate((isolate) async { + final httpLoggingAvailable = await serviceManager.service! + .isHttpTimelineLoggingAvailable(isolate.id!); + if (httpLoggingAvailable) { + final future = serviceManager.service!.httpEnableTimelineLogging( + 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. + // TODO(jacobr): detect whether the isolate is paused using the vm + // service and handle this case gracefully rather than timing out. + await timeout(future, 500); + } + }); } diff --git a/packages/devtools_app/lib/src/shared/navigation.dart b/packages/devtools_app/lib/src/shared/navigation.dart index c37a1f40a8f..4c1c3204bfc 100644 --- a/packages/devtools_app/lib/src/shared/navigation.dart +++ b/packages/devtools_app/lib/src/shared/navigation.dart @@ -60,5 +60,4 @@ String routeNameWithQueryParams( /// /// ModalRoute.of`(innerContext)` returns the unnamed page route. String _inferThemeParameter(ColorScheme colorScheme) => - // ignore: deprecated_member_use_from_same_package colorScheme.isDark ? '/unnamedRoute?theme=dark' : '/unnamedRoute'; diff --git a/packages/devtools_app/lib/src/shared/object_tree.dart b/packages/devtools_app/lib/src/shared/object_tree.dart index cadb84e6587..b5eab3208c6 100644 --- a/packages/devtools_app/lib/src/shared/object_tree.dart +++ b/packages/devtools_app/lib/src/shared/object_tree.dart @@ -113,7 +113,7 @@ Future buildVariablesTree( } } else if (instanceRef != null && serviceManager.service != null) { final variableId = variable.ref!.isolateRef!.id!; - final dynamic result = await serviceManager.service!.getObject( + final result = await serviceManager.service!.getObject( variableId, instanceRef.id!, offset: variable.offset, @@ -688,7 +688,7 @@ List _createVariablesForBytes( ) { final bytes = base64.decode(instance.bytes!); final variables = []; - List result; + List result; switch (instance.kind) { case InstanceKind.kUint8ClampedList: case InstanceKind.kUint8List: @@ -1004,9 +1004,8 @@ class DartObjectNode extends TreeNode { } return instanceRef.valueAsString == null; } - return (ref?.value is! String?) && - (ref?.value is! num?) && - (ref?.value is! bool?); + final value = ref?.value; + return (value is! String?) && (value is! num?) && (value is! bool?); } Object? get value => ref?.value; diff --git a/packages/devtools_app/lib/src/shared/preferences.dart b/packages/devtools_app/lib/src/shared/preferences.dart index f48771f91e2..c1dbc3eb272 100644 --- a/packages/devtools_app/lib/src/shared/preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences.dart @@ -118,7 +118,8 @@ class InspectorPreferencesController extends DisposableController Future init() async { await _initHoverEvalMode(); - await _initCustomPubRootDirectories(); + // TODO(jacobr): consider initializing this first as it is not blocking. + _initCustomPubRootDirectories(); } Future _initHoverEvalMode() async { @@ -137,7 +138,7 @@ class InspectorPreferencesController extends DisposableController }); } - Future _initCustomPubRootDirectories() async { + void _initCustomPubRootDirectories() { autoDisposeStreamSubscription( serviceManager.onConnectionAvailable .listen(_handleConnectionToNewService), @@ -159,13 +160,13 @@ class InspectorPreferencesController extends DisposableController if (debuggerState?.isPaused.value == false) { // the isolate is already unpaused, we can try to load // the directories - preferences.inspector.loadCustomPubRootDirectories(); + unawaited(preferences.inspector.loadCustomPubRootDirectories()); } else { late Function() pausedListener; pausedListener = () { if (debuggerState?.isPaused.value == false) { - preferences.inspector.loadCustomPubRootDirectories(); + unawaited(preferences.inspector.loadCustomPubRootDirectories()); debuggerState?.isPaused.removeListener(pausedListener); } @@ -179,12 +180,12 @@ class InspectorPreferencesController extends DisposableController ); } - void _handleConnectionClosed(dynamic _) async { + void _handleConnectionClosed(Object? _) { _mainScriptDir = null; _customPubRootDirectories.clear(); } - Future _handleConnectionToNewService(VmServiceWrapper wrapper) async { + Future _handleConnectionToNewService(VmServiceWrapper _) async { await _updateMainScriptRef(); _customPubRootDirectories.clear(); @@ -250,8 +251,8 @@ class InspectorPreferencesController extends DisposableController final freshPubRootDirectories = await localInspectorService.getPubRootDirectories(); if (freshPubRootDirectories != null) { - final newSet = Set.from(freshPubRootDirectories); - final oldSet = Set.from(_customPubRootDirectories.value); + final newSet = Set.of(freshPubRootDirectories); + final oldSet = Set.of(_customPubRootDirectories.value); final directoriesToAdd = newSet.difference(oldSet); final directoriesToRemove = oldSet.difference(newSet); 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 188e8514f7f..26bb7acdfe1 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 @@ -528,7 +528,7 @@ class _CustomPointerScrollableState extends State Drag? _drag; ScrollHoldController? _hold; - void _handleDragDown(DragDownDetails details) { + void _handleDragDown(DragDownDetails _) { assert(_drag == null); assert(_hold == null); _hold = position!.hold(_disposeHold); 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 0882a811d54..40c4b0ef6be 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 @@ -116,6 +116,8 @@ class LinkedScrollControllerGroup { /// /// This change notifier de-duplicates change events by only firing listeners /// when the scroll offset of the group has changed. +// TODO(jacobr): create a shorter tye name. +// ignore: prefer-correct-type-name class _LinkedScrollControllerGroupOffsetNotifier extends ChangeNotifier { _LinkedScrollControllerGroupOffsetNotifier(this.controllerGroup); @@ -325,7 +327,6 @@ class _LinkedScrollPosition extends ScrollPositionWithSingleContext { // We override this method to make it public (overridden method is protected) @override - // ignore: unnecessary_overrides void updateUserScrollDirection(ScrollDirection value) { super.updateUserScrollDirection(value); } diff --git a/packages/devtools_app/lib/src/shared/primitives/syntax_highlighting.dart b/packages/devtools_app/lib/src/shared/primitives/syntax_highlighting.dart index c5986f8342b..b1c408a3af8 100644 --- a/packages/devtools_app/lib/src/shared/primitives/syntax_highlighting.dart +++ b/packages/devtools_app/lib/src/shared/primitives/syntax_highlighting.dart @@ -57,8 +57,8 @@ class TextmateGrammar { } void _parseFileRules() { - final List patterns = _definition['patterns']; - for (Map info in patterns.cast>()) { + final List patterns = _definition['patterns']; + for (Map info in patterns.cast>()) { _fileRules.add(Rule(info['name']).._parse(info)); } print('fileRules: $_fileRules'); @@ -79,7 +79,7 @@ class Rule { final String? name; - void _parse(Map? info) { + void _parse(Map? _) { // todo: } 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 cb5cfca719e..5d7949a38da 100644 --- a/packages/devtools_app/lib/src/shared/primitives/trace_event.dart +++ b/packages/devtools_app/lib/src/shared/primitives/trace_event.dart @@ -8,14 +8,14 @@ class TraceEvent { /// Creates a timeline event given JSON-encoded event data. TraceEvent(this.json) - : name = json[nameKey], - category = json[categoryKey], - phase = json[phaseKey], - processId = json[processIdKey], - threadId = json[threadIdKey], - duration = json[durationKey], - timestampMicros = json[timestampKey], - args = json[argsKey]; + : 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'; @@ -44,7 +44,7 @@ class TraceEvent { static const frameNumberArg = 'frame_number'; /// The original event JSON. - final Map json; + final Map json; /// The name of the event. /// @@ -74,12 +74,12 @@ class TraceEvent { /// Each async event has an additional required parameter id. We consider the /// events with the same category and id as events from the same event tree. - dynamic get id => json[idKey]; + String? get id => json[idKey] as String?; /// An optional scope string can be specified to avoid id conflicts, in which /// case we consider events with the same category, scope, and id as events /// from the same event tree. - String? get scope => json[scopeKey]; + String? get scope => json[scopeKey] as String?; /// The duration of the event, in microseconds. /// @@ -93,7 +93,7 @@ class TraceEvent { final int? timestampMicros; /// Arbitrary data attached to the event. - final Map? args; + final Map? args; String get asyncUID => generateAsyncUID(id: id, category: category, scope: scope); diff --git a/packages/devtools_app/lib/src/shared/primitives/utils.dart b/packages/devtools_app/lib/src/shared/primitives/utils.dart index 78d339e8e2b..c4333387675 100644 --- a/packages/devtools_app/lib/src/shared/primitives/utils.dart +++ b/packages/devtools_app/lib/src/shared/primitives/utils.dart @@ -284,7 +284,8 @@ String pluralize(String word, int count, {String? plural}) => /// `GestureBinding.handleBeginFrame`. /// /// See (https://github.com/dart-lang/sdk/issues/36999). -String getSimpleStackFrameName(String name) { +String getSimpleStackFrameName(String? name) { + name ??= ''; final newName = name.replaceAll('', ''); // If the class name contains a space, then it is not a valid Dart name. We @@ -430,7 +431,7 @@ class JsonUtils { } static List getValues(Map json, String member) { - final List? values = json[member] as List?; + final values = json[member] as List?; if (values == null || values.isEmpty) { return const []; } @@ -860,7 +861,7 @@ class DebugTimingLogger { class MovingAverage { MovingAverage({ this.averagePeriod = 50, - this.ratio = .5, + this.ratio = 0.5, List? newDataSet, }) : assert(ratio >= 0 && ratio <= 1, 'Value ratio $ratio is not 0 to 1.') { if (newDataSet != null) { @@ -1216,7 +1217,7 @@ String prettyTimestamp( class ListValueNotifier extends ChangeNotifier implements ValueListenable> { /// Creates a [ListValueNotifier] that wraps this value [_rawList]. - ListValueNotifier(List rawList) : _rawList = List.from(rawList) { + ListValueNotifier(List rawList) : _rawList = List.of(rawList) { _currentList = ImmutableList(_rawList); } @@ -1486,7 +1487,6 @@ extension UriExtension on Uri { String? userInfo, String? host, int? port, - String? path, Iterable? pathSegments, String? query, Map? queryParameters, diff --git a/packages/devtools_app/lib/src/shared/routing.dart b/packages/devtools_app/lib/src/shared/routing.dart index 285d1fb1875..9a481046461 100644 --- a/packages/devtools_app/lib/src/shared/routing.dart +++ b/packages/devtools_app/lib/src/shared/routing.dart @@ -140,20 +140,18 @@ class DevToolsRouterDelegate extends RouterDelegate return Navigator( key: navigatorKey, pages: [_getPage(context, page, args, state)], - onPopPage: _handleOnPopPage, + onPopPage: (_, __) { + if (routes.length <= 1) { + return false; + } + + routes.removeLast(); + notifyListeners(); + return true; + }, ); } - bool _handleOnPopPage(Route route, dynamic result) { - if (routes.length <= 1) { - return false; - } - - routes.removeLast(); - notifyListeners(); - return true; - } - /// Navigates to a new page, optionally updating arguments and state. /// /// If page, args, and state would be the same, does nothing. diff --git a/packages/devtools_app/lib/src/shared/server_api_client.dart b/packages/devtools_app/lib/src/shared/server_api_client.dart index 4218b2c9d2d..8791b6a6fa1 100644 --- a/packages/devtools_app/lib/src/shared/server_api_client.dart +++ b/packages/devtools_app/lib/src/shared/server_api_client.dart @@ -76,7 +76,7 @@ class DevToolsServerConnection { int _nextRequestId = 0; Notification? _lastNotification; - final Map _completers = {}; + final Map> _completers = {}; /// Tie the DevTools server connection to the framework controller. /// @@ -130,7 +130,7 @@ class DevToolsServerConnection { return completer.future; } - void _handleMessage(dynamic msg) { + void _handleMessage(String msg) { try { final Map request = jsonDecode(msg); @@ -176,7 +176,7 @@ class DevToolsServerConnection { } } - void _handleResponse(String id, dynamic result) { + void _handleResponse(String id, Object? result) { final completer = _completers.remove(id); completer?.complete(result); } diff --git a/packages/devtools_app/lib/src/shared/split.dart b/packages/devtools_app/lib/src/shared/split.dart index 2cf3c11f691..8841e3280d6 100644 --- a/packages/devtools_app/lib/src/shared/split.dart +++ b/packages/devtools_app/lib/src/shared/split.dart @@ -93,7 +93,7 @@ class _SplitState extends State { @override void initState() { super.initState(); - fractions = List.from(widget.initialFractions); + fractions = List.of(widget.initialFractions); } @override @@ -101,7 +101,7 @@ class _SplitState extends State { return LayoutBuilder(builder: _buildLayout); } - Widget _buildLayout(BuildContext context, BoxConstraints constraints) { + Widget _buildLayout(BuildContext _, BoxConstraints constraints) { final width = constraints.maxWidth; final height = constraints.maxHeight; final axisSize = isHorizontal ? width : height; diff --git a/packages/devtools_app/lib/src/shared/survey.dart b/packages/devtools_app/lib/src/shared/survey.dart index 486bca55c41..48cd8babc97 100644 --- a/packages/devtools_app/lib/src/shared/survey.dart +++ b/packages/devtools_app/lib/src/shared/survey.dart @@ -49,7 +49,7 @@ class SurveyService { return null; } - void maybeShowSurveyPrompt(BuildContext context) async { + void maybeShowSurveyPrompt() async { final survey = await activeSurvey; if (survey != null) { final message = survey.title!; @@ -58,7 +58,6 @@ class SurveyService { _noThanksLabel, () => _noThanksPressed( message: message, - context: context, ), ), NotificationAction( @@ -66,7 +65,6 @@ class SurveyService { () => _takeSurveyPressed( surveyUrl: _generateSurveyUrl(survey.url!), message: message, - context: context, ), isPrimary: true, ), @@ -130,7 +128,6 @@ class SurveyService { void _noThanksPressed({ required String message, - required BuildContext context, }) async { await server.setSurveyActionTaken(); notificationService.dismiss(message); @@ -139,9 +136,8 @@ class SurveyService { void _takeSurveyPressed({ required String surveyUrl, required String message, - required BuildContext context, }) async { - await launchUrl(surveyUrl, context); + await launchUrl(surveyUrl); await server.setSurveyActionTaken(); notificationService.dismiss(message); } diff --git a/packages/devtools_app/lib/src/shared/table/table.dart b/packages/devtools_app/lib/src/shared/table/table.dart index 82ca97ec272..fc50dca0ff1 100644 --- a/packages/devtools_app/lib/src/shared/table/table.dart +++ b/packages/devtools_app/lib/src/shared/table/table.dart @@ -165,6 +165,8 @@ class FlatTableState extends State> with AutoDisposeMixin { addAutoDisposeListener(tableController.tableData); if (tableController.pinBehavior != FlatTablePinBehavior.none && + // TODO(jacobr): this lint appears to be firing incorrectly. + // ignore: avoid-unnecessary-type-assertions this is! State>) { throw StateError('$T must implement PinnableListEntry'); } @@ -247,6 +249,9 @@ class FlatTableState extends State> with AutoDisposeMixin { } Widget _buildRow({ + // Unused parameters doesn't understand that this parameter is required to + // match the signature for the rowBuilder Function. + // ignore: avoid-unused-parameters required BuildContext context, required LinkedScrollControllerGroup linkedScrollControllerGroup, required int index, @@ -599,6 +604,9 @@ class TreeTableState> extends State> required LinkedScrollControllerGroup linkedScrollControllerGroup, required int index, required List columnWidths, + // Unused parameters doesn't understand that this parameter is required to + // match the signature for the rowBuilder Function. + // ignore: avoid-unused-parameters required bool isPinned, }) { Widget rowForNode(T node) { @@ -942,6 +950,8 @@ class _TableState extends State<_Table> with AutoDisposeMixin { ); } + List get pinnedData => widget.tableController.pinnedData; + @override Widget build(BuildContext context) { // If we're at the end already, scroll to expose the new content. @@ -994,11 +1004,10 @@ class _TableState extends State<_Table> with AutoDisposeMixin { secondarySortColumn: widget.tableController.secondarySortColumn, onSortChanged: widget.tableController.sortDataAndNotify, ), - if (widget.tableController.pinnedData.isNotEmpty) ...[ + if (pinnedData.isNotEmpty) ...[ SizedBox( height: min( - widget.rowItemExtent! * - widget.tableController.pinnedData.length, + widget.rowItemExtent! * pinnedData.length, constraints.maxHeight / 2, ), child: Scrollbar( @@ -1006,7 +1015,7 @@ class _TableState extends State<_Table> with AutoDisposeMixin { controller: pinnedScrollController, child: ListView.builder( controller: pinnedScrollController, - itemCount: widget.tableController.pinnedData.length, + itemCount: pinnedData.length, itemExtent: widget.rowItemExtent, itemBuilder: (context, index) => _buildItem( context, @@ -1435,6 +1444,10 @@ class _TableRowState extends State> // widget class. final padding = column.getNodeIndentPx(node); assert(padding >= 0); + // TODO(jacobr): is this assert really always false or is this lint too + // aggressive? Consider factoring the code so this is check is less + // is for a subclass of the type of Column. + // ignore: avoid-unrelated-type-assertions if (column is ColumnRenderer) { content = (column as ColumnRenderer).build( context, 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 87cde9766d1..2347d69a39c 100644 --- a/packages/devtools_app/lib/src/shared/table/table_controller.dart +++ b/packages/devtools_app/lib/src/shared/table/table_controller.dart @@ -46,7 +46,7 @@ class FlatTableController extends TableControllerBase { @override void setData(List data, String key) { _originalData = UnmodifiableListView( - List.from(data), + List.of(data), ); // Look up the UI state for [key], and sort accordingly. @@ -66,7 +66,7 @@ class FlatTableController extends TableControllerBase { ColumnData? secondarySortColumn, String? dataKey, }) { - var data = List.from(_originalData); + var data = List.of(_originalData); pinnedData = []; data.sort( (T a, T b) => _compareData( diff --git a/packages/devtools_app/lib/src/shared/theme.dart b/packages/devtools_app/lib/src/shared/theme.dart index 37f92e9e343..afd0b1804d9 100644 --- a/packages/devtools_app/lib/src/shared/theme.dart +++ b/packages/devtools_app/lib/src/shared/theme.dart @@ -49,7 +49,6 @@ ThemeData _darkTheme(IdeTheme ideTheme) { : theme.canvasColor; return _baseTheme( theme: theme, - ideTheme: ideTheme, primaryColor: devtoolsGrey[900]!, backgroundColor: background, indicatorColor: devtoolsBlue[400]!, @@ -64,7 +63,6 @@ ThemeData _lightTheme(IdeTheme ideTheme) { : theme.canvasColor; return _baseTheme( theme: theme, - ideTheme: ideTheme, primaryColor: devtoolsBlue[600]!, backgroundColor: background, indicatorColor: Colors.yellowAccent[400]!, @@ -74,20 +72,26 @@ ThemeData _lightTheme(IdeTheme ideTheme) { ThemeData _baseTheme({ required ThemeData theme, - required IdeTheme ideTheme, required Color primaryColor, required Color backgroundColor, required Color indicatorColor, required Color textSelectionColor, }) { + final fillColor = MaterialStateProperty.resolveWith( + (states) { + if (states.contains(MaterialState.selected) && + !states.contains(MaterialState.disabled)) { + return devtoolsBlue[400]; + } + return null; + }, + ); return theme.copyWith( primaryColor: primaryColor, indicatorColor: indicatorColor, // Same values for both light and dark themes. primaryColorDark: devtoolsBlue[700], primaryColorLight: devtoolsBlue[400], - // ignore: deprecated_member_use - accentColor: devtoolsBlue[400], canvasColor: backgroundColor, scaffoldBackgroundColor: backgroundColor, outlinedButtonTheme: OutlinedButtonThemeData( @@ -111,13 +115,7 @@ ThemeData _baseTheme({ ), ), switchTheme: SwitchThemeData( - thumbColor: MaterialStateProperty.resolveWith((states) { - if (states.contains(MaterialState.selected) && - !states.contains(MaterialState.disabled)) { - return devtoolsBlue[400]; - } - return null; - }), + thumbColor: fillColor, trackColor: MaterialStateProperty.resolveWith((states) { if (states.contains(MaterialState.selected) && !states.contains(MaterialState.disabled)) { @@ -126,23 +124,9 @@ ThemeData _baseTheme({ return null; }), ), - radioTheme: RadioThemeData( - fillColor: MaterialStateProperty.resolveWith((states) { - if (states.contains(MaterialState.selected) && - !states.contains(MaterialState.disabled)) { - return devtoolsBlue[400]; - } - return null; - }), - ), + radioTheme: RadioThemeData(fillColor: fillColor), checkboxTheme: CheckboxThemeData( - fillColor: MaterialStateProperty.resolveWith((states) { - if (states.contains(MaterialState.selected) && - !states.contains(MaterialState.disabled)) { - return devtoolsBlue[400]; - } - return null; - }), + fillColor: fillColor, ), textSelectionTheme: TextSelectionThemeData( selectionColor: textSelectionColor, diff --git a/packages/devtools_app/lib/src/shared/tree.dart b/packages/devtools_app/lib/src/shared/tree.dart index bff30f51572..5995f09b6a9 100644 --- a/packages/devtools_app/lib/src/shared/tree.dart +++ b/packages/devtools_app/lib/src/shared/tree.dart @@ -74,7 +74,7 @@ class _TreeViewState> extends State> } void _updateTreeView() { - dataRoots = List.from(widget.dataRootsListenable.value); + dataRoots = List.of(widget.dataRootsListenable.value); _updateItems(); } @@ -171,30 +171,28 @@ class _TreeViewItemState> extends State<_TreeViewItem> with TickerProviderStateMixin, CollapsibleAnimationMixin { @override Widget build(BuildContext context) { - return Padding( - padding: EdgeInsets.only(left: nodeIndent(widget.data)), - child: Container( - color: widget.data.isSelected - ? Theme.of(context).colorScheme.selectedRowColor - : 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, - ), + return Container( + margin: EdgeInsets.only(left: nodeIndent(widget.data)), + color: widget.data.isSelected + ? Theme.of(context).colorScheme.selectedRowColor + : 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, ), - ) - : SizedBox(width: defaultIconSize), - Expanded(child: widget.buildDisplay(_onSelected)), - ], - ), + ), + ) + : SizedBox(width: defaultIconSize), + Expanded(child: widget.buildDisplay(_onSelected)), + ], ), ); } diff --git a/packages/devtools_app/lib/src/shared/ui/gtags.dart b/packages/devtools_app/lib/src/shared/ui/gtags.dart index 83c9e307651..d02a4dcf993 100644 --- a/packages/devtools_app/lib/src/shared/ui/gtags.dart +++ b/packages/devtools_app/lib/src/shared/ui/gtags.dart @@ -22,8 +22,9 @@ import '../analytics/analytics.dart' as ga; bool _debugAnalytics = false; @JS('gtag') -external void _gTagCommandName(String command, String name, [dynamic params]); +external void _gTagCommandName(String command, String name, [Object? params]); +// TODO(jacobr): refactor this code if we do not migrate off gtags. // ignore: avoid_classes_with_only_static_members class GTag { static const String _event = 'event'; @@ -60,7 +61,7 @@ class GtagEvent { int value = 0, bool non_interaction = false, - dynamic custom_map, + Object? custom_map, }); external String? get event_category; @@ -72,7 +73,7 @@ class GtagEvent { external int get value; // Positive number. external bool get non_interaction; - external dynamic get custom_map; // Custom metrics + external Object? get custom_map; // Custom metrics } @JS() diff --git a/packages/devtools_app/lib/src/shared/ui/search.dart b/packages/devtools_app/lib/src/shared/ui/search.dart index 0061601ef73..9615b625ab9 100644 --- a/packages/devtools_app/lib/src/shared/ui/search.dart +++ b/packages/devtools_app/lib/src/shared/ui/search.dart @@ -184,10 +184,11 @@ mixin SearchControllerMixin { List matchesForSearch( String search, { bool searchPreviousMatches = false, - }) => - []; + }); /// Called when selected match index changes. Index is 0 based + // Subclasses provide a valid implementation. + // ignore: avoid-unused-parameters void onMatchChanged(int index) {} void resetSearch() { @@ -538,7 +539,6 @@ mixin AutoCompleteSearchControllerMixin on SearchControllerMixin { /// [bottom] if false placed above TextField (search field). /// [maxWidth] if true drop-down is width of TextField otherwise minPopupWidth. OverlayEntry createAutoCompleteOverlay({ - required BuildContext context, required GlobalKey searchFieldKey, required SelectAutoComplete onTap, bool bottom = true, @@ -579,7 +579,6 @@ mixin AutoCompleteSearchControllerMixin on SearchControllerMixin { } autoCompleteOverlay = createAutoCompleteOverlay( - context: context, searchFieldKey: searchFieldKey, onTap: onTap, bottom: bottom, @@ -890,8 +889,7 @@ mixin SearchFieldMixin } } - void updateSearchField( - SearchControllerMixin controller, { + void updateSearchField({ required String newValue, required int caretPosition, }) { @@ -1098,7 +1096,7 @@ class _AutoCompleteSearchFieldState extends State<_AutoCompleteSearchField> } } - KeyEventResult _handleKeyStrokes(FocusNode node, RawKeyEvent event) { + KeyEventResult _handleKeyStrokes(FocusNode _, RawKeyEvent event) { if (event is RawKeyDownEvent) { final key = event.data.logicalKey.keyId & LogicalKeyboardKey.valueMask; @@ -1312,7 +1310,17 @@ mixin TreeDataSearchStateMixin> on TreeNode, DataSearchStateMixin {} class AutoCompleteController extends DisposableController - with SearchControllerMixin, AutoCompleteSearchControllerMixin {} + with SearchControllerMixin, AutoCompleteSearchControllerMixin { + // TODO(jacobr): seems a little surprising that returning an empty list of + // matches for the search is the intended behavior for the auto-complete + // controller. + @override + List matchesForSearch( + String search, { + bool searchPreviousMatches = false, + }) => + const []; +} class AutoCompleteMatch { AutoCompleteMatch(this.text, {this.matchedSegments = const []}); diff --git a/packages/devtools_app/lib/src/shared/utils.dart b/packages/devtools_app/lib/src/shared/utils.dart index 0dcd61b0560..a5349ffd6a5 100644 --- a/packages/devtools_app/lib/src/shared/utils.dart +++ b/packages/devtools_app/lib/src/shared/utils.dart @@ -26,7 +26,6 @@ import 'globals.dart'; Future copyToClipboard( String data, String? successMessage, - BuildContext context, ) async { await Clipboard.setData( ClipboardData( 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 230ae22a7f0..acaeb707cf2 100644 --- a/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart +++ b/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart @@ -57,10 +57,7 @@ void main() { screen = ProfilerScreen(); }); - void verifyBaseState( - ProfilerScreenBody perfScreenBody, - WidgetTester tester, - ) { + void verifyBaseState() { expect(find.byType(RecordButton), findsOneWidget); expect(find.byType(StopRecordingButton), findsOneWidget); expect(find.byType(ClearButton), findsOneWidget); @@ -106,7 +103,7 @@ void main() { const perfScreenBody = ProfilerScreenBody(); await pumpProfilerScreenBody(tester, perfScreenBody); expect(find.byType(ProfilerScreenBody), findsOneWidget); - verifyBaseState(perfScreenBody, tester); + verifyBaseState(); }); testWidgetsWithWindowSize( @@ -117,7 +114,7 @@ void main() { const perfScreenBody = ProfilerScreenBody(); await pumpProfilerScreenBody(tester, perfScreenBody); expect(find.byType(ProfilerScreenBody), findsOneWidget); - verifyBaseState(perfScreenBody, tester); + verifyBaseState(); }); testWidgetsWithWindowSize( @@ -127,7 +124,7 @@ void main() { const perfScreenBody = ProfilerScreenBody(); await pumpProfilerScreenBody(tester, perfScreenBody); expect(find.byType(ProfilerScreenBody), findsOneWidget); - verifyBaseState(perfScreenBody, tester); + verifyBaseState(); // Start recording. await tester.tap(find.byType(RecordButton)); @@ -149,7 +146,7 @@ void main() { // Clear the profile. await tester.tap(find.byType(ClearButton)); await tester.pump(); - verifyBaseState(perfScreenBody, tester); + verifyBaseState(); }, ); @@ -171,7 +168,7 @@ void main() { await tester.tap(find.text('Enable profiler')); await tester.pumpAndSettle(); - verifyBaseState(perfScreenBody, tester); + verifyBaseState(); }); }); } 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 03c0d076671..07da86ffe77 100644 --- a/packages/devtools_app/test/debugger/debugger_codeview_statistics_test.dart +++ b/packages/devtools_app/test/debugger/debugger_codeview_statistics_test.dart @@ -71,6 +71,7 @@ void main() { 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, diff --git a/packages/devtools_app/test/inspector/layout_explorer/inspector_data_models_test.dart b/packages/devtools_app/test/inspector/layout_explorer/inspector_data_models_test.dart index b0f8819c339..5fb6ca370d4 100644 --- a/packages/devtools_app/test/inspector/layout_explorer/inspector_data_models_test.dart +++ b/packages/devtools_app/test/inspector/layout_explorer/inspector_data_models_test.dart @@ -107,6 +107,9 @@ void main() { group('childrenRenderProperties tests', () { const maxMainAxisDimension = 500.0; + + // This is a false positive. + // ignore: avoid-unused-parameters double maxSizeAvailable(Axis axis) => maxMainAxisDimension; List childrenRenderProperties( @@ -157,7 +160,7 @@ void main() { ), RenderProperties( axis: Axis.horizontal, - size: const Size(261.50, 500), + size: const Size(261.5, 500), realSize: const Size(75.0, 25.0), offset: const Offset(250.0, 0.0), ), diff --git a/packages/devtools_app/test/inspector/layout_explorer/layout_explorer_serialization_delegate.dart b/packages/devtools_app/test/inspector/layout_explorer/layout_explorer_serialization_delegate.dart index 90523177895..4b6e3536ccd 100644 --- a/packages/devtools_app/test/inspector/layout_explorer/layout_explorer_serialization_delegate.dart +++ b/packages/devtools_app/test/inspector/layout_explorer/layout_explorer_serialization_delegate.dart @@ -32,6 +32,7 @@ class LayoutExplorerSerializationDelegate includeProperties: true, ), ); + // Required for test. // ignore: invalid_use_of_protected_member final Constraints constraints = renderObject.constraints; diff --git a/packages/devtools_app/test/inspector/utils/fake_inspector_tree.dart b/packages/devtools_app/test/inspector/utils/fake_inspector_tree.dart index 1405161962e..535deec800f 100644 --- a/packages/devtools_app/test/inspector/utils/fake_inspector_tree.dart +++ b/packages/devtools_app/test/inspector/utils/fake_inspector_tree.dart @@ -51,7 +51,6 @@ class FakeInspectorTree extends InspectorTreeController { // Debugging string to make it easy to write integration tests. String toStringDeep({ bool hidePropertyLines = false, - bool includeTextStyles = false, }) { if (root == null) return '\n'; // Visualize the ticks computed for this node so that bugs in the tick diff --git a/packages/devtools_app/test/legacy_integration_tests/debugger.dart b/packages/devtools_app/test/legacy_integration_tests/debugger.dart index b03b5913bba..eb5cb40d8e4 100644 --- a/packages/devtools_app/test/legacy_integration_tests/debugger.dart +++ b/packages/devtools_app/test/legacy_integration_tests/debugger.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +library debugger; + import 'package:devtools_shared/devtools_test_utils.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -356,7 +358,7 @@ class DebuggingManager { Future> getVariables() async { final AppResponse response = await tools.tabInstance.send('debugger.getVariables'); - final List result = response.result as List; + final List result = response.result as List; return result.cast(); } @@ -387,14 +389,14 @@ class DebuggingManager { Future> getBreakpoints() async { final AppResponse response = await tools.tabInstance.send('debugger.getBreakpoints'); - final List result = response.result as List; + final result = response.result as List; return result.cast(); } Future> getScripts() async { final AppResponse response = await tools.tabInstance.send('debugger.getScripts'); - final List result = response.result as List; + final result = response.result as List; return result.cast(); } @@ -407,7 +409,7 @@ class DebuggingManager { Future> getCallStackFrames() async { final AppResponse response = await tools.tabInstance.send('debugger.getCallStackFrames'); - final List result = response.result as List; + final result = response.result as List; return result.cast(); } } diff --git a/packages/devtools_app/test/legacy_integration_tests/integration.dart b/packages/devtools_app/test/legacy_integration_tests/integration.dart index 9b3a67beb76..a39edbc3ac8 100644 --- a/packages/devtools_app/test/legacy_integration_tests/integration.dart +++ b/packages/devtools_app/test/legacy_integration_tests/integration.dart @@ -76,22 +76,28 @@ class BrowserManager { Future createNewTab() async { final String targetId = await this.tab.createNewTarget(); + // This is a false positive for this lint. + // ignore: prefer-moving-to-variable await delay(); final ChromeTab tab = (await chromeProcess.connectToTabId('localhost', targetId))!; await tab.connect(verbose: true); + // This is a false positive for this lint. + // ignore: prefer-moving-to-variable await delay(); await tab.wipConnection!.target.activateTarget(targetId); + // This is a false positive for this lint. + // ignore: prefer-moving-to-variable await delay(); return BrowserTabInstance(tab); } - Future teardown() async { + void teardown() { chromeProcess.kill(); } } @@ -106,8 +112,7 @@ class BrowserTabInstance { final String value = '${message.value}'; if (value.startsWith('[') && value.endsWith(']')) { try { - final dynamic msg = - jsonDecode(value.substring(1, value.length - 1)); + final msg = jsonDecode(value.substring(1, value.length - 1)); if (msg is Map) { _handleBrowserMessage(msg); } @@ -156,7 +161,7 @@ class BrowserTabInstance { Stream get onEvent => _eventStream.stream; - Future send(String method, [dynamic params]) async { + Future send(String method, [Object? params]) async { _remote ??= await _getAppChannelObject(); final int id = _nextId++; @@ -168,7 +173,7 @@ class BrowserTabInstance { await tab.wipConnection!.runtime.callFunctionOn( "function (method, id, params) { return window['devtools'].send(method, id, params); }", objectId: _remote!.objectId, - arguments: [method, id, params], + arguments: [method, id, params], ); return completer.future; @@ -217,7 +222,7 @@ class AppEvent { String? get event => json['event']; - dynamic get params => json['params']; + Object? get params => json['params']; @override String toString() => '$event ${params ?? ''}'; @@ -230,7 +235,7 @@ class AppResponse { int? get id => json['id']; - dynamic get result => json['result']; + Object? get result => json['result']; bool get hasError => json.containsKey('error'); @@ -408,7 +413,7 @@ class WebBuildFixture { static Future _runFlutter( List buildArgs, { bool verbose = false, - }) async { + }) { // Remove the DART_VM_OPTIONS env variable from the child process, so the // Dart VM doesn't try and open a service protocol port if // 'DART_VM_OPTIONS: --enable-vm-service:63990' was passed in. diff --git a/packages/devtools_app/test/legacy_integration_tests/integration_test.dart b/packages/devtools_app/test/legacy_integration_tests/integration_test.dart index 8cc7124b159..07fc88c77a0 100644 --- a/packages/devtools_app/test/legacy_integration_tests/integration_test.dart +++ b/packages/devtools_app/test/legacy_integration_tests/integration_test.dart @@ -29,7 +29,7 @@ void main() { }); tearDownAll(() async { - await browserManager.teardown(); + browserManager.teardown(); await webBuildFixture.teardown(); }); diff --git a/packages/devtools_app/test/logging/logging_screen_data_test.dart b/packages/devtools_app/test/logging/logging_screen_data_test.dart index 9135a631ba6..cd59e6f45d8 100644 --- a/packages/devtools_app/test/logging/logging_screen_data_test.dart +++ b/packages/devtools_app/test/logging/logging_screen_data_test.dart @@ -27,8 +27,6 @@ void main() async { ); } - await ensureInspectorDependencies(); - when(fakeServiceManager.connectedApp!.isFlutterWebAppNow).thenReturn(false); when(fakeServiceManager.connectedApp!.isProfileBuildNow).thenReturn(false); when(fakeServiceManager.errorBadgeManager.errorCountNotifier('logging')) diff --git a/packages/devtools_app/test/logging/logging_screen_test.dart b/packages/devtools_app/test/logging/logging_screen_test.dart index 66f871ccbdb..312e4624a60 100644 --- a/packages/devtools_app/test/logging/logging_screen_test.dart +++ b/packages/devtools_app/test/logging/logging_screen_test.dart @@ -26,7 +26,6 @@ void main() async { late MockLoggingController mockLoggingController; const windowSize = Size(1000.0, 1000.0); - await ensureInspectorDependencies(); mockLoggingController = MockLoggingController(); final FakeServiceManager fakeServiceManager = FakeServiceManager(); diff --git a/packages/devtools_app/test/memory/allocation_profile/allocation_profile_table_view_test.dart b/packages/devtools_app/test/memory/allocation_profile/allocation_profile_table_view_test.dart index d3385e45297..a84276e256f 100644 --- a/packages/devtools_app/test/memory/allocation_profile/allocation_profile_table_view_test.dart +++ b/packages/devtools_app/test/memory/allocation_profile/allocation_profile_table_view_test.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:devtools_app/src/screens/memory/memory_controller.dart'; import 'package:devtools_app/src/screens/memory/memory_screen.dart'; import 'package:devtools_app/src/screens/memory/memory_tabs.dart'; import 'package:devtools_app/src/screens/memory/panes/allocation_profile/allocation_profile_table_view_controller.dart'; @@ -23,10 +22,7 @@ void main() { await scene.setUp(); }); - Future pumpMemoryScreen( - WidgetTester tester, { - MemoryController? memoryController, - }) async { + Future pumpMemoryScreen(WidgetTester tester) async { await tester.pumpWidget(scene.build()); // Delay to ensure the memory profiler has collected data. await tester.pumpAndSettle(const Duration(seconds: 1)); diff --git a/packages/devtools_app/test/memory/leaks/diagnostics/leak_analyzer_test.dart b/packages/devtools_app/test/memory/leaks/diagnostics/leak_analyzer_test.dart index a08c18f8bd9..f57d3f549b1 100644 --- a/packages/devtools_app/test/memory/leaks/diagnostics/leak_analyzer_test.dart +++ b/packages/devtools_app/test/memory/leaks/diagnostics/leak_analyzer_test.dart @@ -63,7 +63,7 @@ void main() { LeakReport _createReport(int code, String path) => LeakReport( type: '', - context: const {}, - code: 0, + context: const {}, + code: code, trackedClass: 'trackedClass', )..retainingPath = path; diff --git a/packages/devtools_app/test/memory/leaks/model_test.dart b/packages/devtools_app/test/memory/leaks/model_test.dart index f7e01366c28..89d36626859 100644 --- a/packages/devtools_app/test/memory/leaks/model_test.dart +++ b/packages/devtools_app/test/memory/leaks/model_test.dart @@ -16,7 +16,7 @@ void main() { reports: [ LeakReport( type: 'type', - context: const {}, + context: const {}, code: 2, trackedClass: 'trackedClass', ) diff --git a/packages/devtools_app/test/memory/memory_screen_test.dart b/packages/devtools_app/test/memory/memory_screen_test.dart index 9446d57dfdf..96d1eee9ced 100644 --- a/packages/devtools_app/test/memory/memory_screen_test.dart +++ b/packages/devtools_app/test/memory/memory_screen_test.dart @@ -82,7 +82,6 @@ void main() { group('MemoryScreen', () { setUp(() async { - await ensureInspectorDependencies(); setGlobal(OfflineModeController, OfflineModeController()); fakeServiceManager = FakeServiceManager(); when(fakeServiceManager.connectedApp!.isDartWebAppNow).thenReturn(false); diff --git a/packages/devtools_app/test/memory/memory_service_test.dart b/packages/devtools_app/test/memory/memory_service_test.dart index fd4268aad08..3f3c4fc1ee1 100644 --- a/packages/devtools_app/test/memory/memory_service_test.dart +++ b/packages/devtools_app/test/memory/memory_service_test.dart @@ -32,7 +32,7 @@ void main() async { env.afterNewSetup = () async { memoryController = MemoryController(); - await memoryController.startTimeline(); + memoryController.startTimeline(); }; group('MemoryController', () { diff --git a/packages/devtools_app/test/network/network_profiler_test.dart b/packages/devtools_app/test/network/network_profiler_test.dart index bacf9f08466..c12a870c65e 100644 --- a/packages/devtools_app/test/network/network_profiler_test.dart +++ b/packages/devtools_app/test/network/network_profiler_test.dart @@ -187,7 +187,7 @@ void main() { } } - Future validateOverviewTab(NetworkRequest data) async { + Future validateOverviewTab() async { // Switch to overview tab. await tester.tap(find.byKey(NetworkRequestInspector.overviewTabKey)); await tester.pumpAndSettle(); @@ -268,7 +268,7 @@ void main() { await validateResponseTab(selection); await validateCookiesTab(selection); } - await validateOverviewTab(selection); + await validateOverviewTab(); } // Pause recording. diff --git a/packages/devtools_app/test/performance/performance_controller_test.dart b/packages/devtools_app/test/performance/performance_controller_test.dart index 6e243e0b96f..81faaf301a6 100644 --- a/packages/devtools_app/test/performance/performance_controller_test.dart +++ b/packages/devtools_app/test/performance/performance_controller_test.dart @@ -9,7 +9,7 @@ import 'package:mockito/mockito.dart'; // TODO(kenz): add better test coverage for [PerformanceController]. -void main() async { +void main() { late PerformanceController controller; late MockServiceConnectionManager mockServiceManager; @@ -31,17 +31,17 @@ void main() async { controller = PerformanceController(); }); - test('setActiveFeature', () { + test('setActiveFeature', () async { expect(controller.flutterFramesController.isActiveFeature, isTrue); expect(controller.timelineEventsController.isActiveFeature, isFalse); expect(controller.rasterStatsController.isActiveFeature, isFalse); - controller.setActiveFeature(controller.timelineEventsController); + await controller.setActiveFeature(controller.timelineEventsController); expect(controller.flutterFramesController.isActiveFeature, isTrue); expect(controller.timelineEventsController.isActiveFeature, isTrue); expect(controller.rasterStatsController.isActiveFeature, isFalse); - controller.setActiveFeature(controller.rasterStatsController); + await controller.setActiveFeature(controller.rasterStatsController); expect(controller.flutterFramesController.isActiveFeature, isTrue); expect(controller.timelineEventsController.isActiveFeature, isFalse); expect(controller.rasterStatsController.isActiveFeature, isTrue); diff --git a/packages/devtools_app/test/performance/performance_screen_test.dart b/packages/devtools_app/test/performance/performance_screen_test.dart index b1b765957c5..1611acf32ac 100644 --- a/packages/devtools_app/test/performance/performance_screen_test.dart +++ b/packages/devtools_app/test/performance/performance_screen_test.dart @@ -77,7 +77,6 @@ void main() { group('PerformanceScreen', () { setUp(() async { - await ensureInspectorDependencies(); await _setUpServiceManagerWithTimeline(testTimelineJson); controller = PerformanceController(); await controller.initialized; diff --git a/packages/devtools_app/test/performance/timeline_events/legacy/timeline_flame_chart_test.dart b/packages/devtools_app/test/performance/timeline_events/legacy/timeline_flame_chart_test.dart index 8afafef7ab3..5054602692e 100644 --- a/packages/devtools_app/test/performance/timeline_events/legacy/timeline_flame_chart_test.dart +++ b/packages/devtools_app/test/performance/timeline_events/legacy/timeline_flame_chart_test.dart @@ -21,9 +21,9 @@ void main() { FakeServiceManager fakeServiceManager; late PerformanceController controller; - Future _setUpServiceManagerWithTimeline( + void _setUpServiceManagerWithTimeline( Map timelineJson, - ) async { + ) { fakeServiceManager = FakeServiceManager( service: FakeServiceManager.createFakeService( timelineData: vm_service.Timeline.parse(timelineJson)!, @@ -43,8 +43,8 @@ void main() { } group('$TimelineEventsView', () { - setUp(() async { - await _setUpServiceManagerWithTimeline(testTimelineJson); + setUp(() { + _setUpServiceManagerWithTimeline(testTimelineJson); }); Future pumpPerformanceScreenBody( @@ -80,7 +80,7 @@ void main() { testWidgetsWithWindowSize('builds header with search field', windowSize, (WidgetTester tester) async { await tester.runAsync(() async { - await _setUpServiceManagerWithTimeline({}); + _setUpServiceManagerWithTimeline({}); await pumpPerformanceScreenBody(tester); await tester.pumpAndSettle(); expect(find.byType(RefreshTimelineEventsButton), findsOneWidget); @@ -92,7 +92,7 @@ void main() { testWidgetsWithWindowSize('can show help dialog', windowSize, (WidgetTester tester) async { await tester.runAsync(() async { - await _setUpServiceManagerWithTimeline({}); + _setUpServiceManagerWithTimeline({}); await pumpPerformanceScreenBody(tester); await tester.pumpAndSettle(); @@ -127,7 +127,7 @@ void main() { testWidgetsWithWindowSize('builds flame chart with no data', windowSize, (WidgetTester tester) async { await tester.runAsync(() async { - await _setUpServiceManagerWithTimeline({}); + _setUpServiceManagerWithTimeline({}); await pumpPerformanceScreenBody(tester, runAsync: true); await tester.pumpAndSettle(); expect( @@ -168,7 +168,6 @@ void main() { // Await delay for golden comparison. await tester.pumpAndSettle(const Duration(seconds: 2)); }, - // ignore: avoid_redundant_argument_values skip: kIsWeb, ); }); diff --git a/packages/devtools_app/test/primitives/utils_test.dart b/packages/devtools_app/test/primitives/utils_test.dart index 833e41fc5f0..41514541fc2 100644 --- a/packages/devtools_app/test/primitives/utils_test.dart +++ b/packages/devtools_app/test/primitives/utils_test.dart @@ -1556,9 +1556,7 @@ void main() { required String? subtract, required double? from, }) => - // ignore: unnecessary_cast - _SubtractionResult(subtract: subtract, from: from) - as _SubtractionResult?; + _SubtractionResult(subtract: subtract, from: from); final result = subtractMaps( substract: null, @@ -1579,9 +1577,7 @@ void main() { required String? subtract, required double? from, }) => - // ignore: unnecessary_cast - _SubtractionResult(subtract: subtract, from: from) - as _SubtractionResult?; + _SubtractionResult(subtract: subtract, from: from); final result = subtractMaps( substract: subtract, diff --git a/packages/devtools_app/test/shared/about_dialog_test.dart b/packages/devtools_app/test/shared/about_dialog_test.dart index cd449879b68..5fdd8f27faa 100644 --- a/packages/devtools_app/test/shared/about_dialog_test.dart +++ b/packages/devtools_app/test/shared/about_dialog_test.dart @@ -41,11 +41,11 @@ void main() { testWidgets('content renders correctly', (WidgetTester tester) async { await tester.pumpWidget(wrap(aboutDialog)); expect(find.text('About DevTools'), findsOneWidget); - expect(findSubstring(aboutDialog, devtools.version), findsOneWidget); + expect(findSubstring(devtools.version), findsOneWidget); expect(find.text('release notes'), findsOneWidget); expect(find.textContaining('Encountered an issue?'), findsOneWidget); expect( - findSubstring(aboutDialog, 'github.com/flutter/devtools/issues/new'), + findSubstring('github.com/flutter/devtools/issues/new'), findsOneWidget, ); expect(find.text('Contributing'), findsOneWidget); @@ -53,10 +53,10 @@ void main() { find.textContaining('Want to contribute to DevTools?'), findsOneWidget, ); - expect(findSubstring(aboutDialog, 'CONTRIBUTING'), findsOneWidget); + expect(findSubstring('CONTRIBUTING'), findsOneWidget); expect(find.textContaining('connect with us on'), findsOneWidget); expect( - findSubstring(aboutDialog, 'Discord'), + findSubstring('Discord'), findsOneWidget, ); }); diff --git a/packages/devtools_app/test/shared/ansi_up_test.dart b/packages/devtools_app/test/shared/ansi_up_test.dart index 965387943c4..2daa48a954f 100644 --- a/packages/devtools_app/test/shared/ansi_up_test.dart +++ b/packages/devtools_app/test/shared/ansi_up_test.dart @@ -164,9 +164,6 @@ void main() { } setUp(() async { - // TODO(polinach): remove unnecessary setup steps after fixing - // https://github.com/flutter/devtools/issues/3616. - await ensureInspectorDependencies(); mockLoggingController = MockLoggingController(); when(mockLoggingController.data).thenReturn([]); when(mockLoggingController.search).thenReturn(''); diff --git a/packages/devtools_app/test/shared/auto_complete_test.dart b/packages/devtools_app/test/shared/auto_complete_test.dart index 7fe204a504e..3050aa8c3f3 100644 --- a/packages/devtools_app/test/shared/auto_complete_test.dart +++ b/packages/devtools_app/test/shared/auto_complete_test.dart @@ -6,6 +6,9 @@ import 'package:devtools_app/src/shared/ui/search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +// Set debug to true displays editing parts. +bool debug = false; + void main() { group('AutoComplete', () { setUp(() { @@ -22,11 +25,7 @@ void main() { ); } - // Set debug to true displays editing parts. - const debug = false; - void outputResult(int num, EditingParts editingParts) { - // ignore: dead_code if (debug) { print( '$num. left=${editingParts.leftSide}, ' diff --git a/packages/devtools_app/test/shared/auto_dispose_mixin_test.dart b/packages/devtools_app/test/shared/auto_dispose_mixin_test.dart index 303be13778b..7a572433e85 100644 --- a/packages/devtools_app/test/shared/auto_dispose_mixin_test.dart +++ b/packages/devtools_app/test/shared/auto_dispose_mixin_test.dart @@ -32,7 +32,7 @@ class _AutoDisposedWidgetState extends State autoDisposeStreamSubscription(widget.stream.listen(_onData)); } - void _onData(dynamic data) { + void _onData(Object? _) { eventCount++; } diff --git a/packages/devtools_app/test/shared/device_dialog_test.dart b/packages/devtools_app/test/shared/device_dialog_test.dart index e6729b782af..00517baa7e8 100644 --- a/packages/devtools_app/test/shared/device_dialog_test.dart +++ b/packages/devtools_app/test/shared/device_dialog_test.dart @@ -17,9 +17,9 @@ void main() { const windowSize = Size(2000.0, 1000.0); group('DeviceDialog', () { - Future initServiceManager({ + void initServiceManager({ bool flutterVersionServiceAvailable = true, - }) async { + }) { final availableServices = [ if (flutterVersionServiceAvailable) registrations.flutterVersion.service, @@ -44,8 +44,8 @@ void main() { DeviceDialog deviceDialog; - setUp(() async { - await initServiceManager(); + setUp(() { + initServiceManager(); }); testWidgetsWithWindowSize('builds dialog for dart web app', windowSize, @@ -282,7 +282,7 @@ void main() { expect(find.richText('VM Flags'), findsOneWidget); expect(find.richText('flag 1 name'), findsOneWidget); final RichText commentText = tester.firstWidget( - findSubstring(vmFlagsDialog, 'flag 1 comment'), + findSubstring('flag 1 comment'), ); expect(commentText, isNotNull); }); diff --git a/packages/devtools_app/test/shared/extent_delegate_list_view_test.dart b/packages/devtools_app/test/shared/extent_delegate_list_view_test.dart index eeb7723dd22..689156a06d2 100644 --- a/packages/devtools_app/test/shared/extent_delegate_list_view_test.dart +++ b/packages/devtools_app/test/shared/extent_delegate_list_view_test.dart @@ -48,7 +48,7 @@ void main() { testWidgets('builds successfully with customPointerSignalHandler', (tester) async { int pointerSignalEventCount = 0; - void _handlePointerSignal(PointerSignalEvent event) { + void _handlePointerSignal(PointerSignalEvent _) { pointerSignalEventCount++; } diff --git a/packages/devtools_app/test/shared/import_export_test.dart b/packages/devtools_app/test/shared/import_export_test.dart index d063f05925d..21a66b126e2 100644 --- a/packages/devtools_app/test/shared/import_export_test.dart +++ b/packages/devtools_app/test/shared/import_export_test.dart @@ -102,17 +102,17 @@ void main() async { final nonDevToolsFileJson = DevToolsJsonFile( name: 'nonDevToolsFileJson', lastModifiedTime: DateTime.fromMicrosecondsSinceEpoch(1000), - data: {}, + data: {}, ); final nonDevToolsFileJsonWithListData = DevToolsJsonFile( name: 'nonDevToolsFileJsonWithListData', lastModifiedTime: DateTime.fromMicrosecondsSinceEpoch(1000), - data: >[], + data: >[], ); final devToolsFileJson = DevToolsJsonFile( name: 'devToolsFileJson', lastModifiedTime: DateTime.fromMicrosecondsSinceEpoch(2000), - data: { + data: { 'devToolsSnapshot': true, 'activeScreenId': 'example', 'example': {'title': 'example custom tools'} diff --git a/packages/devtools_app/test/shared/initializer_test.dart b/packages/devtools_app/test/shared/initializer_test.dart index 384ebfda73e..e83d3a38eae 100644 --- a/packages/devtools_app/test/shared/initializer_test.dart +++ b/packages/devtools_app/test/shared/initializer_test.dart @@ -17,7 +17,6 @@ void main() { late MaterialApp app; const Key initializedKey = Key('initialized'); setUp(() async { - await ensureInspectorDependencies(); final serviceManager = FakeServiceManager(); when(serviceManager.connectedApp!.isDartWebApp) .thenAnswer((_) => Future.value(false)); @@ -28,7 +27,6 @@ void main() { initialRoute: '/init', routes: { '/init': (_) => Initializer( - // ignore: avoid_redundant_argument_values url: null, builder: (_) => const SizedBox(key: initializedKey), ), diff --git a/packages/devtools_app/test/shared/json_to_service_cache_test.dart b/packages/devtools_app/test/shared/json_to_service_cache_test.dart index d236bde6423..b8f64320ba6 100644 --- a/packages/devtools_app/test/shared/json_to_service_cache_test.dart +++ b/packages/devtools_app/test/shared/json_to_service_cache_test.dart @@ -9,7 +9,7 @@ import 'package:vm_service/vm_service.dart'; void main() { group('JsonToServiceCache', () { test('basic', () { - const data = { + const data = { 'id': 1, 'map': { 'foo': 'bar', @@ -90,7 +90,7 @@ void main() { }); test('sub-collection support', () { - final data = { + final data = { 'list': [ for (int i = 0; i < 10; ++i) i, ], diff --git a/packages/devtools_app/test/shared/service_manager_test.dart b/packages/devtools_app/test/shared/service_manager_test.dart index 008c58cfa76..e0a020ca74d 100644 --- a/packages/devtools_app/test/shared/service_manager_test.dart +++ b/packages/devtools_app/test/shared/service_manager_test.dart @@ -532,7 +532,7 @@ Future _verifyInitialExtensionStateInServiceManager( Future _verifyExtensionStateInServiceManager( String extensionName, bool enabled, - dynamic value, + Object? value, ) async { final stateListenable = serviceManager.serviceExtensionManager .getServiceExtensionState(extensionName); diff --git a/packages/devtools_app/test/shared/split_test.dart b/packages/devtools_app/test/shared/split_test.dart index 49867c0f89e..9a706654ba0 100644 --- a/packages/devtools_app/test/shared/split_test.dart +++ b/packages/devtools_app/test/shared/split_test.dart @@ -46,7 +46,7 @@ void main() { testWidgets('with 50% space to first child', (WidgetTester tester) async { final split = buildSplit( Axis.horizontal, - initialFractions: [0.50, 0.50], + initialFractions: [0.5, 0.5], ); await tester.pumpWidget(wrap(split)); expectEqualSizes( diff --git a/packages/devtools_app/test/shared/table_test.dart b/packages/devtools_app/test/shared/table_test.dart index 34fc01e3b77..4c8f74af7ce 100644 --- a/packages/devtools_app/test/shared/table_test.dart +++ b/packages/devtools_app/test/shared/table_test.dart @@ -969,6 +969,7 @@ void main() { 'and no play', 'makes Ben', 'a dull boy', + // String is maybe a little easier to read this way. // ignore: no_adjacent_strings_in_list 'The quick brown fox jumps over the lazy dog, although the fox ' "can't jump very high and the dog is very, very small, so it really" diff --git a/packages/devtools_app/test/shared/treemap_test.dart b/packages/devtools_app/test/shared/treemap_test.dart index b606c8643ba..34e53443125 100644 --- a/packages/devtools_app/test/shared/treemap_test.dart +++ b/packages/devtools_app/test/shared/treemap_test.dart @@ -185,7 +185,6 @@ void main() { matchesDevToolsGolden('../test_infra/goldens/treemap_sizes.png'), ); }, - // ignore: avoid_redundant_argument_values skip: kIsWeb, ); }); @@ -211,7 +210,6 @@ void main() { // Await delay for golden comparison. await tester.pumpAndSettle(const Duration(seconds: 2)); }, - // ignore: avoid_redundant_argument_values skip: kIsWeb, ); }); @@ -237,7 +235,6 @@ void main() { // Await delay for golden comparison. await tester.pumpAndSettle(const Duration(seconds: 2)); }, - // ignore: avoid_redundant_argument_values skip: kIsWeb, ); }); diff --git a/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/main.dart b/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/main.dart index cf3ae5bee0f..b055759059a 100644 --- a/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/main.dart +++ b/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/main.dart @@ -3,10 +3,9 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - -// ignore: unused_import +// Unused imports are useful for testing autocomplete. +// ignore_for_file: unused_import import 'src/autocomplete.dart'; -// ignore: unused_import import 'src/other_classes.dart'; void main() => runApp(MyApp()); diff --git a/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete.dart b/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete.dart index 9d2d4e1b1f7..bb890e98ba9 100644 --- a/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete.dart +++ b/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete.dart @@ -5,11 +5,15 @@ import 'dart:developer' as developer; import 'dart:math' as math; -// ignore: unused_import +// These lints get in the way of testing autocomplete. +// ignore_for_file: unused_import, unused_local_variable, unused_element, prefer_final_locals + import 'autocomplete_helper_library.dart'; export 'other_classes.dart'; +// Unused parameters are needed to test autocomplete. +// ignore_for_file: avoid-unused-parameters class FooClass { FooClass(); FooClass.namedConstructor(); @@ -28,7 +32,6 @@ class FooClass { } } -// ignore: unused_element class _PrivateClass {} class AnotherClass { @@ -43,13 +46,9 @@ class AnotherClass { void someInstanceMethod() {} void pauseWithScopedVariablesMethod() { - // ignore: unused_local_variable, prefer_final_locals var foo = FooClass(); - // ignore: unused_local_variable, prefer_final_locals var foobar = 2; - // ignore: unused_local_variable, prefer_final_locals var baz = 3; - // ignore: unused_local_variable, prefer_final_locals var bar = 4; developer.debugger(); } @@ -68,7 +67,5 @@ set someTopLevelSetter(v) {} void someTopLevelMember() {} -// ignore: unused_element const _privateField1 = 1; -// ignore: unused_element const _privateField2 = 2; diff --git a/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete_export.dart b/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete_export.dart index 418ca27a67a..e6bcbed5bad 100644 --- a/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete_export.dart +++ b/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete_export.dart @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// This lint gets in the way of testing. +// ignore_for_file: unused_element + void somePublicExportedMethod() {} -// ignore: unused_element void _somePrivateExportedMethod() {} int exportedField = 3; -// ignore: unused_element int _privateExportedField = 10; class ExportedClass {} -// ignore: unused_element class _PrivateExportedClass {} diff --git a/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete_helper_library.dart b/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete_helper_library.dart index c9b825311fa..be9b4f87d2a 100644 --- a/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete_helper_library.dart +++ b/packages/devtools_app/test/test_infra/fixtures/flutter_app/lib/src/autocomplete_helper_library.dart @@ -4,10 +4,10 @@ export 'autocomplete_export.dart'; -// ignore: unused_element +// This lint gets in the way of testing autocomplete. +// ignore_for_file: unused_element int _privateFieldInOtherLibrary = 2; int publicFieldInOtherLibrary = 3; -// ignore: unused_element void _privateMethodOtherLibrary() {} void publicMethodOtherLibrary() {} diff --git a/packages/devtools_app/test/test_infra/fixtures/provider_app/lib/main.dart b/packages/devtools_app/test/test_infra/fixtures/provider_app/lib/main.dart index d75db52429d..1bac4f3fbd0 100644 --- a/packages/devtools_app/test/test_infra/fixtures/provider_app/lib/main.dart +++ b/packages/devtools_app/test/test_infra/fixtures/provider_app/lib/main.dart @@ -12,6 +12,9 @@ import 'mixin.dart'; // ignore: unused_import, allows the tests to use functions from tester.dart import 'tester.dart'; +// This lint gets in the way of testing the provider package. +// ignore_for_file: unnecessary_getters_setters + void main() { runApp(MyApp()); } @@ -38,7 +41,7 @@ class _MyAppState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text('Providers count ${1 + _providers.length}'), + Text('Providers count ${_providers.length + 1}'), Text(context.watch().count.toString()), ElevatedButton( key: const Key('increment'), @@ -67,7 +70,7 @@ class _MyAppState extends State { key: const Key('remove'), onPressed: () { setState(() { - _providers = List.from(_providers)..removeLast(); + _providers = List.of(_providers)..removeLast(); }); }, child: const Icon(Icons.remove), @@ -105,7 +108,7 @@ class ComplexObject { Null nill; bool boolean = false; int integer = 0; - double float = .42; + double float = 0.42; String string = 'hello world'; Object plainInstance = const _SubObject('hello world'); @@ -117,9 +120,7 @@ class ComplexObject { int get getter => 42; int _getterAndSetter = 0; - // ignore: unnecessary_getters_setters int get getterAndSetter => _getterAndSetter; - // ignore: unnecessary_getters_setters set getterAndSetter(int value) => _getterAndSetter = value; var map = { diff --git a/packages/devtools_app/test/test_infra/flutter_test_driver.dart b/packages/devtools_app/test/test_infra/flutter_test_driver.dart index 82750cfc333..0002b12552b 100644 --- a/packages/devtools_app/test/test_infra/flutter_test_driver.dart +++ b/packages/devtools_app/test/test_infra/flutter_test_driver.dart @@ -110,7 +110,7 @@ abstract class FlutterTestDriver { stderrController.stream.listen(_debugPrint); } - Future killGracefully() async { + Future killGracefully() { _debugPrint('Sending SIGTERM to $procPid..'); Process.killPid(procPid); return proc.exitCode.timeout(quitTimeout, onTimeout: _killForcefully); @@ -176,7 +176,7 @@ abstract class FlutterTestDriver { Future resume({String? step, bool wait = true}) async { _debugPrint('Sending resume ($step)'); - await _timeoutWithMessages( + await _timeoutWithMessages( () async => vmService!.resume(await getFlutterIsolateId(), step: step), message: 'Isolate did not respond to resume ($step)', ); @@ -193,7 +193,7 @@ abstract class FlutterTestDriver { Completer>(); late StreamSubscription sub; sub = stdoutController.stream.listen((String line) async { - final dynamic json = _parseFlutterResponse(line); + final json = _parseFlutterResponse(line); if (json == null) { return; } else if ((event != null && json['event'] == event) || @@ -207,11 +207,14 @@ abstract class FlutterTestDriver { error.write( '${event != null ? '$event event' : 'response to request $id.'}.\n\n', ); - if (json['params'] != null && json['params']['error'] != null) { - error.write('${json['params']['error']}\n\n'); - } - if (json['params'] != null && json['params']['trace'] != null) { - error.write('${json['params']['trace']}\n\n'); + final params = json['params']; + if (params != null && params is Map) { + if (params['error'] != null) { + error.write('${params['error']}\n\n'); + } + if (params['trace'] != null) { + error.write('${params['trace']}\n\n'); + } } response.completeError(error.toString()); } @@ -249,12 +252,12 @@ abstract class FlutterTestDriver { logMessage(''); throw '$message'; }, - ).catchError((dynamic error) { + ).catchError((Object? error) { throw '$error\nReceived:\n${messages.toString()}'; }).whenComplete(() => sub.cancel()); } - Map? _parseFlutterResponse(String line) { + Map? _parseFlutterResponse(String line) { if (line.startsWith('[') && line.endsWith(']')) { try { final Map? resp = json.decode(line)[0]; @@ -407,16 +410,17 @@ class FlutterRunTestDriver extends FlutterTestDriver { throw Exception('App has not started yet'); } - final dynamic hotReloadResp = await _sendRequest( + final hotReloadResp = await _sendRequest( 'app.restart', - { + { 'appId': _currentRunningAppId, 'fullRestart': fullRestart, 'pause': pause }, ); - if (hotReloadResp == null || hotReloadResp['code'] != 0) { + if (hotReloadResp == null || + (hotReloadResp as Map)['code'] != 0) { _throwErrorResponse( 'Hot ${fullRestart ? 'restart' : 'reload'} request failed', ); @@ -435,7 +439,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { proc.exitCode, _sendRequest( 'app.detach', - {'appId': _currentRunningAppId}, + {'appId': _currentRunningAppId}, ), ]).timeout( quitTimeout, @@ -461,7 +465,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { proc.exitCode, _sendRequest( 'app.stop', - {'appId': _currentRunningAppId}, + {'appId': _currentRunningAppId}, ), ]).timeout( quitTimeout, @@ -478,14 +482,14 @@ class FlutterRunTestDriver extends FlutterTestDriver { int id = 1; - Future _sendRequest(String method, dynamic params) async { + Future _sendRequest(String method, Object? params) async { final int requestId = id++; - final Map request = { + final request = { 'id': requestId, 'method': method, 'params': params }; - final String jsonEncoded = json.encode(>[request]); + final String jsonEncoded = json.encode(>[request]); _debugPrint(jsonEncoded); // Set up the response future before we send the request to avoid any diff --git a/packages/devtools_app/test/test_infra/flutter_test_environment.dart b/packages/devtools_app/test/test_infra/flutter_test_environment.dart index 079e3e95b7e..4b5b7006435 100644 --- a/packages/devtools_app/test/test_infra/flutter_test_environment.dart +++ b/packages/devtools_app/test/test_infra/flutter_test_environment.dart @@ -83,6 +83,8 @@ class FlutterTestEnvironment { bool _needsSetup = true; + Completer? _setupInProgress; + // Switch this flag to false to debug issues with non-atomic test behavior. bool reuseTestEnvironment = true; @@ -92,50 +94,60 @@ class FlutterTestEnvironment { bool force = false, FlutterRunConfiguration? config, }) async { + final setupInProgress = _setupInProgress; + if (setupInProgress != null && !setupInProgress.isCompleted) { + await setupInProgress.future; + } // Setting up the environment is slow so we reuse the existing environment // when possible. if (force || _needsSetup || !reuseTestEnvironment || _isNewRunConfig(config)) { - // If we already have a running test device, stop it before setting up a - // new one. - if (_flutter != null) await tearDownEnvironment(force: true); - - // Update the run configuration if we have a new one. - if (_isNewRunConfig(config)) _runConfig = config!; - - _needsSetup = false; - - _flutter = _flutterDriverFactory(Directory(testAppDirectory)) - as FlutterRunTestDriver?; - await _flutter!.run( - flutterExecutable: _flutterExe, - runConfig: _runConfig, - ); - - _service = _flutter!.vmService!; - - _preferencesController = PreferencesController(); - - setGlobal(IdeTheme, IdeTheme()); - setGlobal(Storage, FlutterDesktopStorage()); - setGlobal(ServiceConnectionManager, ServiceConnectionManager()); - setGlobal(PreferencesController, _preferencesController); - setGlobal(DevToolsExtensionPoints, ExternalDevToolsExtensionPoints()); - setGlobal(MessageBus, MessageBus()); - setGlobal(ScriptManager, ScriptManager()); - setGlobal(BreakpointManager, BreakpointManager()); - - // Clear out VM service calls from the test driver. - // ignore: invalid_use_of_visible_for_testing_member - _service.clearVmServiceCalls(); - - await serviceManager.vmServiceOpened( - _service, - onClosed: Completer().future, - ); - await _preferencesController!.init(); + _setupInProgress = Completer(); + try { + // If we already have a running test device, stop it before setting up a + // new one. + if (_flutter != null) await tearDownEnvironment(force: true); + + // Update the run configuration if we have a new one. + if (_isNewRunConfig(config)) _runConfig = config!; + + _flutter = _flutterDriverFactory(Directory(testAppDirectory)) + as FlutterRunTestDriver?; + await _flutter!.run( + flutterExecutable: _flutterExe, + runConfig: _runConfig, + ); + + _service = _flutter!.vmService!; + + final preferencesController = PreferencesController(); + _preferencesController = preferencesController; + + setGlobal(IdeTheme, IdeTheme()); + setGlobal(Storage, FlutterDesktopStorage()); + setGlobal(ServiceConnectionManager, ServiceConnectionManager()); + setGlobal(PreferencesController, preferencesController); + setGlobal(DevToolsExtensionPoints, ExternalDevToolsExtensionPoints()); + setGlobal(MessageBus, MessageBus()); + setGlobal(ScriptManager, ScriptManager()); + setGlobal(BreakpointManager, BreakpointManager()); + + // Clear out VM service calls from the test driver. + // ignore: invalid_use_of_visible_for_testing_member + _service.clearVmServiceCalls(); + + await serviceManager.vmServiceOpened( + _service, + onClosed: Completer().future, + ); + await _preferencesController!.init(); + + _needsSetup = false; + } finally { + _setupInProgress!.complete(!_needsSetup); + } if (_afterNewSetup != null) await _afterNewSetup!(); } diff --git a/packages/devtools_app/test/test_infra/matchers/matchers.dart b/packages/devtools_app/test/test_infra/matchers/matchers.dart index 4a91f91f8f5..0cb34218656 100644 --- a/packages/devtools_app/test/test_infra/matchers/matchers.dart +++ b/packages/devtools_app/test/test_infra/matchers/matchers.dart @@ -85,8 +85,8 @@ class _EqualsGoldenIgnoringHashCodes extends Matcher { } @override - bool matches(dynamic object, Map matchState) { - final String description = _normalize(object); + bool matches(Object? object, Map matchState) { + final String description = _normalize(object as String); if (_value != description) { if (updateGoldens) { io.File(path).writeAsStringSync(description); @@ -109,7 +109,7 @@ class _EqualsGoldenIgnoringHashCodes extends Matcher { @override Description describeMismatch( - dynamic item, + Object? item, Description mismatchDescription, Map matchState, bool verbose, @@ -136,7 +136,7 @@ class AlwaysTrueMatcher extends Matcher { const AlwaysTrueMatcher(); @override - bool matches(dynamic object, Map matchState) { + bool matches(Object? object, Map matchState) { return true; } diff --git a/packages/devtools_app/test/test_infra/scenes/memory/default.dart b/packages/devtools_app/test/test_infra/scenes/memory/default.dart index f12ff69896e..4ed5227eb9b 100644 --- a/packages/devtools_app/test/test_infra/scenes/memory/default.dart +++ b/packages/devtools_app/test/test_infra/scenes/memory/default.dart @@ -39,7 +39,6 @@ class MemoryDefaultScene extends Scene { @override Future setUp() async { - await ensureInspectorDependencies(); setGlobal(OfflineModeController, OfflineModeController()); setGlobal(IdeTheme, IdeTheme()); setGlobal(NotificationService, NotificationService()); diff --git a/packages/devtools_app/test/test_infra/scenes/performance/default.dart b/packages/devtools_app/test/test_infra/scenes/performance/default.dart index 8bc79024942..3db414028db 100644 --- a/packages/devtools_app/test/test_infra/scenes/performance/default.dart +++ b/packages/devtools_app/test/test_infra/scenes/performance/default.dart @@ -31,7 +31,6 @@ class PerformanceDefaultScene extends Scene { Future setUp() async { FeatureFlags.widgetRebuildstats = true; - await ensureInspectorDependencies(); setGlobal(OfflineModeController, OfflineModeController()); setGlobal(IdeTheme, IdeTheme()); setGlobal(NotificationService, NotificationService()); diff --git a/packages/devtools_app/test/test_infra/test_data/cpu_profile.dart b/packages/devtools_app/test/test_infra/test_data/cpu_profile.dart index 5be259b5f2d..1f40082697b 100644 --- a/packages/devtools_app/test/test_infra/test_data/cpu_profile.dart +++ b/packages/devtools_app/test/test_infra/test_data/cpu_profile.dart @@ -912,7 +912,7 @@ final filteredCpuSampleTraceEvents = [ 'tid': 42247, 'ts': 47377796685, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Foo', 'vmTag': 'Dart', }, @@ -925,7 +925,7 @@ final filteredCpuSampleTraceEvents = [ 'tid': 42247, 'ts': 47377797975, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Foo', 'vmTag': 'Dart', }, @@ -938,7 +938,7 @@ final filteredCpuSampleTraceEvents = [ 'tid': 42247, 'ts': 47377799063, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Foo', 'vmTag': 'Dart', }, @@ -951,7 +951,7 @@ final filteredCpuSampleTraceEvents = [ 'tid': 42247, 'ts': 47377800363, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -964,7 +964,7 @@ final filteredCpuSampleTraceEvents = [ 'tid': 42247, 'ts': 47377800463, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -977,7 +977,7 @@ final filteredCpuSampleTraceEvents = [ 'tid': 42247, 'ts': 47377800563, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -990,7 +990,7 @@ final filteredCpuSampleTraceEvents = [ 'tid': 42247, 'ts': 47377800663, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -1003,7 +1003,7 @@ final filteredCpuSampleTraceEvents = [ 'tid': 42247, 'ts': 47377800763, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -1021,7 +1021,7 @@ final List> goldenCpuProfileTraceEvents = 'tid': 42247, 'ts': 47377800363, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -1034,7 +1034,7 @@ final List> goldenCpuProfileTraceEvents = 'tid': 42247, 'ts': 47377800463, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -1047,7 +1047,7 @@ final List> goldenCpuProfileTraceEvents = 'tid': 42247, 'ts': 47377800563, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -1060,7 +1060,7 @@ final List> goldenCpuProfileTraceEvents = 'tid': 42247, 'ts': 47377800663, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -1073,7 +1073,7 @@ final List> goldenCpuProfileTraceEvents = 'tid': 42247, 'ts': 47377800763, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Default', 'vmTag': 'VM', }, @@ -1089,7 +1089,7 @@ final subProfileTraceEvents = [ 'tid': 42247, 'ts': 47377796685, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Foo', 'vmTag': 'Dart', }, @@ -1102,7 +1102,7 @@ final subProfileTraceEvents = [ 'tid': 42247, 'ts': 47377797975, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Foo', 'vmTag': 'Dart', }, @@ -1115,7 +1115,7 @@ final subProfileTraceEvents = [ 'tid': 42247, 'ts': 47377799063, 'cat': 'Dart', - 'args': { + 'args': { 'userTag': 'Foo', 'vmTag': 'Dart', }, @@ -1170,7 +1170,7 @@ final responseWithMissingLeafFrame = { 'tid': 42247, 'ts': 47377796685, 'cat': 'Dart', - 'args': {}, + 'args': {}, 'sf': '140357727781376-0' }, { @@ -1180,7 +1180,7 @@ final responseWithMissingLeafFrame = { 'tid': 42247, 'ts': 47377797975, 'cat': 'Dart', - 'args': {}, + 'args': {}, 'sf': '140357727781376-2' }, { @@ -1190,7 +1190,7 @@ final responseWithMissingLeafFrame = { 'tid': 42247, 'ts': 47377799063, 'cat': 'Dart', - 'args': {}, + 'args': {}, 'sf': '140357727781376-4' }, ] diff --git a/packages/devtools_app/test/test_infra/test_data/memory/leaks/leaking_demo_app.yaml b/packages/devtools_app/test/test_infra/test_data/memory/leaks/leaking_demo_app.yaml index 57012b75589..cb5111b3936 100644 --- a/packages/devtools_app/test/test_infra/test_data/memory/leaks/leaking_demo_app.yaml +++ b/packages/devtools_app/test/test_infra/test_data/memory/leaks/leaking_demo_app.yaml @@ -1,5 +1,5 @@ # For memory leaks troubleshooting tips see -# https://github.com/flutter/devtools/blob/master/packages/devtools_app/lib/src/screens/memory/panes/leaks/LEAK_TRACKING.md +# https://github.com/dart-lang/leak_tracker not-gced: total: 2 diff --git a/packages/devtools_app/test/test_infra/test_data/performance.dart b/packages/devtools_app/test/test_infra/test_data/performance.dart index e64b7cd9473..930bb17e19b 100644 --- a/packages/devtools_app/test/test_infra/test_data/performance.dart +++ b/packages/devtools_app/test/test_infra/test_data/performance.dart @@ -1327,7 +1327,7 @@ final unknownEventEndTrace = testTraceEventWrapper({ }); // Mark: OfflinePerformanceData. -final goldenTraceEventsJson = List>.from( +final goldenTraceEventsJson = List>.of( goldenUiTraceEvents.map((trace) => trace.json).toList() ..addAll(goldenRasterTraceEvents.map((trace) => trace.json).toList()), ); diff --git a/packages/devtools_app/test/test_infra/utils/rendering_tester.dart b/packages/devtools_app/test/test_infra/utils/rendering_tester.dart index 88a0b64c5ca..3609e008cb3 100644 --- a/packages/devtools_app/test/test_infra/utils/rendering_tester.dart +++ b/packages/devtools_app/test/test_infra/utils/rendering_tester.dart @@ -73,7 +73,7 @@ class TestRenderingFlutterBinding extends BindingBase /// The returned iterable takes errors lazily. If, for example, you iterate over 2 /// errors, but there are 5 errors total, this binding will still fail the test. /// Tests are expected to take and inspect all errors. - Iterable takeAllFlutterExceptions() sync* { + Iterable takeAllFlutterExceptions() sync* { // sync* and yield are used for lazy evaluation. Otherwise, the list would be // drained eagerly and allow a test pass with unexpected errors. while (_errors.isNotEmpty) { diff --git a/packages/devtools_app/test/test_infra/utils/test_utils.dart b/packages/devtools_app/test/test_infra/utils/test_utils.dart index e24df4b4cd1..8d061d734a3 100644 --- a/packages/devtools_app/test/test_infra/utils/test_utils.dart +++ b/packages/devtools_app/test/test_infra/utils/test_utils.dart @@ -38,9 +38,9 @@ void setupClipboardCopyListener({ clipboardContentsCallback(call.arguments['text']); break; case 'Clipboard.getData': - return Future.value({}); + return Future.value({}); case 'Clipboard.hasStrings': - return Future.value({'value': true}); + return Future.value({'value': true}); default: break; } diff --git a/packages/devtools_app/test/vm_developer/object_inspector/vm_code_display_test.dart b/packages/devtools_app/test/vm_developer/object_inspector/vm_code_display_test.dart index 009d8c26f55..2acb6a4a6d9 100644 --- a/packages/devtools_app/test/vm_developer/object_inspector/vm_code_display_test.dart +++ b/packages/devtools_app/test/vm_developer/object_inspector/vm_code_display_test.dart @@ -36,7 +36,7 @@ void main() { ); testCode.json = {}; final offset = pow(2, 20) as int; - testCode.disassembly = Disassembly.parse([ + testCode.disassembly = Disassembly.parse([ for (int i = 0; i < 1000; ++i) ...[ (i * 4 + offset).toRadixString(16), 'unknown', diff --git a/packages/devtools_app/test/vm_developer/vm_developer_test_utils.dart b/packages/devtools_app/test/vm_developer/vm_developer_test_utils.dart index 54303841bed..a9ff162667f 100644 --- a/packages/devtools_app/test/vm_developer/vm_developer_test_utils.dart +++ b/packages/devtools_app/test/vm_developer/vm_developer_test_utils.dart @@ -132,7 +132,7 @@ class TestInboundReferences extends InboundReferences { TestInboundReferences({required super.references}); @override - Map? get json => {}; + Map? get json => {}; } class TestObjectInspectorViewController extends ObjectInspectorViewController { diff --git a/packages/devtools_test/lib/src/mocks/fake_service_extension_manager.dart b/packages/devtools_test/lib/src/mocks/fake_service_extension_manager.dart index 07df7f27700..88b07a73e1c 100644 --- a/packages/devtools_test/lib/src/mocks/fake_service_extension_manager.dart +++ b/packages/devtools_test/lib/src/mocks/fake_service_extension_manager.dart @@ -80,7 +80,7 @@ class FakeServiceExtensionManager extends Fake ) async { final extension = serviceExtensionsAllowlist[name]; if (extension != null) { - final dynamic value = _getExtensionValueFromJson(name, valueFromJson); + final Object? value = _getExtensionValueFromJson(name, valueFromJson); final enabled = extension is ToggleableServiceExtensionDescription ? value == extension.enabledValue @@ -98,7 +98,7 @@ class FakeServiceExtensionManager extends Fake } } - dynamic _getExtensionValueFromJson(String name, String valueFromJson) { + Object? _getExtensionValueFromJson(String name, String valueFromJson) { final expectedValueType = serviceExtensionsAllowlist[name]!.values.first.runtimeType; switch (expectedValueType) { @@ -186,8 +186,9 @@ class FakeServiceExtensionManager extends Fake } } - Future callServiceExtension(String name, dynamic value) async { + Future callServiceExtension(String name, Object? value) { extensionValueOnDevice[name] = value; + return Future.value(); } @override @@ -205,7 +206,7 @@ class FakeServiceExtensionManager extends Fake Future setServiceExtensionState( String name, { required bool enabled, - required dynamic value, + required Object? value, bool callExtension = true, }) async { if (callExtension && _serviceExtensions.contains(name)) { diff --git a/packages/devtools_test/lib/src/mocks/fake_service_manager.dart b/packages/devtools_test/lib/src/mocks/fake_service_manager.dart index 27dc3192acc..75c3873b281 100644 --- a/packages/devtools_test/lib/src/mocks/fake_service_manager.dart +++ b/packages/devtools_test/lib/src/mocks/fake_service_manager.dart @@ -52,7 +52,6 @@ class FakeServiceManager extends Fake implements ServiceConnectionManager { HttpProfile? httpProfile, SamplesMemoryJson? memoryData, AllocationMemoryJson? allocationData, - CpuProfileData? cpuProfileData, CpuSamples? cpuSamples, CpuSamples? allocationSamples, Map? resolvedUriMap, diff --git a/packages/devtools_test/lib/src/mocks/fake_vm_service_wrapper.dart b/packages/devtools_test/lib/src/mocks/fake_vm_service_wrapper.dart index a00a3984117..8a116d51b15 100644 --- a/packages/devtools_test/lib/src/mocks/fake_vm_service_wrapper.dart +++ b/packages/devtools_test/lib/src/mocks/fake_vm_service_wrapper.dart @@ -77,7 +77,7 @@ class FakeVmServiceWrapper extends Fake implements VmServiceWrapper { late final Map? _reverseResolvedUriMap; final _gcEventStream = StreamController.broadcast(); - final _flags = { + final _flags = >{ 'flags': [ Flag( name: 'flag 1 name', @@ -107,6 +107,7 @@ class FakeVmServiceWrapper extends Fake implements VmServiceWrapper { ), ], }; + @override Future getCpuSamples( String isolateId, @@ -222,12 +223,16 @@ class FakeVmServiceWrapper extends Fake implements VmServiceWrapper { @override Future getIsolate(String isolateId) { return Future.value( - Isolate.parse({ - 'rootLib': LibraryRef.parse({ - 'name': 'fake_isolate_name', - 'uri': 'package:fake_uri_root/main.dart' - }) - }), + Isolate.parse( + { + 'rootLib': LibraryRef.parse( + { + 'name': 'fake_isolate_name', + 'uri': 'package:fake_uri_root/main.dart', + }, + ), + }, + ), ); } @@ -267,7 +272,7 @@ class FakeVmServiceWrapper extends Fake implements VmServiceWrapper { @override Future setFlag(String name, String value) { - final List flags = _flags['flags']; + final List flags = _flags['flags']!; final existingFlag = flags.firstWhereOrNull((f) => f?.name == name); if (existingFlag != null) { existingFlag.valueAsString = value; @@ -288,6 +293,8 @@ class FakeVmServiceWrapper extends Fake implements VmServiceWrapper { newValue: value, timestamp: 1, // 1 is arbitrary. ); + // This library is conceptually for testing even though it is in its own + // package to support code reuse. // ignore: invalid_use_of_visible_for_testing_member _vmFlagManager.handleVmEvent(fakeVmFlagUpdateEvent); return Future.value(Success()); @@ -297,7 +304,7 @@ class FakeVmServiceWrapper extends Fake implements VmServiceWrapper { Future getFlagList() => Future.value(FlagList.parse(_flags) ?? FlagList(flags: [])); - final _vmTimelineFlags = { + final _vmTimelineFlags = { 'type': 'TimelineFlags', 'recordedStreams': [], 'availableStreams': [], diff --git a/packages/devtools_test/lib/src/mocks/mocks.dart b/packages/devtools_test/lib/src/mocks/mocks.dart index e42e7e0df95..841cbc11442 100644 --- a/packages/devtools_test/lib/src/mocks/mocks.dart +++ b/packages/devtools_test/lib/src/mocks/mocks.dart @@ -162,6 +162,13 @@ class MockLoggingController extends Mock @override final selectedLog = ValueNotifier(null); + @override + List matchesForSearch( + String search, { + bool searchPreviousMatches = false, + }) => + []; + @override List data = []; } @@ -227,16 +234,6 @@ class MockProgramExplorerControllerLegacy extends Mock class MockVM extends Mock implements VM {} -Future ensureInspectorDependencies() async { - assert( - !kIsWeb, - 'Attempted to resolve a package path from web code.\n' - 'Package path resolution uses dart:io, which is not available in web.' - '\n' - "To fix this, mark the failing test as @TestOn('vm')", - ); -} - void mockWebVm(VM vm) { when(vm.targetCPU).thenReturn('Web'); when(vm.architectureBits).thenReturn(-1); diff --git a/packages/devtools_test/lib/src/utils.dart b/packages/devtools_test/lib/src/utils.dart index eff1c94d370..94f492aa925 100644 --- a/packages/devtools_test/lib/src/utils.dart +++ b/packages/devtools_test/lib/src/utils.dart @@ -32,7 +32,7 @@ final screenIds = [ /// /// Tests that `listener` has actually been invoked. Future addListenerScope({ - required dynamic listenable, + required Listenable listenable, required Function listener, required Function callback, }) async { @@ -89,7 +89,7 @@ TreemapNode generateTree(Map treeJson) { if (rawChildren != null) { // If not a leaf node, build all children then take the sum of the // children's sizes as its own size. - for (dynamic child in rawChildren) { + for (var child in rawChildren) { final childTreemapNode = generateTree(child); treemapNodeChildren.add(childTreemapNode); treemapNodeSize += childTreemapNode.byteSize; @@ -105,7 +105,7 @@ TreemapNode generateTree(Map treeJson) { ..addAllChildren(treemapNodeChildren); } -Finder findSubstring(Widget widget, String text) { +Finder findSubstring(String text) { return find.byWidgetPredicate((widget) { if (widget is Text) { if (widget.data != null) return widget.data!.contains(text);