Skip to content

Commit 4c73118

Browse files
committed
Fix a number more issues by enabling Dart code metrics.
1 parent be4031e commit 4c73118

File tree

189 files changed

+1251
-1017
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

189 files changed

+1251
-1017
lines changed

analysis_options.yaml

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
analyzer:
2-
#strong-mode:
3-
#implicit-casts: false # 367 issues
4-
#implicit-dynamic: false # 169 issues
52
#language:
63
#strict-inference: true # 34 issues
74
#strict-raw-types: true # 103 issues
@@ -144,3 +141,94 @@ linter:
144141
# - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
145142
- valid_regexps
146143
# - void_checks # not yet tested
144+
145+
dart_code_metrics:
146+
metrics:
147+
cyclomatic-complexity: 20
148+
number-of-parameters: 4
149+
maximum-nesting-level: 5
150+
metrics-exclude:
151+
- test/**
152+
rules:
153+
# - arguments-ordering Too strict
154+
- avoid-banned-imports
155+
- avoid-cascade-after-if-null
156+
- avoid-collection-methods-with-unrelated-types
157+
- avoid-duplicate-exports
158+
- avoid-dynamic
159+
# - avoid-global-state TODO(jacobr): bunch of false positives around boolean flags.
160+
# - avoid-ignoring-return-values
161+
# - avoid-late-keyword
162+
- avoid-missing-enum-constant-in-map
163+
- avoid-nested-conditional-expressions
164+
# - avoid-non-ascii-symbols TODO(jacobr): probably worth enabling.
165+
# - avoid-non-null-assertion
166+
# - avoid-passing-async-when-sync-expected TODO(jacobr): consider re-enabliing.
167+
- avoid-redundant-async
168+
- avoid-throw-in-catch-block
169+
170+
# - avoid-top-level-members-in-tests Doesn't seem to match our style.
171+
- avoid-unnecessary-type-assertions
172+
- avoid-unnecessary-type-casts
173+
- avoid-unrelated-type-assertions
174+
- avoid-unused-parameters
175+
- ban-name
176+
# - binary-expression-operand-order Some nice catches but too many false positives to enable.
177+
- double-literal-format
178+
# - format-comment TODO(jacobr): enable this one after fixing violations.
179+
# TODO(jacobr): enable member-ordering. This catches a bunch of real style
180+
# issues but would be alot of work to migrate.
181+
# - member-ordering
182+
# - newline-before-return TODO(jacobr): should be in the formatter if it was a rule to adopt.
183+
- no-boolean-literal-compare
184+
# - no-empty-block Too many false positives. However it does flag a bunch of code smells so possibly worth re-enabling.
185+
# This one seems interesting but has too many false positives. Gave it a try.
186+
# - no-equal-arguments:
187+
# ignored-parameters:
188+
# - height
189+
# - width
190+
# - double-literal-format
191+
# - defaultSortColumn
192+
# - left
193+
# - right
194+
# - top
195+
# - bottom
196+
# - bottomLeft
197+
# - topLeft
198+
# - enabledBorder
199+
- no-equal-then-else
200+
# - no-magic-number
201+
# - no-object-declaration Too difficult to use along with avoiding dynamic particular for JSON decoding logic.
202+
# - prefer-async-await TODO(jacobr): evaluate enabling.
203+
- prefer-commenting-analyzer-ignores
204+
# - prefer-conditional-expressions Too many false positives involving large conditional expressions.
205+
# - prefer-correct-identifier-length Too many false positives with fine names like i and id.
206+
# - prefer-correct-test-file-name TODO(jacobr): enable and fix violations.
207+
- prefer-correct-type-name
208+
# - prefer-enums-by-name Cannot able unless lint adds a special case for orElse
209+
# - prefer-first TODO(jacobr): enable as a follow up PR.
210+
# - prefer-immediate-return TODO(jacobr): enable as a follow up PR.
211+
- prefer-iterable-of
212+
- prefer-last
213+
# - prefer-match-file-name
214+
# TODO(jacobr): consider enabling or enabling to periodically audit.
215+
# This one has a lot of false positives but is also quite nice.
216+
- prefer-moving-to-variable:
217+
allowed-duplicated-chains: 3
218+
# - prefer-static-class
219+
# - prefer-trailing-comma This one suggests trailing commas in some places they don't need to be. Reasonable but a bit verbose.
220+
- tag-name
221+
- always-remove-listener
222+
# - avoid-border-all Micro-optimization to avoid a const constructor.
223+
# - avoid-returning-widgets This one is nice but has a lot of false positives.
224+
- avoid-shrink-wrap-in-lists
225+
- avoid-unnecessary-setstate
226+
- avoid-expanded-as-spacer
227+
- avoid-wrapping-in-padding
228+
- check-for-equals-in-render-object-setters
229+
- consistent-update-render-object
230+
# - prefer-const-border-radius TODO(jacobr): enable.
231+
- prefer-correct-edge-insets-constructor
232+
# - prefer-extracting-callbacks I'm not clear this is always a good idea. Seems like a workaround.
233+
# - prefer-single-widget-per-file
234+
- prefer-using-list-view

packages/devtools_app/analysis_options.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@ analyzer:
1010
# these files if you want to ensure code is not invalid except where
1111
# expected.
1212
- test/test_infra/test_data/syntax_highlighting/**
13+
14+
dart_code_metrics:
15+
metrics-exclude:
16+
- test/**
17+
- test/test_infra/test_data/**

packages/devtools_app/lib/src/app.dart

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -112,21 +112,21 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
112112
});
113113

114114
_isDarkThemeEnabled = preferences.darkModeTheme.value;
115-
preferences.darkModeTheme.addListener(() {
115+
addAutoDisposeListener(preferences.darkModeTheme, () {
116116
setState(() {
117117
_isDarkThemeEnabled = preferences.darkModeTheme.value;
118118
});
119119
});
120120

121121
_vmDeveloperModeEnabled = preferences.vmDeveloperModeEnabled.value;
122-
preferences.vmDeveloperModeEnabled.addListener(() {
122+
addAutoDisposeListener(preferences.vmDeveloperModeEnabled, () {
123123
setState(() {
124124
_vmDeveloperModeEnabled = preferences.vmDeveloperModeEnabled.value;
125125
});
126126
});
127127

128128
_denseModeEnabled = preferences.denseModeEnabled.value;
129-
preferences.denseModeEnabled.addListener(() {
129+
addAutoDisposeListener(preferences.denseModeEnabled, () {
130130
setState(() {
131131
_denseModeEnabled = preferences.denseModeEnabled.value;
132132
});
@@ -191,10 +191,10 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
191191
}
192192

193193
Widget _buildTabbedPage(
194-
BuildContext context,
194+
BuildContext _,
195195
String? page,
196196
Map<String, String?> params,
197-
DevToolsNavigationState? state,
197+
DevToolsNavigationState? __,
198198
) {
199199
final vmServiceUri = params['uri'];
200200

@@ -234,7 +234,8 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
234234
.where((p) => !hide.contains(p.screenId))
235235
.toList();
236236
if (screens.isEmpty) return child ?? const SizedBox.shrink();
237-
return _providedControllers(
237+
return MultiProvider(
238+
providers: _providedControllers(),
238239
child: DevToolsScaffold(
239240
embed: embed,
240241
ideTheme: ideTheme,
@@ -277,8 +278,8 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
277278
return DevToolsScaffold.withChild(
278279
key: UniqueKey(),
279280
ideTheme: ideTheme,
280-
child: _providedControllers(
281-
offline: true,
281+
child: MultiProvider(
282+
providers: _providedControllers(offline: true),
282283
child: SnapshotScreenBody(snapshotArgs, _screens),
283284
),
284285
);
@@ -292,7 +293,8 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
292293
ReportFeedbackButton(),
293294
OpenAboutAction(),
294295
],
295-
child: _providedControllers(
296+
child: MultiProvider(
297+
providers: _providedControllers(),
296298
child: const AppSizeBody(),
297299
),
298300
);
@@ -308,18 +310,13 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
308310

309311
List<Screen> _visibleScreens() => _screens.where(shouldShowScreen).toList();
310312

311-
Widget _providedControllers({required Widget child, bool offline = false}) {
312-
final _providers = widget.screens
313+
List<Provider> _providedControllers({bool offline = false}) {
314+
return widget.screens
313315
.where(
314316
(s) => s.providesController && (offline ? s.supportsOffline : true),
315317
)
316318
.map((s) => s.controllerProvider(routerDelegate))
317319
.toList();
318-
319-
return MultiProvider(
320-
providers: _providers,
321-
child: child,
322-
);
323320
}
324321

325322
@override
@@ -456,7 +453,7 @@ class OpenSettingsAction extends StatelessWidget {
456453
return DevToolsTooltip(
457454
message: 'Settings',
458455
child: InkWell(
459-
onTap: () async {
456+
onTap: () {
460457
unawaited(
461458
showDialog(
462459
context: context,
@@ -505,7 +502,8 @@ class SettingsDialog extends StatelessWidget {
505502
CheckboxSetting(
506503
label: const Text('Enable analytics'),
507504
listenable: analyticsController.analyticsEnabled,
508-
toggle: analyticsController.toggleAnalyticsEnabled,
505+
toggle: (enable) =>
506+
unawaited(analyticsController.toggleAnalyticsEnabled(enable)),
509507
gaItem: gac.analytics,
510508
),
511509
CheckboxSetting(
@@ -537,7 +535,7 @@ class CheckboxSetting extends StatelessWidget {
537535

538536
final ValueListenable<bool> listenable;
539537

540-
final Function(bool) toggle;
538+
final void Function(bool) toggle;
541539

542540
final String gaItem;
543541

packages/devtools_app/lib/src/framework/about_dialog.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class OpenAboutAction extends StatelessWidget {
140140
return DevToolsTooltip(
141141
message: 'About DevTools',
142142
child: InkWell(
143-
onTap: () async {
143+
onTap: () {
144144
unawaited(
145145
showDialog(
146146
context: context,

packages/devtools_app/lib/src/framework/app_error_handling.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import '../shared/config_specific/logger/logger.dart';
2121
/// application.
2222
void setupErrorHandling(Future Function() appStartCallback) {
2323
// First, run all our code in a new zone.
24-
return runZonedGuarded(() async {
24+
return runZonedGuarded(
25+
// ignore: avoid-passing-async-when-sync-expected this ignore should be fixed.
26+
() async {
2527
WidgetsFlutterBinding.ensureInitialized();
2628

2729
final FlutterExceptionHandler? oldHandler = FlutterError.onError;

packages/devtools_app/lib/src/framework/framework_core.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ import '../shared/primitives/utils.dart';
1919
import '../shared/scripts/script_manager.dart';
2020
import '../shared/survey.dart';
2121

22-
typedef ErrorReporter = void Function(String title, dynamic error);
22+
typedef ErrorReporter = void Function(String title, Object error);
2323

24+
// TODO(jacobr): refactor this class to not use static members.
2425
// ignore: avoid_classes_with_only_static_members
2526
class FrameworkCore {
2627
static void initGlobals() {

packages/devtools_app/lib/src/framework/landing_screen.dart

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -130,29 +130,9 @@ class _ConnectDialogState extends State<ConnectDialog>
130130

131131
@override
132132
Widget build(BuildContext context) {
133-
return LandingScreenSection(
134-
title: 'Connect',
135-
child: Column(
136-
crossAxisAlignment: CrossAxisAlignment.start,
137-
children: [
138-
Text(
139-
'Connect to a Running App',
140-
style: Theme.of(context).textTheme.titleMedium,
141-
),
142-
const SizedBox(height: denseRowSpacing),
143-
Text(
144-
'Enter a URL to a running Dart or Flutter application',
145-
style: Theme.of(context).textTheme.bodySmall,
146-
),
147-
const Padding(padding: EdgeInsets.only(top: 20.0)),
148-
_buildConnectInput(),
149-
],
150-
),
151-
);
152-
}
133+
final textTheme = Theme.of(context).textTheme;
153134

154-
Widget _buildConnectInput() {
155-
return Column(
135+
final connectorInput = Column(
156136
crossAxisAlignment: CrossAxisAlignment.stretch,
157137
children: [
158138
Row(
@@ -177,7 +157,7 @@ class _ConnectDialogState extends State<ConnectDialog>
177157
),
178158
const SizedBox(width: defaultSpacing),
179159
ElevatedButton(
180-
onPressed: actionInProgress ? null : _connect,
160+
onPressed: actionInProgress ? null : () => unawaited(_connect()),
181161
child: const Text('Connect'),
182162
),
183163
],
@@ -192,6 +172,26 @@ class _ConnectDialogState extends State<ConnectDialog>
192172
),
193173
],
194174
);
175+
176+
return LandingScreenSection(
177+
title: 'Connect',
178+
child: Column(
179+
crossAxisAlignment: CrossAxisAlignment.start,
180+
children: [
181+
Text(
182+
'Connect to a Running App',
183+
style: textTheme.titleMedium,
184+
),
185+
const SizedBox(height: denseRowSpacing),
186+
Text(
187+
'Enter a URL to a running Dart or Flutter application',
188+
style: textTheme.bodySmall,
189+
),
190+
const Padding(padding: EdgeInsets.only(top: 20.0)),
191+
connectorInput,
192+
],
193+
),
194+
);
195195
}
196196

197197
Future<void> _connect() async {
@@ -251,20 +251,21 @@ class ImportFileInstructions extends StatelessWidget {
251251

252252
@override
253253
Widget build(BuildContext context) {
254+
final textTheme = Theme.of(context).textTheme;
254255
return LandingScreenSection(
255256
title: 'Load DevTools Data',
256257
child: Column(
257258
crossAxisAlignment: CrossAxisAlignment.start,
258259
children: [
259260
Text(
260261
'Import a data file to use DevTools without an app connection.',
261-
style: Theme.of(context).textTheme.titleMedium,
262+
style: textTheme.titleMedium,
262263
),
263264
const SizedBox(height: denseRowSpacing),
264265
Text(
265266
'At this time, DevTools only supports importing files that were originally'
266267
' exported from DevTools.',
267-
style: Theme.of(context).textTheme.bodySmall,
268+
style: textTheme.bodySmall,
268269
),
269270
const SizedBox(height: defaultSpacing),
270271
ElevatedButton(
@@ -300,20 +301,21 @@ class AppSizeToolingInstructions extends StatelessWidget {
300301

301302
@override
302303
Widget build(BuildContext context) {
304+
final textTheme = Theme.of(context).textTheme;
303305
return LandingScreenSection(
304306
title: 'App Size Tooling',
305307
child: Column(
306308
crossAxisAlignment: CrossAxisAlignment.start,
307309
children: [
308310
Text(
309311
'Analyze and view diffs for your app\'s size',
310-
style: Theme.of(context).textTheme.titleMedium,
312+
style: textTheme.titleMedium,
311313
),
312314
const SizedBox(height: denseRowSpacing),
313315
Text(
314316
'Load Dart AOT snapshots or app size analysis files to '
315317
'track down size issues in your app.',
316-
style: Theme.of(context).textTheme.bodySmall,
318+
style: textTheme.bodySmall,
317319
),
318320
const SizedBox(height: defaultSpacing),
319321
ElevatedButton(

0 commit comments

Comments
 (0)