Enable strict-inference (#135043)

Avoids that dynamic accidentally sneaks in, see https://dart.dev/tools/analysis#enabling-additional-type-checks
This commit is contained in:
Michael Goderbauer 2023-09-20 12:59:08 -07:00 committed by GitHub
parent 96a4ae9dc5
commit b0a90aee17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 63 additions and 55 deletions

View file

@ -17,6 +17,7 @@
analyzer:
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
errors:
# allow self-reference to deprecated members (we do this because otherwise we have

View file

@ -11,7 +11,7 @@ library dart.ui;
///
/// ```dart
/// class MyStringBuffer {
/// error; // error (missing_const_final_var_or_type, always_specify_types)
/// error; // error (prefer_typing_uninitialized_variables, inference_failure_on_uninitialized_variable, missing_const_final_var_or_type)
///
/// StringBuffer _buffer = StringBuffer(); // error (prefer_final_fields, unused_field)
/// }

View file

@ -16,6 +16,6 @@ String? bar;
/// error: widgets library was not imported (not even implicitly).
/// ```dart
/// print(Widget);
/// print(Widget); // error (undefined_identifier)
/// ```
String? foo;

View file

@ -131,7 +131,7 @@
/// Widget build(BuildContext context) {
/// final String title;
/// return Opacity(
/// key: globalKey, // error (undefined_identifier, argument_type_not_assignable)
/// key: globalKey, // error (undefined_identifier)
/// opacity: _visible ? 1.0 : 0.0,
/// child: Text(title), // error (read_potentially_unassigned_final)
/// );
@ -144,13 +144,14 @@
/// ```
///
/// ```dart
/// import 'dart:io'; // error (unused_import)/// final Widget p = Placeholder(); // error (undefined_class, undefined_function)
/// import 'dart:io'; // error (unused_import)
/// final Widget p = Placeholder(); // error (undefined_class, undefined_function)
/// ```
///
/// ```dart
/// // (e.g. in a stateful widget)
/// void initState() { // error (must_call_super, annotate_overrides)
/// widget.toString(); // error (undefined_identifier, return_of_invalid_type)
/// widget.toString();
/// }
/// ```
///

View file

@ -21,16 +21,19 @@ const List<String> expectedMainErrors = <String>[
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:134:14: (top-level declaration) (undefined_identifier)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:136:21: (top-level declaration) (read_potentially_unassigned_final)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:147:12: (self-contained program) (unused_import)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:152:10: (stateful widget) (annotate_overrides)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:152:10: (stateful widget) (must_call_super)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:160:7: (top-level declaration) (undefined_identifier)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:164: Found "```" in code but it did not match RegExp: pattern=^ */// *```dart\$ flags= so something is wrong. Line was: "/// ```"',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:148:11: (self-contained program) (undefined_class)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:148:22: (self-contained program) (undefined_function)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:153:10: (stateful widget) (annotate_overrides)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:153:10: (stateful widget) (must_call_super)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:161:7: (top-level declaration) (undefined_identifier)',
'dev/bots/test/analyze-snippet-code-test-input/known_broken_documentation.dart:165: Found "```" in code but it did not match RegExp: pattern=^ */// *```dart\$ flags= so something is wrong. Line was: "/// ```"',
'dev/bots/test/analyze-snippet-code-test-input/short_but_still_broken.dart:9:12: (statement) (invalid_assignment)',
'dev/bots/test/analyze-snippet-code-test-input/short_but_still_broken.dart:18:4: Empty ```dart block in snippet code.',
];
const List<String> expectedUiErrors = <String>[
'dev/bots/test/analyze-snippet-code-test-dart-ui/ui.dart:14:7: (top-level declaration) (prefer_typing_uninitialized_variables)',
'dev/bots/test/analyze-snippet-code-test-dart-ui/ui.dart:14:7: (top-level declaration) (inference_failure_on_uninitialized_variable)',
'dev/bots/test/analyze-snippet-code-test-dart-ui/ui.dart:14:7: (top-level declaration) (missing_const_final_var_or_type)',
'dev/bots/test/analyze-snippet-code-test-dart-ui/ui.dart:16:20: (top-level declaration) (prefer_final_fields)',
'dev/bots/test/analyze-snippet-code-test-dart-ui/ui.dart:16:20: (top-level declaration) (unused_field)',
@ -69,7 +72,7 @@ void main() {
final List<String> stderrNoDescriptions = stderrLines.map(removeLintDescriptions).toList();
expect(stderrNoDescriptions, <String>[
...expectedMainErrors,
'Found 16 snippet code errors.',
'Found 18 snippet code errors.',
'See the documentation at the top of dev/bots/analyze_snippet_code.dart for details.',
'', // because we end with a newline, split gives us an extra blank line
]);
@ -93,7 +96,7 @@ void main() {
expect(stderrNoDescriptions, <String>[
...expectedUiErrors,
...expectedMainErrors,
'Found 20 snippet code errors.',
'Found 23 snippet code errors.',
'See the documentation at the top of dev/bots/analyze_snippet_code.dart for details.',
'', // because we end with a newline, split gives us an extra blank line
]);

View file

@ -170,7 +170,7 @@ void main() {
await expectLater(
() async {
final Future<void> rollFuture = autoroller.roll();
await controller.stream.drain();
await controller.stream.drain<Object?>();
await rollFuture;
},
throwsA(isA<Exception>().having(
@ -214,7 +214,7 @@ void main() {
], stdout: '[{"number": 123}]'),
]);
final Future<void> rollFuture = autoroller.roll();
await controller.stream.drain();
await controller.stream.drain<Object?>();
await rollFuture;
expect(processManager, hasNoRemainingExpectations);
expect(stdio.stdout, contains('flutter-pub-roller-bot already has open tool PRs'));
@ -312,7 +312,7 @@ void main() {
]),
]);
final Future<void> rollFuture = autoroller.roll();
await controller.stream.drain();
await controller.stream.drain<Object?>();
await rollFuture;
expect(processManager, hasNoRemainingExpectations);
});

View file

@ -16,7 +16,7 @@ const String _activityName = 'MainActivity';
const int _numberOfIterations = 10;
Future<void> _withApkInstall(
String apkPath, String bundleName, Function(AndroidDevice) body) async {
String apkPath, String bundleName, Future<void> Function(AndroidDevice) body) async {
final DeviceDiscovery devices = DeviceDiscovery();
final AndroidDevice device = await devices.workingDevice as AndroidDevice;
await device.unlock();

View file

@ -42,7 +42,7 @@ Future<void> runTasks(
List<String>? taskArgs,
bool useEmulator = false,
@visibleForTesting Map<String, String>? isolateParams,
@visibleForTesting Function(String) print = print,
@visibleForTesting void Function(String) print = print,
@visibleForTesting List<String>? logs,
}) async {
for (final String taskName in taskNames) {

View file

@ -201,7 +201,7 @@ class _ZOrderTestPageState extends State<ZOrderTestPage> {
)),
TextButton(
onPressed: () {
showDialog(
showDialog<void>(
context: context,
builder: (BuildContext context) {
return const SizedBox(

View file

@ -91,7 +91,7 @@ class _BottomNavigationBarExampleState extends State<BottomNavigationBarExample>
}
void showModal(BuildContext context) {
showDialog(
showDialog<void>(
context: context,
builder: (BuildContext context) => AlertDialog(
content: const Text('Example Dialog'),

View file

@ -174,7 +174,7 @@ class RootPage extends StatelessWidget {
ElevatedButton(
style: buttonStyle,
onPressed: () {
showDialog(
showDialog<void>(
context: context,
useRootNavigator: false,
builder: _buildDialog,
@ -186,9 +186,9 @@ class RootPage extends StatelessWidget {
ElevatedButton(
style: buttonStyle,
onPressed: () {
showDialog(
showDialog<void>(
context: context,
useRootNavigator: true,
useRootNavigator: true, // ignore: avoid_redundant_argument_values
builder: _buildDialog,
);
},
@ -200,7 +200,7 @@ class RootPage extends StatelessWidget {
return ElevatedButton(
style: buttonStyle,
onPressed: () {
showBottomSheet(
showBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(

View file

@ -136,7 +136,7 @@ class GridBuilder extends StatefulWidget {
});
final bool isSelectionMode;
final Function(bool)? onSelectionChange;
final ValueChanged<bool>? onSelectionChange;
final List<bool> selectedList;
@override
@ -189,7 +189,7 @@ class ListBuilder extends StatefulWidget {
final bool isSelectionMode;
final List<bool> selectedList;
final Function(bool)? onSelectionChange;
final ValueChanged<bool>? onSelectionChange;
@override
State<ListBuilder> createState() => _ListBuilderState();

View file

@ -111,7 +111,7 @@ mixin ToggleableStateMixin<S extends StatefulWidget> on TickerProviderStateMixin
/// build method - potentially after wrapping it in other widgets.
Widget buildToggleable({
FocusNode? focusNode,
Function(bool)? onFocusChange,
ValueChanged<bool>? onFocusChange,
bool autofocus = false,
required Size size,
required CustomPainter painter,

View file

@ -440,7 +440,7 @@ class _DragHandle extends StatelessWidget {
});
final VoidCallback? onSemanticsTap;
final Function(bool) handleHover;
final ValueChanged<bool> handleHover;
final Set<MaterialState> materialState;
final Color? dragHandleColor;
final Size? dragHandleSize;

View file

@ -710,7 +710,7 @@ class _MaterialSwitch extends StatefulWidget {
final MaterialStateProperty<Color?>? overlayColor;
final double? splashRadius;
final FocusNode? focusNode;
final Function(bool)? onFocusChange;
final ValueChanged<bool>? onFocusChange;
final bool autofocus;
final Size size;

View file

@ -302,7 +302,7 @@ mixin ToggleableStateMixin<S extends StatefulWidget> on TickerProviderStateMixin
/// build method - potentially after wrapping it in other widgets.
Widget buildToggleable({
FocusNode? focusNode,
Function(bool)? onFocusChange,
ValueChanged<bool>? onFocusChange,
bool autofocus = false,
required MaterialStateProperty<MouseCursor> mouseCursor,
required Size size,

View file

@ -5470,7 +5470,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
}
/// Gets first route entry satisfying the predicate, or null if not found.
_RouteEntry? _firstRouteEntryWhereOrNull<T>(_RouteEntryPredicate test) {
_RouteEntry? _firstRouteEntryWhereOrNull(_RouteEntryPredicate test) {
for (final _RouteEntry element in _history) {
if (test(element)) {
return element;
@ -5480,7 +5480,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
}
/// Gets last route entry satisfying the predicate, or null if not found.
_RouteEntry? _lastRouteEntryWhereOrNull<T>(_RouteEntryPredicate test) {
_RouteEntry? _lastRouteEntryWhereOrNull(_RouteEntryPredicate test) {
_RouteEntry? result;
for (final _RouteEntry element in _history) {
if (test(element)) {

View file

@ -3352,7 +3352,7 @@ void main() {
itemBuilder: (BuildContext context) => <PopupMenuItem<int>>[
PopupMenuItem<int>(
onTap: () {
showModalBottomSheet(
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return const SizedBox(

View file

@ -464,7 +464,7 @@ void main() {
});
test('ColorSwatch.lerp identical a,b', () {
expect(ColorSwatch.lerp(null, null, 0), null);
expect(ColorSwatch.lerp<Object?>(null, null, 0), null);
const ColorSwatch<int> color = ColorSwatch<int>(0x00000000, <int, Color>{1: Color(0x00000000)});
expect(identical(ColorSwatch.lerp(color, color, 0.5), color), true);
});

View file

@ -881,7 +881,7 @@ void main() {
});
// Simulate painting a RenderBox as if 'debugPaintSizeEnabled == true'
Function(PaintingContext, Offset) debugPaint(RenderBox renderBox) {
DebugPaintCallback debugPaint(RenderBox renderBox) {
layout(renderBox);
pumpFrame(phase: EnginePhase.compositingBits);
return (PaintingContext context, Offset offset) {
@ -891,7 +891,7 @@ void main() {
}
test('RenderClipPath.debugPaintSize draws a path and a debug text when clipBehavior is not Clip.none', () {
Function(PaintingContext, Offset) debugPaintClipRect(Clip clip) {
DebugPaintCallback debugPaintClipRect(Clip clip) {
final RenderBox child = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 200, height: 200));
final RenderClipPath renderClipPath = RenderClipPath(clipBehavior: clip, child: child);
return debugPaint(renderClipPath);
@ -908,7 +908,7 @@ void main() {
});
test('RenderClipRect.debugPaintSize draws a rect and a debug text when clipBehavior is not Clip.none', () {
Function(PaintingContext, Offset) debugPaintClipRect(Clip clip) {
DebugPaintCallback debugPaintClipRect(Clip clip) {
final RenderBox child = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 200, height: 200));
final RenderClipRect renderClipRect = RenderClipRect(clipBehavior: clip, child: child);
return debugPaint(renderClipRect);
@ -924,7 +924,7 @@ void main() {
});
test('RenderClipRRect.debugPaintSize draws a rounded rect and a debug text when clipBehavior is not Clip.none', () {
Function(PaintingContext, Offset) debugPaintClipRRect(Clip clip) {
DebugPaintCallback debugPaintClipRRect(Clip clip) {
final RenderBox child = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 200, height: 200));
final RenderClipRRect renderClipRRect = RenderClipRRect(clipBehavior: clip, child: child);
return debugPaint(renderClipRRect);
@ -940,7 +940,7 @@ void main() {
});
test('RenderClipOval.debugPaintSize draws a path and a debug text when clipBehavior is not Clip.none', () {
Function(PaintingContext, Offset) debugPaintClipOval(Clip clip) {
DebugPaintCallback debugPaintClipOval(Clip clip) {
final RenderBox child = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 200, height: 200));
final RenderClipOval renderClipOval = RenderClipOval(clipBehavior: clip, child: child);
return debugPaint(renderClipOval);
@ -1085,3 +1085,5 @@ void expectAssertionError() {
FlutterError.reportError(errorDetails);
}
}
typedef DebugPaintCallback = void Function(PaintingContext context, Offset offset);

View file

@ -11,7 +11,7 @@ import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class _MediaQueryAspectCase {
const _MediaQueryAspectCase(this.method, this.data);
final Function(BuildContext) method;
final void Function(BuildContext) method;
final MediaQueryData data;
}

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
@ -327,7 +328,7 @@ void main() {
testWidgets('Assertion error when SliverExpanded is used outside of SliverCrossAxisGroup', (WidgetTester tester) async {
final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
final Function(FlutterErrorDetails)? oldHandler = FlutterError.onError;
final FlutterExceptionHandler? oldHandler = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails error) => errors.add(error);
await tester.pumpWidget(
@ -459,7 +460,7 @@ void main() {
testWidgetsWithLeakTracking('Assertion error when constrained widget runs out of cross axis extent', (WidgetTester tester) async {
final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
final Function(FlutterErrorDetails)? oldHandler = FlutterError.onError;
final FlutterExceptionHandler? oldHandler = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails error) => errors.add(error);
final List<int> items = List<int>.generate(20, (int i) => i);
@ -481,7 +482,7 @@ void main() {
testWidgetsWithLeakTracking('Assertion error when expanded widget runs out of cross axis extent', (WidgetTester tester) async {
final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
final Function(FlutterErrorDetails)? oldHandler = FlutterError.onError;
final FlutterExceptionHandler? oldHandler = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails error) => errors.add(error);
final List<int> items = List<int>.generate(20, (int i) => i);

View file

@ -128,7 +128,7 @@ class _MockHttpClient implements HttpClient {
bool Function(X509Certificate cert, String host, int port)? badCertificateCallback;
@override
Function(String line)? keyLog;
void Function(String line)? keyLog;
@override
void close({ bool force = false }) { }

View file

@ -19,7 +19,7 @@ void verifyPropertyFaked<TProperty>({
required TProperty realValue,
required TProperty fakeValue,
required TProperty Function() propertyRetriever,
required Function(TestWidgetsFlutterBinding, TProperty fakeValue) propertyFaker,
required void Function(TestWidgetsFlutterBinding, TProperty fakeValue) propertyFaker,
Matcher Function(TProperty) matcher = equals,
}) {
TProperty propertyBeforeFaking;
@ -45,8 +45,8 @@ void verifyPropertyReset<TProperty>({
required WidgetTester tester,
required TProperty fakeValue,
required TProperty Function() propertyRetriever,
required Function() propertyResetter,
required Function(TProperty fakeValue) propertyFaker,
required VoidCallback propertyResetter,
required ValueSetter<TProperty> propertyFaker,
Matcher Function(TProperty) matcher = equals,
}) {
TProperty propertyBeforeFaking;

View file

@ -80,7 +80,7 @@ void main () {
expect(iosDeployDebugger.logLines, emits('Did finish launching.'));
expect(await iosDeployDebugger.launchAndAttach(), isTrue);
await iosDeployDebugger.logLines.drain();
await iosDeployDebugger.logLines.drain<Object?>();
expect(processManager, hasNoRemainingExpectations);
expect(appDeltaDirectory, exists);
});
@ -141,7 +141,7 @@ void main () {
'process detach',
]));
expect(await iosDeployDebugger.launchAndAttach(), isTrue);
await logLines.drain();
await logLines.drain<Object?>();
expect(logger.traceText, contains('PROCESS_STOPPED'));
expect(logger.traceText, contains('thread backtrace all'));
@ -189,7 +189,7 @@ void main () {
expect(iosDeployDebugger.logLines, emitsDone);
expect(await iosDeployDebugger.launchAndAttach(), isFalse);
await iosDeployDebugger.logLines.drain();
await iosDeployDebugger.logLines.drain<Object?>();
});
testWithoutContext('app exit', () async {
@ -209,7 +209,7 @@ void main () {
]));
expect(await iosDeployDebugger.launchAndAttach(), isTrue);
await iosDeployDebugger.logLines.drain();
await iosDeployDebugger.logLines.drain<Object?>();
});
testWithoutContext('app crash', () async {
@ -239,7 +239,7 @@ void main () {
]));
expect(await iosDeployDebugger.launchAndAttach(), isTrue);
await iosDeployDebugger.logLines.drain();
await iosDeployDebugger.logLines.drain<Object?>();
expect(logger.traceText, contains('Process 6156 stopped'));
expect(logger.traceText, contains('thread backtrace all'));
@ -263,7 +263,7 @@ void main () {
expect(iosDeployDebugger.logLines, emitsDone);
expect(await iosDeployDebugger.launchAndAttach(), isFalse);
await iosDeployDebugger.logLines.drain();
await iosDeployDebugger.logLines.drain<Object?>();
});
testWithoutContext('no provisioning profile 1, stdout', () async {
@ -364,7 +364,7 @@ void main () {
'Log on attach2',
]));
expect(await iosDeployDebugger.launchAndAttach(), isTrue);
await logLines.drain();
await logLines.drain<Object?>();
expect(LineSplitter.split(logger.traceText), containsOnce('Received logs from ios-deploy.'));
});

View file

@ -19,7 +19,7 @@ abstract class DapTestServer {
Future<void> stop();
StreamSink<List<int>> get sink;
Stream<List<int>> get stream;
Function(String message)? onStderrOutput;
void Function(String message)? onStderrOutput;
}
/// An instance of a DAP server running in-process (to aid debugging).
@ -83,7 +83,7 @@ class OutOfProcessDapTestServer extends DapTestServer {
.listen((String error) {
logger?.call(error);
if (!_isShuttingDown) {
final Function(String message)? stderrHandler = onStderrOutput;
final void Function(String message)? stderrHandler = onStderrOutput;
if (stderrHandler != null) {
stderrHandler(error);
} else {

View file

@ -147,7 +147,7 @@ class FakeHttpClient implements HttpClient {
bool Function(X509Certificate cert, String host, int port)? badCertificateCallback;
@override
Function(String line)? keyLog;
void Function(String line)? keyLog;
@override
void close({bool force = false}) { }