Ban sync*/async* from user facing code (#95050)
This commit is contained in:
parent
895beb04bb
commit
ab0a335973
@ -24,6 +24,7 @@ import 'utils.dart';
|
|||||||
final String flutterRoot = path.dirname(path.dirname(path.dirname(path.fromUri(Platform.script))));
|
final String flutterRoot = path.dirname(path.dirname(path.dirname(path.fromUri(Platform.script))));
|
||||||
final String flutter = path.join(flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
|
final String flutter = path.join(flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
|
||||||
final String flutterPackages = path.join(flutterRoot, 'packages');
|
final String flutterPackages = path.join(flutterRoot, 'packages');
|
||||||
|
final String flutterExamples = path.join(flutterRoot, 'examples');
|
||||||
final String dart = path.join(flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', Platform.isWindows ? 'dart.exe' : 'dart');
|
final String dart = path.join(flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', Platform.isWindows ? 'dart.exe' : 'dart');
|
||||||
final String pub = path.join(flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', Platform.isWindows ? 'pub.bat' : 'pub');
|
final String pub = path.join(flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', Platform.isWindows ? 'pub.bat' : 'pub');
|
||||||
final String pubCache = path.join(flutterRoot, '.pub-cache');
|
final String pubCache = path.join(flutterRoot, '.pub-cache');
|
||||||
@ -51,6 +52,10 @@ Future<void> run(List<String> arguments) async {
|
|||||||
exitWithError(<String>['The analyze.dart script must be run with --enable-asserts.']);
|
exitWithError(<String>['The analyze.dart script must be run with --enable-asserts.']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print('$clock No sync*/async*');
|
||||||
|
await verifyNoSyncAsyncStar(flutterPackages);
|
||||||
|
await verifyNoSyncAsyncStar(flutterExamples, minimumMatches: 200);
|
||||||
|
|
||||||
print('$clock No runtimeType in toString...');
|
print('$clock No runtimeType in toString...');
|
||||||
await verifyNoRuntimeTypeInToString(flutterRoot);
|
await verifyNoRuntimeTypeInToString(flutterRoot);
|
||||||
|
|
||||||
@ -153,6 +158,34 @@ Future<void> run(List<String> arguments) async {
|
|||||||
|
|
||||||
// TESTS
|
// TESTS
|
||||||
|
|
||||||
|
Future<void> verifyNoSyncAsyncStar(String workingDirectory, {int minimumMatches = 2000 }) async {
|
||||||
|
final RegExp syncPattern = RegExp(r'\s*?a?sync\*\s*?{');
|
||||||
|
const String ignorePattern = 'no_sync_async_star';
|
||||||
|
final RegExp commentPattern = RegExp(r'^\s*?///?');
|
||||||
|
final List<String> errors = <String>[];
|
||||||
|
await for (final File file in _allFiles(workingDirectory, 'dart', minimumMatches: minimumMatches)) {
|
||||||
|
if (file.path.contains('test')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final List<String> lines = file.readAsLinesSync();
|
||||||
|
for (int index = 0; index < lines.length; index += 1) {
|
||||||
|
final String line = lines[index];
|
||||||
|
if (line.startsWith(commentPattern)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.contains(syncPattern) && !line.contains(ignorePattern) && (index == 0 || !lines[index - 1].contains(ignorePattern))) {
|
||||||
|
errors.add('${file.path}:$index: sync*/async* without an ignore (no_sync_async_star).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errors.isNotEmpty) {
|
||||||
|
exitWithError(<String>[
|
||||||
|
'${bold}Do not use sync*/async* methods. See https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#avoid-syncasync for details.$reset',
|
||||||
|
...errors,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final RegExp _findGoldenTestPattern = RegExp(r'matchesGoldenFile\(');
|
final RegExp _findGoldenTestPattern = RegExp(r'matchesGoldenFile\(');
|
||||||
final RegExp _findGoldenDefinitionPattern = RegExp(r'matchesGoldenFile\(Object');
|
final RegExp _findGoldenDefinitionPattern = RegExp(r'matchesGoldenFile\(Object');
|
||||||
final RegExp _leadingComment = RegExp(r'\/\/');
|
final RegExp _leadingComment = RegExp(r'\/\/');
|
||||||
|
@ -430,6 +430,8 @@ Future<void> runForbiddenFromReleaseTests() async {
|
|||||||
'--snapshot', path.join(tempDirectory.path, 'snapshot.arm64-v8a.json'),
|
'--snapshot', path.join(tempDirectory.path, 'snapshot.arm64-v8a.json'),
|
||||||
'--package-config', path.join(flutterRoot, 'examples', 'hello_world', '.dart_tool', 'package_config.json'),
|
'--package-config', path.join(flutterRoot, 'examples', 'hello_world', '.dart_tool', 'package_config.json'),
|
||||||
'--forbidden-type', 'package:flutter/src/widgets/widget_inspector.dart::WidgetInspectorService',
|
'--forbidden-type', 'package:flutter/src/widgets/widget_inspector.dart::WidgetInspectorService',
|
||||||
|
'--forbidden-type', 'package:flutter/src/widgets/framework.dart::DebugCreator',
|
||||||
|
'--forbidden-type', 'package:flutter/src/foundation/print.dart::debugPrint',
|
||||||
];
|
];
|
||||||
await runCommand(
|
await runCommand(
|
||||||
dart,
|
dart,
|
||||||
|
@ -48,9 +48,9 @@ class CastListState extends State<CastList> {
|
|||||||
const Actor('James Madison', 'JM'),
|
const Actor('James Madison', 'JM'),
|
||||||
];
|
];
|
||||||
|
|
||||||
Iterable<Widget> get actorWidgets sync* {
|
Iterable<Widget> get actorWidgets {
|
||||||
for (final Actor actor in _cast) {
|
return _cast.map((Actor actor) {
|
||||||
yield Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(4.0),
|
padding: const EdgeInsets.all(4.0),
|
||||||
child: Chip(
|
child: Chip(
|
||||||
avatar: CircleAvatar(child: Text(actor.initials)),
|
avatar: CircleAvatar(child: Text(actor.initials)),
|
||||||
@ -64,7 +64,7 @@ class CastListState extends State<CastList> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -30,6 +30,7 @@ class MyStatefulWidget extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
|
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
|
||||||
|
// ignore: no_sync_async_star
|
||||||
final Stream<int> _bids = (() async* {
|
final Stream<int> _bids = (() async* {
|
||||||
await Future<void>.delayed(const Duration(seconds: 1));
|
await Future<void>.delayed(const Duration(seconds: 1));
|
||||||
yield 1;
|
yield 1;
|
||||||
|
@ -94,13 +94,13 @@ class RenderDiagonal extends RenderBox with SlottedContainerRenderObjectMixin<Di
|
|||||||
|
|
||||||
// Returns children in hit test order.
|
// Returns children in hit test order.
|
||||||
@override
|
@override
|
||||||
Iterable<RenderBox> get children sync* {
|
Iterable<RenderBox> get children {
|
||||||
if (_topLeft != null) {
|
return <RenderBox>[
|
||||||
yield _topLeft!;
|
if (_topLeft != null)
|
||||||
}
|
_topLeft!,
|
||||||
if (_bottomRight != null) {
|
if (_bottomRight != null)
|
||||||
yield _bottomRight!;
|
_bottomRight!,
|
||||||
}
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// LAYOUT
|
// LAYOUT
|
||||||
|
@ -141,13 +141,13 @@ mixin AnimationLocalListenersMixin {
|
|||||||
for (final VoidCallback listener in localListeners) {
|
for (final VoidCallback listener in localListeners) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<AnimationLocalListenersMixin>(
|
DiagnosticsProperty<AnimationLocalListenersMixin>(
|
||||||
'The $runtimeType notifying listeners was',
|
'The $runtimeType notifying listeners was',
|
||||||
this,
|
this,
|
||||||
style: DiagnosticsTreeStyle.errorProperty,
|
style: DiagnosticsTreeStyle.errorProperty,
|
||||||
);
|
),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
try {
|
try {
|
||||||
@ -234,13 +234,13 @@ mixin AnimationLocalStatusListenersMixin {
|
|||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<AnimationLocalStatusListenersMixin>(
|
DiagnosticsProperty<AnimationLocalStatusListenersMixin>(
|
||||||
'The $runtimeType notifying status listeners was',
|
'The $runtimeType notifying status listeners was',
|
||||||
this,
|
this,
|
||||||
style: DiagnosticsTreeStyle.errorProperty,
|
style: DiagnosticsTreeStyle.errorProperty,
|
||||||
);
|
),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
|
@ -487,10 +487,12 @@ class _CupertinoAppState extends State<CupertinoApp> {
|
|||||||
// of a particular LocalizationsDelegate.type is loaded so the
|
// of a particular LocalizationsDelegate.type is loaded so the
|
||||||
// localizationsDelegate parameter can be used to override
|
// localizationsDelegate parameter can be used to override
|
||||||
// _CupertinoLocalizationsDelegate.
|
// _CupertinoLocalizationsDelegate.
|
||||||
Iterable<LocalizationsDelegate<dynamic>> get _localizationsDelegates sync* {
|
Iterable<LocalizationsDelegate<dynamic>> get _localizationsDelegates {
|
||||||
if (widget.localizationsDelegates != null)
|
return <LocalizationsDelegate<dynamic>>[
|
||||||
yield* widget.localizationsDelegates!;
|
if (widget.localizationsDelegates != null)
|
||||||
yield DefaultCupertinoLocalizations.delegate;
|
...widget.localizationsDelegates!,
|
||||||
|
DefaultCupertinoLocalizations.delegate,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _inspectorSelectButtonBuilder(BuildContext context, VoidCallback onPressed) {
|
Widget _inspectorSelectButtonBuilder(BuildContext context, VoidCallback onPressed) {
|
||||||
|
@ -2050,16 +2050,18 @@ class _RenderCupertinoDialogActions extends RenderBox
|
|||||||
markNeedsPaint();
|
markNeedsPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<RenderBox> get _pressedButtons sync* {
|
Iterable<RenderBox> get _pressedButtons {
|
||||||
|
final List<RenderBox> boxes = <RenderBox>[];
|
||||||
RenderBox? currentChild = firstChild;
|
RenderBox? currentChild = firstChild;
|
||||||
while (currentChild != null) {
|
while (currentChild != null) {
|
||||||
assert(currentChild.parentData is _ActionButtonParentData);
|
assert(currentChild.parentData is _ActionButtonParentData);
|
||||||
final _ActionButtonParentData parentData = currentChild.parentData! as _ActionButtonParentData;
|
final _ActionButtonParentData parentData = currentChild.parentData! as _ActionButtonParentData;
|
||||||
if (parentData.isPressed) {
|
if (parentData.isPressed) {
|
||||||
yield currentChild;
|
boxes.add(currentChild);
|
||||||
}
|
}
|
||||||
currentChild = childAfter(currentChild);
|
currentChild = childAfter(currentChild);
|
||||||
}
|
}
|
||||||
|
return boxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get _isButtonPressed {
|
bool get _isButtonPressed {
|
||||||
|
@ -542,10 +542,10 @@ class FlutterErrorDetails with Diagnosticable {
|
|||||||
/// FlutterError.reportError(FlutterErrorDetails(
|
/// FlutterError.reportError(FlutterErrorDetails(
|
||||||
/// exception: error,
|
/// exception: error,
|
||||||
/// stack: stack,
|
/// stack: stack,
|
||||||
/// informationCollector: () sync* {
|
/// informationCollector: () => <DiagnosticsNode>[
|
||||||
/// yield ErrorDescription('This happened while climbing the space elevator.');
|
/// ErrorDescription('This happened while climbing the space elevator.'),
|
||||||
/// yield ErrorHint('The process ID is: $pid');
|
/// ErrorHint('The process ID is: $pid'),
|
||||||
/// },
|
/// ],
|
||||||
/// ));
|
/// ));
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
@ -113,7 +113,7 @@ class CachingIterable<E> extends IterableBase<E> {
|
|||||||
/// once. If you have an [Iterable], you can pass its [iterator]
|
/// once. If you have an [Iterable], you can pass its [iterator]
|
||||||
/// field as the argument to this constructor.
|
/// field as the argument to this constructor.
|
||||||
///
|
///
|
||||||
/// You can use a `sync*` function with this as follows:
|
/// You can this with an existing `sync*` function as follows:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// Iterable<int> range(int start, int end) sync* {
|
/// Iterable<int> range(int start, int end) sync* {
|
||||||
@ -125,6 +125,10 @@ class CachingIterable<E> extends IterableBase<E> {
|
|||||||
/// print(i.length); // walks the list
|
/// print(i.length); // walks the list
|
||||||
/// print(i.length); // efficient
|
/// print(i.length); // efficient
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// Beware that this will eagerly evaluate the `range` iterable, and because
|
||||||
|
/// of that it would be better to just implement `range` as something that
|
||||||
|
/// returns a `List` to begin with if possible.
|
||||||
CachingIterable(this._prefillIterator);
|
CachingIterable(this._prefillIterator);
|
||||||
|
|
||||||
final Iterator<E> _prefillIterator;
|
final Iterator<E> _prefillIterator;
|
||||||
|
@ -312,13 +312,13 @@ class ChangeNotifier implements Listenable {
|
|||||||
stack: stack,
|
stack: stack,
|
||||||
library: 'foundation library',
|
library: 'foundation library',
|
||||||
context: ErrorDescription('while dispatching notifications for $runtimeType'),
|
context: ErrorDescription('while dispatching notifications for $runtimeType'),
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<ChangeNotifier>(
|
DiagnosticsProperty<ChangeNotifier>(
|
||||||
'The $runtimeType sending notification was',
|
'The $runtimeType sending notification was',
|
||||||
this,
|
this,
|
||||||
style: DiagnosticsTreeStyle.errorProperty,
|
style: DiagnosticsTreeStyle.errorProperty,
|
||||||
);
|
),
|
||||||
},
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -870,12 +870,12 @@ class _PrefixedStringBuilder {
|
|||||||
///
|
///
|
||||||
/// This method wraps a sequence of text where only some spans of text can be
|
/// This method wraps a sequence of text where only some spans of text can be
|
||||||
/// used as wrap boundaries.
|
/// used as wrap boundaries.
|
||||||
static Iterable<String> _wordWrapLine(String message, List<int> wrapRanges, int width, { int startOffset = 0, int otherLineOffset = 0}) sync* {
|
static Iterable<String> _wordWrapLine(String message, List<int> wrapRanges, int width, { int startOffset = 0, int otherLineOffset = 0}) {
|
||||||
if (message.length + startOffset < width) {
|
if (message.length + startOffset < width) {
|
||||||
// Nothing to do. The line doesn't wrap.
|
// Nothing to do. The line doesn't wrap.
|
||||||
yield message;
|
return <String>[message];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
final List<String> wrappedLine = <String>[];
|
||||||
int startForLengthCalculations = -startOffset;
|
int startForLengthCalculations = -startOffset;
|
||||||
bool addPrefix = false;
|
bool addPrefix = false;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
@ -920,10 +920,10 @@ class _PrefixedStringBuilder {
|
|||||||
lastWordEnd = index;
|
lastWordEnd = index;
|
||||||
}
|
}
|
||||||
final String line = message.substring(start, lastWordEnd);
|
final String line = message.substring(start, lastWordEnd);
|
||||||
yield line;
|
wrappedLine.add(line);
|
||||||
addPrefix = true;
|
addPrefix = true;
|
||||||
if (lastWordEnd >= message.length)
|
if (lastWordEnd >= message.length)
|
||||||
return;
|
return wrappedLine;
|
||||||
// just yielded a line
|
// just yielded a line
|
||||||
if (lastWordEnd == index) {
|
if (lastWordEnd == index) {
|
||||||
// we broke at current position
|
// we broke at current position
|
||||||
@ -2590,12 +2590,10 @@ class FlagsSummary<T> extends DiagnosticsProperty<Map<String, T?>> {
|
|||||||
//
|
//
|
||||||
// For a null value, it is omitted unless `includeEmpty` is true and
|
// For a null value, it is omitted unless `includeEmpty` is true and
|
||||||
// [ifEntryNull] contains a corresponding description.
|
// [ifEntryNull] contains a corresponding description.
|
||||||
Iterable<String> _formattedValues() sync* {
|
Iterable<String> _formattedValues() {
|
||||||
for (final MapEntry<String, T?> entry in value.entries) {
|
return value.entries
|
||||||
if (entry.value != null) {
|
.where((MapEntry<String, T?> entry) => entry.value != null)
|
||||||
yield entry.key;
|
.map((MapEntry<String, T?> entry) => entry.key);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ class LicenseEntryWithLineBreaks extends LicenseEntry {
|
|||||||
final String text;
|
final String text;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<LicenseParagraph> get paragraphs sync* {
|
Iterable<LicenseParagraph> get paragraphs {
|
||||||
int lineStart = 0;
|
int lineStart = 0;
|
||||||
int currentPosition = 0;
|
int currentPosition = 0;
|
||||||
int lastLineIndent = 0;
|
int lastLineIndent = 0;
|
||||||
@ -147,6 +147,7 @@ class LicenseEntryWithLineBreaks extends LicenseEntry {
|
|||||||
int? currentParagraphIndentation;
|
int? currentParagraphIndentation;
|
||||||
_LicenseEntryWithLineBreaksParserState state = _LicenseEntryWithLineBreaksParserState.beforeParagraph;
|
_LicenseEntryWithLineBreaksParserState state = _LicenseEntryWithLineBreaksParserState.beforeParagraph;
|
||||||
final List<String> lines = <String>[];
|
final List<String> lines = <String>[];
|
||||||
|
final List<LicenseParagraph> result = <LicenseParagraph>[];
|
||||||
|
|
||||||
void addLine() {
|
void addLine() {
|
||||||
assert(lineStart < currentPosition);
|
assert(lineStart < currentPosition);
|
||||||
@ -182,7 +183,7 @@ class LicenseEntryWithLineBreaks extends LicenseEntry {
|
|||||||
case '\n':
|
case '\n':
|
||||||
case '\f':
|
case '\f':
|
||||||
if (lines.isNotEmpty) {
|
if (lines.isNotEmpty) {
|
||||||
yield getParagraph();
|
result.add(getParagraph());
|
||||||
}
|
}
|
||||||
if (text[currentPosition] == '\r' && currentPosition < text.length - 1
|
if (text[currentPosition] == '\r' && currentPosition < text.length - 1
|
||||||
&& text[currentPosition + 1] == '\n') {
|
&& text[currentPosition + 1] == '\n') {
|
||||||
@ -206,7 +207,7 @@ class LicenseEntryWithLineBreaks extends LicenseEntry {
|
|||||||
startParagraph:
|
startParagraph:
|
||||||
default:
|
default:
|
||||||
if (lines.isNotEmpty && currentLineIndent > lastLineIndent) {
|
if (lines.isNotEmpty && currentLineIndent > lastLineIndent) {
|
||||||
yield getParagraph();
|
result.add(getParagraph());
|
||||||
currentParagraphIndentation = null;
|
currentParagraphIndentation = null;
|
||||||
}
|
}
|
||||||
// The following is a wild heuristic for guessing the indentation level.
|
// The following is a wild heuristic for guessing the indentation level.
|
||||||
@ -231,7 +232,7 @@ class LicenseEntryWithLineBreaks extends LicenseEntry {
|
|||||||
break;
|
break;
|
||||||
case '\f':
|
case '\f':
|
||||||
addLine();
|
addLine();
|
||||||
yield getParagraph();
|
result.add(getParagraph());
|
||||||
lastLineIndent = 0;
|
lastLineIndent = 0;
|
||||||
currentLineIndent = 0;
|
currentLineIndent = 0;
|
||||||
currentParagraphIndentation = null;
|
currentParagraphIndentation = null;
|
||||||
@ -248,14 +249,15 @@ class LicenseEntryWithLineBreaks extends LicenseEntry {
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case _LicenseEntryWithLineBreaksParserState.beforeParagraph:
|
case _LicenseEntryWithLineBreaksParserState.beforeParagraph:
|
||||||
if (lines.isNotEmpty) {
|
if (lines.isNotEmpty) {
|
||||||
yield getParagraph();
|
result.add(getParagraph());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case _LicenseEntryWithLineBreaksParserState.inParagraph:
|
case _LicenseEntryWithLineBreaksParserState.inParagraph:
|
||||||
addLine();
|
addLine();
|
||||||
yield getParagraph();
|
result.add(getParagraph());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,6 +309,9 @@ class LicenseRegistry {
|
|||||||
/// Returns the licenses that have been registered.
|
/// Returns the licenses that have been registered.
|
||||||
///
|
///
|
||||||
/// Generating the list of licenses is expensive.
|
/// Generating the list of licenses is expensive.
|
||||||
|
// TODO(dnfield): Refactor the license logic.
|
||||||
|
// https://github.com/flutter/flutter/issues/95043
|
||||||
|
// flutter_ignore: no_sync_async_star
|
||||||
static Stream<LicenseEntry> get licenses async* {
|
static Stream<LicenseEntry> get licenses async* {
|
||||||
if (_collectors == null)
|
if (_collectors == null)
|
||||||
return;
|
return;
|
||||||
|
@ -113,11 +113,11 @@ enum _WordWrapParseMode { inSpace, inWord, atBreak }
|
|||||||
/// and so forth. It is only intended for formatting error messages.
|
/// and so forth. It is only intended for formatting error messages.
|
||||||
///
|
///
|
||||||
/// The default [debugPrint] implementation uses this for its line wrapping.
|
/// The default [debugPrint] implementation uses this for its line wrapping.
|
||||||
Iterable<String> debugWordWrap(String message, int width, { String wrapIndent = '' }) sync* {
|
Iterable<String> debugWordWrap(String message, int width, { String wrapIndent = '' }) {
|
||||||
if (message.length < width || message.trimLeft()[0] == '#') {
|
if (message.length < width || message.trimLeft()[0] == '#') {
|
||||||
yield message;
|
return <String>[message];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
final List<String> wrapped = <String>[];
|
||||||
final Match prefixMatch = _indentPattern.matchAsPrefix(message)!;
|
final Match prefixMatch = _indentPattern.matchAsPrefix(message)!;
|
||||||
final String prefix = wrapIndent + ' ' * prefixMatch.group(0)!.length;
|
final String prefix = wrapIndent + ' ' * prefixMatch.group(0)!.length;
|
||||||
int start = 0;
|
int start = 0;
|
||||||
@ -149,13 +149,13 @@ Iterable<String> debugWordWrap(String message, int width, { String wrapIndent =
|
|||||||
lastWordEnd = index;
|
lastWordEnd = index;
|
||||||
}
|
}
|
||||||
if (addPrefix) {
|
if (addPrefix) {
|
||||||
yield prefix + message.substring(start, lastWordEnd);
|
wrapped.add(prefix + message.substring(start, lastWordEnd));
|
||||||
} else {
|
} else {
|
||||||
yield message.substring(start, lastWordEnd);
|
wrapped.add(message.substring(start, lastWordEnd));
|
||||||
addPrefix = true;
|
addPrefix = true;
|
||||||
}
|
}
|
||||||
if (lastWordEnd >= message.length)
|
if (lastWordEnd >= message.length)
|
||||||
return;
|
return wrapped;
|
||||||
// just yielded a line
|
// just yielded a line
|
||||||
if (lastWordEnd == index) {
|
if (lastWordEnd == index) {
|
||||||
// we broke at current position
|
// we broke at current position
|
||||||
|
@ -407,9 +407,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
|||||||
library: 'gesture library',
|
library: 'gesture library',
|
||||||
context: ErrorDescription('while dispatching a non-hit-tested pointer event'),
|
context: ErrorDescription('while dispatching a non-hit-tested pointer event'),
|
||||||
event: event,
|
event: event,
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<PointerEvent>('Event', event, style: DiagnosticsTreeStyle.errorProperty);
|
DiagnosticsProperty<PointerEvent>('Event', event, style: DiagnosticsTreeStyle.errorProperty),
|
||||||
},
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -425,10 +425,10 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
|||||||
context: ErrorDescription('while dispatching a pointer event'),
|
context: ErrorDescription('while dispatching a pointer event'),
|
||||||
event: event,
|
event: event,
|
||||||
hitTestEntry: entry,
|
hitTestEntry: entry,
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<PointerEvent>('Event', event, style: DiagnosticsTreeStyle.errorProperty);
|
DiagnosticsProperty<PointerEvent>('Event', event, style: DiagnosticsTreeStyle.errorProperty),
|
||||||
yield DiagnosticsProperty<HitTestTarget>('Target', entry.target, style: DiagnosticsTreeStyle.errorProperty);
|
DiagnosticsProperty<HitTestTarget>('Target', entry.target, style: DiagnosticsTreeStyle.errorProperty),
|
||||||
},
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,197 +44,188 @@ class PointerEventConverter {
|
|||||||
/// [dart:ui.FlutterView.devicePixelRatio]) is used to convert the incoming data
|
/// [dart:ui.FlutterView.devicePixelRatio]) is used to convert the incoming data
|
||||||
/// from physical coordinates to logical pixels. See the discussion at
|
/// from physical coordinates to logical pixels. See the discussion at
|
||||||
/// [PointerEvent] for more details on the [PointerEvent] coordinate space.
|
/// [PointerEvent] for more details on the [PointerEvent] coordinate space.
|
||||||
static Iterable<PointerEvent> expand(Iterable<ui.PointerData> data, double devicePixelRatio) sync* {
|
static Iterable<PointerEvent> expand(Iterable<ui.PointerData> data, double devicePixelRatio) {
|
||||||
for (final ui.PointerData datum in data) {
|
return data
|
||||||
final Offset position = Offset(datum.physicalX, datum.physicalY) / devicePixelRatio;
|
.where((ui.PointerData datum) => datum.signalKind != ui.PointerSignalKind.unknown)
|
||||||
assert(position != null);
|
.map((ui.PointerData datum) {
|
||||||
final Offset delta = Offset(datum.physicalDeltaX, datum.physicalDeltaY) / devicePixelRatio;
|
final Offset position = Offset(datum.physicalX, datum.physicalY) / devicePixelRatio;
|
||||||
final double radiusMinor = _toLogicalPixels(datum.radiusMinor, devicePixelRatio);
|
assert(position != null);
|
||||||
final double radiusMajor = _toLogicalPixels(datum.radiusMajor, devicePixelRatio);
|
final Offset delta = Offset(datum.physicalDeltaX, datum.physicalDeltaY) / devicePixelRatio;
|
||||||
final double radiusMin = _toLogicalPixels(datum.radiusMin, devicePixelRatio);
|
final double radiusMinor = _toLogicalPixels(datum.radiusMinor, devicePixelRatio);
|
||||||
final double radiusMax = _toLogicalPixels(datum.radiusMax, devicePixelRatio);
|
final double radiusMajor = _toLogicalPixels(datum.radiusMajor, devicePixelRatio);
|
||||||
final Duration timeStamp = datum.timeStamp;
|
final double radiusMin = _toLogicalPixels(datum.radiusMin, devicePixelRatio);
|
||||||
final PointerDeviceKind kind = datum.kind;
|
final double radiusMax = _toLogicalPixels(datum.radiusMax, devicePixelRatio);
|
||||||
assert(datum.change != null);
|
final Duration timeStamp = datum.timeStamp;
|
||||||
if (datum.signalKind == null || datum.signalKind == ui.PointerSignalKind.none) {
|
final PointerDeviceKind kind = datum.kind;
|
||||||
switch (datum.change) {
|
assert(datum.change != null);
|
||||||
case ui.PointerChange.add:
|
switch (datum.signalKind ?? ui.PointerSignalKind.none) {
|
||||||
yield PointerAddedEvent(
|
case ui.PointerSignalKind.none:
|
||||||
timeStamp: timeStamp,
|
switch (datum.change) {
|
||||||
kind: kind,
|
case ui.PointerChange.add:
|
||||||
device: datum.device,
|
return PointerAddedEvent(
|
||||||
position: position,
|
timeStamp: timeStamp,
|
||||||
obscured: datum.obscured,
|
kind: kind,
|
||||||
pressureMin: datum.pressureMin,
|
device: datum.device,
|
||||||
pressureMax: datum.pressureMax,
|
position: position,
|
||||||
distance: datum.distance,
|
obscured: datum.obscured,
|
||||||
distanceMax: datum.distanceMax,
|
pressureMin: datum.pressureMin,
|
||||||
radiusMin: radiusMin,
|
pressureMax: datum.pressureMax,
|
||||||
radiusMax: radiusMax,
|
distance: datum.distance,
|
||||||
orientation: datum.orientation,
|
distanceMax: datum.distanceMax,
|
||||||
tilt: datum.tilt,
|
radiusMin: radiusMin,
|
||||||
embedderId: datum.embedderId,
|
radiusMax: radiusMax,
|
||||||
);
|
orientation: datum.orientation,
|
||||||
break;
|
tilt: datum.tilt,
|
||||||
case ui.PointerChange.hover:
|
embedderId: datum.embedderId,
|
||||||
yield PointerHoverEvent(
|
);
|
||||||
timeStamp: timeStamp,
|
case ui.PointerChange.hover:
|
||||||
kind: kind,
|
return PointerHoverEvent(
|
||||||
device: datum.device,
|
timeStamp: timeStamp,
|
||||||
position: position,
|
kind: kind,
|
||||||
delta: delta,
|
device: datum.device,
|
||||||
buttons: datum.buttons,
|
position: position,
|
||||||
obscured: datum.obscured,
|
delta: delta,
|
||||||
pressureMin: datum.pressureMin,
|
buttons: datum.buttons,
|
||||||
pressureMax: datum.pressureMax,
|
obscured: datum.obscured,
|
||||||
distance: datum.distance,
|
pressureMin: datum.pressureMin,
|
||||||
distanceMax: datum.distanceMax,
|
pressureMax: datum.pressureMax,
|
||||||
size: datum.size,
|
distance: datum.distance,
|
||||||
radiusMajor: radiusMajor,
|
distanceMax: datum.distanceMax,
|
||||||
radiusMinor: radiusMinor,
|
size: datum.size,
|
||||||
radiusMin: radiusMin,
|
radiusMajor: radiusMajor,
|
||||||
radiusMax: radiusMax,
|
radiusMinor: radiusMinor,
|
||||||
orientation: datum.orientation,
|
radiusMin: radiusMin,
|
||||||
tilt: datum.tilt,
|
radiusMax: radiusMax,
|
||||||
synthesized: datum.synthesized,
|
orientation: datum.orientation,
|
||||||
embedderId: datum.embedderId,
|
tilt: datum.tilt,
|
||||||
);
|
synthesized: datum.synthesized,
|
||||||
break;
|
embedderId: datum.embedderId,
|
||||||
case ui.PointerChange.down:
|
);
|
||||||
yield PointerDownEvent(
|
case ui.PointerChange.down:
|
||||||
timeStamp: timeStamp,
|
return PointerDownEvent(
|
||||||
pointer: datum.pointerIdentifier,
|
timeStamp: timeStamp,
|
||||||
kind: kind,
|
pointer: datum.pointerIdentifier,
|
||||||
device: datum.device,
|
kind: kind,
|
||||||
position: position,
|
device: datum.device,
|
||||||
buttons: _synthesiseDownButtons(datum.buttons, kind),
|
position: position,
|
||||||
obscured: datum.obscured,
|
buttons: _synthesiseDownButtons(datum.buttons, kind),
|
||||||
pressure: datum.pressure,
|
obscured: datum.obscured,
|
||||||
pressureMin: datum.pressureMin,
|
pressure: datum.pressure,
|
||||||
pressureMax: datum.pressureMax,
|
pressureMin: datum.pressureMin,
|
||||||
distanceMax: datum.distanceMax,
|
pressureMax: datum.pressureMax,
|
||||||
size: datum.size,
|
distanceMax: datum.distanceMax,
|
||||||
radiusMajor: radiusMajor,
|
size: datum.size,
|
||||||
radiusMinor: radiusMinor,
|
radiusMajor: radiusMajor,
|
||||||
radiusMin: radiusMin,
|
radiusMinor: radiusMinor,
|
||||||
radiusMax: radiusMax,
|
radiusMin: radiusMin,
|
||||||
orientation: datum.orientation,
|
radiusMax: radiusMax,
|
||||||
tilt: datum.tilt,
|
orientation: datum.orientation,
|
||||||
embedderId: datum.embedderId,
|
tilt: datum.tilt,
|
||||||
);
|
embedderId: datum.embedderId,
|
||||||
break;
|
);
|
||||||
case ui.PointerChange.move:
|
case ui.PointerChange.move:
|
||||||
yield PointerMoveEvent(
|
return PointerMoveEvent(
|
||||||
timeStamp: timeStamp,
|
timeStamp: timeStamp,
|
||||||
pointer: datum.pointerIdentifier,
|
pointer: datum.pointerIdentifier,
|
||||||
kind: kind,
|
kind: kind,
|
||||||
device: datum.device,
|
device: datum.device,
|
||||||
position: position,
|
position: position,
|
||||||
delta: delta,
|
delta: delta,
|
||||||
buttons: _synthesiseDownButtons(datum.buttons, kind),
|
buttons: _synthesiseDownButtons(datum.buttons, kind),
|
||||||
obscured: datum.obscured,
|
obscured: datum.obscured,
|
||||||
pressure: datum.pressure,
|
pressure: datum.pressure,
|
||||||
pressureMin: datum.pressureMin,
|
pressureMin: datum.pressureMin,
|
||||||
pressureMax: datum.pressureMax,
|
pressureMax: datum.pressureMax,
|
||||||
distanceMax: datum.distanceMax,
|
distanceMax: datum.distanceMax,
|
||||||
size: datum.size,
|
size: datum.size,
|
||||||
radiusMajor: radiusMajor,
|
radiusMajor: radiusMajor,
|
||||||
radiusMinor: radiusMinor,
|
radiusMinor: radiusMinor,
|
||||||
radiusMin: radiusMin,
|
radiusMin: radiusMin,
|
||||||
radiusMax: radiusMax,
|
radiusMax: radiusMax,
|
||||||
orientation: datum.orientation,
|
orientation: datum.orientation,
|
||||||
tilt: datum.tilt,
|
tilt: datum.tilt,
|
||||||
platformData: datum.platformData,
|
platformData: datum.platformData,
|
||||||
synthesized: datum.synthesized,
|
synthesized: datum.synthesized,
|
||||||
embedderId: datum.embedderId,
|
embedderId: datum.embedderId,
|
||||||
);
|
);
|
||||||
break;
|
case ui.PointerChange.up:
|
||||||
case ui.PointerChange.up:
|
return PointerUpEvent(
|
||||||
yield PointerUpEvent(
|
timeStamp: timeStamp,
|
||||||
timeStamp: timeStamp,
|
pointer: datum.pointerIdentifier,
|
||||||
pointer: datum.pointerIdentifier,
|
kind: kind,
|
||||||
kind: kind,
|
device: datum.device,
|
||||||
device: datum.device,
|
position: position,
|
||||||
position: position,
|
buttons: datum.buttons,
|
||||||
buttons: datum.buttons,
|
obscured: datum.obscured,
|
||||||
obscured: datum.obscured,
|
pressure: datum.pressure,
|
||||||
pressure: datum.pressure,
|
pressureMin: datum.pressureMin,
|
||||||
pressureMin: datum.pressureMin,
|
pressureMax: datum.pressureMax,
|
||||||
pressureMax: datum.pressureMax,
|
distance: datum.distance,
|
||||||
distance: datum.distance,
|
distanceMax: datum.distanceMax,
|
||||||
distanceMax: datum.distanceMax,
|
size: datum.size,
|
||||||
size: datum.size,
|
radiusMajor: radiusMajor,
|
||||||
radiusMajor: radiusMajor,
|
radiusMinor: radiusMinor,
|
||||||
radiusMinor: radiusMinor,
|
radiusMin: radiusMin,
|
||||||
radiusMin: radiusMin,
|
radiusMax: radiusMax,
|
||||||
radiusMax: radiusMax,
|
orientation: datum.orientation,
|
||||||
orientation: datum.orientation,
|
tilt: datum.tilt,
|
||||||
tilt: datum.tilt,
|
embedderId: datum.embedderId,
|
||||||
embedderId: datum.embedderId,
|
);
|
||||||
);
|
case ui.PointerChange.cancel:
|
||||||
break;
|
return PointerCancelEvent(
|
||||||
case ui.PointerChange.cancel:
|
timeStamp: timeStamp,
|
||||||
yield PointerCancelEvent(
|
pointer: datum.pointerIdentifier,
|
||||||
timeStamp: timeStamp,
|
kind: kind,
|
||||||
pointer: datum.pointerIdentifier,
|
device: datum.device,
|
||||||
kind: kind,
|
position: position,
|
||||||
device: datum.device,
|
buttons: datum.buttons,
|
||||||
position: position,
|
obscured: datum.obscured,
|
||||||
buttons: datum.buttons,
|
pressureMin: datum.pressureMin,
|
||||||
obscured: datum.obscured,
|
pressureMax: datum.pressureMax,
|
||||||
pressureMin: datum.pressureMin,
|
distance: datum.distance,
|
||||||
pressureMax: datum.pressureMax,
|
distanceMax: datum.distanceMax,
|
||||||
distance: datum.distance,
|
size: datum.size,
|
||||||
distanceMax: datum.distanceMax,
|
radiusMajor: radiusMajor,
|
||||||
size: datum.size,
|
radiusMinor: radiusMinor,
|
||||||
radiusMajor: radiusMajor,
|
radiusMin: radiusMin,
|
||||||
radiusMinor: radiusMinor,
|
radiusMax: radiusMax,
|
||||||
radiusMin: radiusMin,
|
orientation: datum.orientation,
|
||||||
radiusMax: radiusMax,
|
tilt: datum.tilt,
|
||||||
orientation: datum.orientation,
|
embedderId: datum.embedderId,
|
||||||
tilt: datum.tilt,
|
);
|
||||||
embedderId: datum.embedderId,
|
case ui.PointerChange.remove:
|
||||||
);
|
return PointerRemovedEvent(
|
||||||
break;
|
timeStamp: timeStamp,
|
||||||
case ui.PointerChange.remove:
|
kind: kind,
|
||||||
yield PointerRemovedEvent(
|
device: datum.device,
|
||||||
timeStamp: timeStamp,
|
position: position,
|
||||||
kind: kind,
|
obscured: datum.obscured,
|
||||||
device: datum.device,
|
pressureMin: datum.pressureMin,
|
||||||
position: position,
|
pressureMax: datum.pressureMax,
|
||||||
obscured: datum.obscured,
|
distanceMax: datum.distanceMax,
|
||||||
pressureMin: datum.pressureMin,
|
radiusMin: radiusMin,
|
||||||
pressureMax: datum.pressureMax,
|
radiusMax: radiusMax,
|
||||||
distanceMax: datum.distanceMax,
|
embedderId: datum.embedderId,
|
||||||
radiusMin: radiusMin,
|
);
|
||||||
radiusMax: radiusMax,
|
}
|
||||||
embedderId: datum.embedderId,
|
case ui.PointerSignalKind.scroll:
|
||||||
);
|
final Offset scrollDelta =
|
||||||
break;
|
Offset(datum.scrollDeltaX, datum.scrollDeltaY) / devicePixelRatio;
|
||||||
}
|
return PointerScrollEvent(
|
||||||
} else {
|
timeStamp: timeStamp,
|
||||||
switch (datum.signalKind!) {
|
kind: kind,
|
||||||
case ui.PointerSignalKind.scroll:
|
device: datum.device,
|
||||||
final Offset scrollDelta =
|
position: position,
|
||||||
Offset(datum.scrollDeltaX, datum.scrollDeltaY) / devicePixelRatio;
|
scrollDelta: scrollDelta,
|
||||||
yield PointerScrollEvent(
|
embedderId: datum.embedderId,
|
||||||
timeStamp: timeStamp,
|
);
|
||||||
kind: kind,
|
case ui.PointerSignalKind.unknown:
|
||||||
device: datum.device,
|
// This branch should already have 'unknown' filtered out, but
|
||||||
position: position,
|
// we don't want to return anything or miss if someone adds a new
|
||||||
scrollDelta: scrollDelta,
|
// enumeration to PointerSignalKind.
|
||||||
embedderId: datum.embedderId,
|
throw StateError('Unreachable');
|
||||||
);
|
}
|
||||||
break;
|
});
|
||||||
case ui.PointerSignalKind.none:
|
|
||||||
assert(false); // This branch should already have 'none' filtered out.
|
|
||||||
break;
|
|
||||||
case ui.PointerSignalKind.unknown:
|
|
||||||
// Ignore unknown signals.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static double _toLogicalPixels(double physicalPixels, double devicePixelRatio) => physicalPixels / devicePixelRatio;
|
static double _toLogicalPixels(double physicalPixels, double devicePixelRatio) => physicalPixels / devicePixelRatio;
|
||||||
|
@ -95,11 +95,11 @@ class PointerRouter {
|
|||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<PointerRouter>('router', this, level: DiagnosticLevel.debug);
|
DiagnosticsProperty<PointerRouter>('router', this, level: DiagnosticLevel.debug),
|
||||||
yield DiagnosticsProperty<PointerRoute>('route', route, level: DiagnosticLevel.debug);
|
DiagnosticsProperty<PointerRoute>('route', route, level: DiagnosticLevel.debug),
|
||||||
yield DiagnosticsProperty<PointerEvent>('event', event, level: DiagnosticLevel.debug);
|
DiagnosticsProperty<PointerEvent>('event', event, level: DiagnosticLevel.debug),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
|
@ -89,9 +89,9 @@ class PointerSignalResolver {
|
|||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<PointerSignalEvent>('Event', event, style: DiagnosticsTreeStyle.errorProperty);
|
DiagnosticsProperty<PointerSignalEvent>('Event', event, style: DiagnosticsTreeStyle.errorProperty),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
|
@ -199,10 +199,10 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
|
|||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield StringProperty('Handler', name);
|
StringProperty('Handler', name),
|
||||||
yield DiagnosticsProperty<GestureRecognizer>('Recognizer', this, style: DiagnosticsTreeStyle.errorProperty);
|
DiagnosticsProperty<GestureRecognizer>('Recognizer', this, style: DiagnosticsTreeStyle.errorProperty),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
|
@ -797,11 +797,13 @@ class _MaterialAppState extends State<MaterialApp> {
|
|||||||
// of a particular LocalizationsDelegate.type is loaded so the
|
// of a particular LocalizationsDelegate.type is loaded so the
|
||||||
// localizationsDelegate parameter can be used to override
|
// localizationsDelegate parameter can be used to override
|
||||||
// _MaterialLocalizationsDelegate.
|
// _MaterialLocalizationsDelegate.
|
||||||
Iterable<LocalizationsDelegate<dynamic>> get _localizationsDelegates sync* {
|
Iterable<LocalizationsDelegate<dynamic>> get _localizationsDelegates {
|
||||||
if (widget.localizationsDelegates != null)
|
return <LocalizationsDelegate<dynamic>>[
|
||||||
yield* widget.localizationsDelegates!;
|
if (widget.localizationsDelegates != null)
|
||||||
yield DefaultMaterialLocalizations.delegate;
|
...widget.localizationsDelegates!,
|
||||||
yield DefaultCupertinoLocalizations.delegate;
|
DefaultMaterialLocalizations.delegate,
|
||||||
|
DefaultCupertinoLocalizations.delegate,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _inspectorSelectButtonBuilder(BuildContext context, VoidCallback onPressed) {
|
Widget _inspectorSelectButtonBuilder(BuildContext context, VoidCallback onPressed) {
|
||||||
|
@ -1076,9 +1076,9 @@ class ChoiceChip extends StatelessWidget
|
|||||||
/// ];
|
/// ];
|
||||||
/// final List<String> _filters = <String>[];
|
/// final List<String> _filters = <String>[];
|
||||||
///
|
///
|
||||||
/// Iterable<Widget> get actorWidgets sync* {
|
/// Iterable<Widget> get actorWidgets {
|
||||||
/// for (final ActorFilterEntry actor in _cast) {
|
/// return _cast.map((ActorFilterEntry actor) {
|
||||||
/// yield Padding(
|
/// return Padding(
|
||||||
/// padding: const EdgeInsets.all(4.0),
|
/// padding: const EdgeInsets.all(4.0),
|
||||||
/// child: FilterChip(
|
/// child: FilterChip(
|
||||||
/// avatar: CircleAvatar(child: Text(actor.initials)),
|
/// avatar: CircleAvatar(child: Text(actor.initials)),
|
||||||
@ -1097,7 +1097,7 @@ class ChoiceChip extends StatelessWidget
|
|||||||
/// },
|
/// },
|
||||||
/// ),
|
/// ),
|
||||||
/// );
|
/// );
|
||||||
/// }
|
/// });
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// @override
|
/// @override
|
||||||
@ -2257,16 +2257,15 @@ class _RenderChip extends RenderBox with SlottedContainerRenderObjectMixin<_Chip
|
|||||||
|
|
||||||
// The returned list is ordered for hit testing.
|
// The returned list is ordered for hit testing.
|
||||||
@override
|
@override
|
||||||
Iterable<RenderBox> get children sync* {
|
Iterable<RenderBox> get children {
|
||||||
if (avatar != null) {
|
return <RenderBox>[
|
||||||
yield avatar!;
|
if (avatar != null)
|
||||||
}
|
avatar!,
|
||||||
if (label != null) {
|
if (label != null)
|
||||||
yield label!;
|
label!,
|
||||||
}
|
if (deleteIcon != null)
|
||||||
if (deleteIcon != null) {
|
deleteIcon!,
|
||||||
yield deleteIcon!;
|
];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get isDrawingCheckmark => theme.showCheckmark && !checkmarkAnimation.isDismissed;
|
bool get isDrawingCheckmark => theme.showCheckmark && !checkmarkAnimation.isDismissed;
|
||||||
|
@ -723,29 +723,31 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
|
|
||||||
// The returned list is ordered for hit testing.
|
// The returned list is ordered for hit testing.
|
||||||
@override
|
@override
|
||||||
Iterable<RenderBox> get children sync* {
|
Iterable<RenderBox> get children {
|
||||||
if (icon != null)
|
return <RenderBox>[
|
||||||
yield icon!;
|
if (icon != null)
|
||||||
if (input != null)
|
icon!,
|
||||||
yield input!;
|
if (input != null)
|
||||||
if (prefixIcon != null)
|
input!,
|
||||||
yield prefixIcon!;
|
if (prefixIcon != null)
|
||||||
if (suffixIcon != null)
|
prefixIcon!,
|
||||||
yield suffixIcon!;
|
if (suffixIcon != null)
|
||||||
if (prefix != null)
|
suffixIcon!,
|
||||||
yield prefix!;
|
if (prefix != null)
|
||||||
if (suffix != null)
|
prefix!,
|
||||||
yield suffix!;
|
if (suffix != null)
|
||||||
if (label != null)
|
suffix!,
|
||||||
yield label!;
|
if (label != null)
|
||||||
if (hint != null)
|
label!,
|
||||||
yield hint!;
|
if (hint != null)
|
||||||
if (helperError != null)
|
hint!,
|
||||||
yield helperError!;
|
if (helperError != null)
|
||||||
if (counter != null)
|
helperError!,
|
||||||
yield counter!;
|
if (counter != null)
|
||||||
if (container != null)
|
counter!,
|
||||||
yield container!;
|
if (container != null)
|
||||||
|
container!,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
_Decoration get decoration => _decoration;
|
_Decoration get decoration => _decoration;
|
||||||
|
@ -1041,33 +1041,31 @@ class ListTile extends StatelessWidget {
|
|||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [Divider], which you can use to obtain this effect manually.
|
/// * [Divider], which you can use to obtain this effect manually.
|
||||||
static Iterable<Widget> divideTiles({ BuildContext? context, required Iterable<Widget> tiles, Color? color }) sync* {
|
static Iterable<Widget> divideTiles({ BuildContext? context, required Iterable<Widget> tiles, Color? color }) {
|
||||||
assert(tiles != null);
|
assert(tiles != null);
|
||||||
assert(color != null || context != null);
|
assert(color != null || context != null);
|
||||||
|
tiles = tiles.toList();
|
||||||
|
|
||||||
final Iterator<Widget> iterator = tiles.iterator;
|
if (tiles.isEmpty || tiles.length == 1) {
|
||||||
final bool hasNext = iterator.moveNext();
|
return tiles;
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasNext)
|
Widget wrapTile(Widget tile) {
|
||||||
return;
|
return DecoratedBox(
|
||||||
|
|
||||||
final Decoration decoration = BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
bottom: Divider.createBorderSide(context, color: color),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget tile = iterator.current;
|
|
||||||
while (iterator.moveNext()) {
|
|
||||||
yield DecoratedBox(
|
|
||||||
position: DecorationPosition.foreground,
|
position: DecorationPosition.foreground,
|
||||||
decoration: decoration,
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: Divider.createBorderSide(context, color: color),
|
||||||
|
),
|
||||||
|
),
|
||||||
child: tile,
|
child: tile,
|
||||||
);
|
);
|
||||||
tile = iterator.current;
|
|
||||||
}
|
}
|
||||||
if (hasNext)
|
|
||||||
yield tile;
|
return <Widget>[
|
||||||
|
...tiles.take(tiles.length - 1).map(wrapTile),
|
||||||
|
tiles.last,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color? _iconColor(ThemeData theme, ListTileThemeData tileTheme) {
|
Color? _iconColor(ThemeData theme, ListTileThemeData tileTheme) {
|
||||||
@ -1389,15 +1387,17 @@ class _RenderListTile extends RenderBox with SlottedContainerRenderObjectMixin<_
|
|||||||
|
|
||||||
// The returned list is ordered for hit testing.
|
// The returned list is ordered for hit testing.
|
||||||
@override
|
@override
|
||||||
Iterable<RenderBox> get children sync* {
|
Iterable<RenderBox> get children {
|
||||||
if (leading != null)
|
return <RenderBox>[
|
||||||
yield leading!;
|
if (leading != null)
|
||||||
if (title != null)
|
leading!,
|
||||||
yield title!;
|
if (title != null)
|
||||||
if (subtitle != null)
|
title!,
|
||||||
yield subtitle!;
|
if (subtitle != null)
|
||||||
if (trailing != null)
|
subtitle!,
|
||||||
yield trailing!;
|
if (trailing != null)
|
||||||
|
trailing!,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get isDense => _isDense;
|
bool get isDense => _isDense;
|
||||||
|
@ -51,12 +51,10 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
|
|||||||
chunkEvents: chunkEvents.stream,
|
chunkEvents: chunkEvents.stream,
|
||||||
scale: key.scale,
|
scale: key.scale,
|
||||||
debugLabel: key.url,
|
debugLabel: key.url,
|
||||||
informationCollector: () {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
return <DiagnosticsNode>[
|
DiagnosticsProperty<image_provider.ImageProvider>('Image provider', this),
|
||||||
DiagnosticsProperty<image_provider.ImageProvider>('Image provider', this),
|
DiagnosticsProperty<image_provider.NetworkImage>('Image key', key),
|
||||||
DiagnosticsProperty<image_provider.NetworkImage>('Image key', key),
|
],
|
||||||
];
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,12 +59,10 @@ class NetworkImage
|
|||||||
InformationCollector? _imageStreamInformationCollector(image_provider.NetworkImage key) {
|
InformationCollector? _imageStreamInformationCollector(image_provider.NetworkImage key) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () {
|
collector = () => <DiagnosticsNode>[
|
||||||
return <DiagnosticsNode>[
|
DiagnosticsProperty<image_provider.ImageProvider>('Image provider', this),
|
||||||
DiagnosticsProperty<image_provider.ImageProvider>('Image provider', this),
|
DiagnosticsProperty<NetworkImage>('Image key', key as NetworkImage),
|
||||||
DiagnosticsProperty<NetworkImage>('Image key', key as NetworkImage),
|
];
|
||||||
];
|
|
||||||
};
|
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
return collector;
|
return collector;
|
||||||
|
@ -657,7 +657,7 @@ void paintImage({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<Rect> _generateImageTileRects(Rect outputRect, Rect fundamentalRect, ImageRepeat repeat) sync* {
|
Iterable<Rect> _generateImageTileRects(Rect outputRect, Rect fundamentalRect, ImageRepeat repeat) {
|
||||||
int startX = 0;
|
int startX = 0;
|
||||||
int startY = 0;
|
int startY = 0;
|
||||||
int stopX = 0;
|
int stopX = 0;
|
||||||
@ -675,10 +675,11 @@ Iterable<Rect> _generateImageTileRects(Rect outputRect, Rect fundamentalRect, Im
|
|||||||
stopY = ((outputRect.bottom - fundamentalRect.bottom) / strideY).ceil();
|
stopY = ((outputRect.bottom - fundamentalRect.bottom) / strideY).ceil();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = startX; i <= stopX; ++i) {
|
return <Rect>[
|
||||||
for (int j = startY; j <= stopY; ++j)
|
for (int i = startX; i <= stopX; ++i)
|
||||||
yield fundamentalRect.shift(Offset(i * strideX, j * strideY));
|
for (int j = startY; j <= stopY; ++j)
|
||||||
}
|
fundamentalRect.shift(Offset(i * strideX, j * strideY)),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect _scaleRect(Rect rect, double scale) => Rect.fromLTRB(rect.left * scale, rect.top * scale, rect.right * scale, rect.bottom * scale);
|
Rect _scaleRect(Rect rect, double scale) => Rect.fromLTRB(rect.left * scale, rect.top * scale, rect.right * scale, rect.bottom * scale);
|
||||||
|
@ -336,11 +336,11 @@ abstract class ImageProvider<T extends Object> {
|
|||||||
await null; // wait an event turn in case a listener has been added to the image stream.
|
await null; // wait an event turn in case a listener has been added to the image stream.
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<ImageProvider>('Image provider', this);
|
DiagnosticsProperty<ImageProvider>('Image provider', this),
|
||||||
yield DiagnosticsProperty<ImageConfiguration>('Image configuration', configuration);
|
DiagnosticsProperty<ImageConfiguration>('Image configuration', configuration),
|
||||||
yield DiagnosticsProperty<T>('Image key', key, defaultValue: null);
|
DiagnosticsProperty<T>('Image key', key, defaultValue: null),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
if (stream.completer == null) {
|
if (stream.completer == null) {
|
||||||
@ -395,11 +395,11 @@ abstract class ImageProvider<T extends Object> {
|
|||||||
} else {
|
} else {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<ImageProvider>('Image provider', this);
|
DiagnosticsProperty<ImageProvider>('Image provider', this),
|
||||||
yield DiagnosticsProperty<ImageConfiguration>('Image configuration', configuration);
|
DiagnosticsProperty<ImageConfiguration>('Image configuration', configuration),
|
||||||
yield DiagnosticsProperty<T>('Image key', key, defaultValue: null);
|
DiagnosticsProperty<T>('Image key', key, defaultValue: null),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
@ -648,10 +648,10 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
|
|||||||
ImageStreamCompleter load(AssetBundleImageKey key, DecoderCallback decode) {
|
ImageStreamCompleter load(AssetBundleImageKey key, DecoderCallback decode) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<ImageProvider>('Image provider', this);
|
DiagnosticsProperty<ImageProvider>('Image provider', this),
|
||||||
yield DiagnosticsProperty<AssetBundleImageKey>('Image key', key);
|
DiagnosticsProperty<AssetBundleImageKey>('Image key', key),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
return MultiFrameImageStreamCompleter(
|
return MultiFrameImageStreamCompleter(
|
||||||
@ -878,9 +878,9 @@ class FileImage extends ImageProvider<FileImage> {
|
|||||||
codec: _loadAsync(key, decode),
|
codec: _loadAsync(key, decode),
|
||||||
scale: key.scale,
|
scale: key.scale,
|
||||||
debugLabel: key.file.path,
|
debugLabel: key.file.path,
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield ErrorDescription('Path: ${file.path}');
|
ErrorDescription('Path: ${file.path}'),
|
||||||
},
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,16 +241,18 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
|
|||||||
exception: FlutterError('A $runtimeType overflowed by $overflowText.'),
|
exception: FlutterError('A $runtimeType overflowed by $overflowText.'),
|
||||||
library: 'rendering library',
|
library: 'rendering library',
|
||||||
context: ErrorDescription('during layout'),
|
context: ErrorDescription('during layout'),
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
if (debugCreator != null)
|
// debugCreator should only be set in DebugMode, but we want the
|
||||||
yield DiagnosticsDebugCreator(debugCreator!);
|
// treeshaker to know that.
|
||||||
yield* overflowHints!;
|
if (kDebugMode && debugCreator != null)
|
||||||
yield describeForError('The specific $runtimeType in question is');
|
DiagnosticsDebugCreator(debugCreator!),
|
||||||
|
...overflowHints!,
|
||||||
|
describeForError('The specific $runtimeType in question is'),
|
||||||
// TODO(jacobr): this line is ascii art that it would be nice to
|
// TODO(jacobr): this line is ascii art that it would be nice to
|
||||||
// handle a little more generically in GUI debugging clients in the
|
// handle a little more generically in GUI debugging clients in the
|
||||||
// future.
|
// future.
|
||||||
yield DiagnosticsNode.message('◢◤' * (FlutterError.wrapWidth ~/ 2), allowWrap: false);
|
DiagnosticsNode.message('◢◤' * (FlutterError.wrapWidth ~/ 2), allowWrap: false),
|
||||||
},
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -67,9 +67,8 @@ class AnnotationResult<T> {
|
|||||||
/// tree.
|
/// tree.
|
||||||
///
|
///
|
||||||
/// It is similar to [entries] but does not contain other information.
|
/// It is similar to [entries] but does not contain other information.
|
||||||
Iterable<T> get annotations sync* {
|
Iterable<T> get annotations {
|
||||||
for (final AnnotationEntry<T> entry in _entries)
|
return _entries.map((AnnotationEntry<T> entry) => entry.annotation);
|
||||||
yield entry.annotation;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1391,16 +1391,18 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
|
|||||||
stack: stack,
|
stack: stack,
|
||||||
library: 'rendering library',
|
library: 'rendering library',
|
||||||
context: ErrorDescription('during $method()'),
|
context: ErrorDescription('during $method()'),
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
if (debugCreator != null)
|
// debugCreator should always be null outside of debugMode, but we want
|
||||||
yield DiagnosticsDebugCreator(debugCreator!);
|
// the tree shaker to notice this.
|
||||||
yield describeForError('The following RenderObject was being processed when the exception was fired');
|
if (kDebugMode && debugCreator != null)
|
||||||
|
DiagnosticsDebugCreator(debugCreator!),
|
||||||
|
describeForError('The following RenderObject was being processed when the exception was fired'),
|
||||||
// TODO(jacobr): this error message has a code smell. Consider whether
|
// TODO(jacobr): this error message has a code smell. Consider whether
|
||||||
// displaying the truncated children is really useful for command line
|
// displaying the truncated children is really useful for command line
|
||||||
// users. Inspector users can see the full tree by clicking on the
|
// users. Inspector users can see the full tree by clicking on the
|
||||||
// render object so this may not be that useful.
|
// render object so this may not be that useful.
|
||||||
yield describeForError('RenderObject', style: DiagnosticsTreeStyle.truncateChildren);
|
describeForError('RenderObject', style: DiagnosticsTreeStyle.truncateChildren),
|
||||||
},
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1781,7 +1783,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
|
|||||||
assert(constraints != null);
|
assert(constraints != null);
|
||||||
assert(constraints.debugAssertIsValid(
|
assert(constraints.debugAssertIsValid(
|
||||||
isAppliedConstraint: true,
|
isAppliedConstraint: true,
|
||||||
informationCollector: () sync* {
|
informationCollector: () {
|
||||||
final List<String> stack = StackTrace.current.toString().split('\n');
|
final List<String> stack = StackTrace.current.toString().split('\n');
|
||||||
int? targetFrame;
|
int? targetFrame;
|
||||||
final Pattern layoutFramePattern = RegExp(r'^#[0-9]+ +RenderObject.layout \(');
|
final Pattern layoutFramePattern = RegExp(r'^#[0-9]+ +RenderObject.layout \(');
|
||||||
@ -1796,13 +1798,16 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
|
|||||||
final Match? targetFrameMatch = targetFramePattern.matchAsPrefix(stack[targetFrame]);
|
final Match? targetFrameMatch = targetFramePattern.matchAsPrefix(stack[targetFrame]);
|
||||||
final String? problemFunction = (targetFrameMatch != null && targetFrameMatch.groupCount > 0) ? targetFrameMatch.group(1) : stack[targetFrame].trim();
|
final String? problemFunction = (targetFrameMatch != null && targetFrameMatch.groupCount > 0) ? targetFrameMatch.group(1) : stack[targetFrame].trim();
|
||||||
// TODO(jacobr): this case is similar to displaying a single stack frame.
|
// TODO(jacobr): this case is similar to displaying a single stack frame.
|
||||||
yield ErrorDescription(
|
return <DiagnosticsNode>[
|
||||||
"These invalid constraints were provided to $runtimeType's layout() "
|
ErrorDescription(
|
||||||
'function by the following function, which probably computed the '
|
"These invalid constraints were provided to $runtimeType's layout() "
|
||||||
'invalid constraints in question:\n'
|
'function by the following function, which probably computed the '
|
||||||
' $problemFunction',
|
'invalid constraints in question:\n'
|
||||||
);
|
' $problemFunction',
|
||||||
|
),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
return <DiagnosticsNode>[];
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
assert(!_debugDoingThisResize);
|
assert(!_debugDoingThisResize);
|
||||||
|
@ -1203,9 +1203,9 @@ abstract class RenderSliver extends RenderObject {
|
|||||||
@override
|
@override
|
||||||
void debugAssertDoesMeetConstraints() {
|
void debugAssertDoesMeetConstraints() {
|
||||||
assert(geometry!.debugAssertIsValid(
|
assert(geometry!.debugAssertIsValid(
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield describeForError('The RenderSliver that returned the offending geometry was');
|
describeForError('The RenderSliver that returned the offending geometry was'),
|
||||||
},
|
],
|
||||||
));
|
));
|
||||||
assert(() {
|
assert(() {
|
||||||
if (geometry!.paintOrigin + geometry!.paintExtent > constraints.remainingPaintExtent) {
|
if (geometry!.paintOrigin + geometry!.paintExtent > constraints.remainingPaintExtent) {
|
||||||
|
@ -795,6 +795,7 @@ class RenderTable extends RenderBox {
|
|||||||
/// column, in row order, starting from the first row.
|
/// column, in row order, starting from the first row.
|
||||||
///
|
///
|
||||||
/// This is a lazily-evaluated iterable.
|
/// This is a lazily-evaluated iterable.
|
||||||
|
// flutter_ignore: no_sync_async_star
|
||||||
Iterable<RenderBox> column(int x) sync* {
|
Iterable<RenderBox> column(int x) sync* {
|
||||||
for (int y = 0; y < rows; y += 1) {
|
for (int y = 0; y < rows; y += 1) {
|
||||||
final int xy = x + y * columns;
|
final int xy = x + y * columns;
|
||||||
@ -808,6 +809,7 @@ class RenderTable extends RenderBox {
|
|||||||
/// row, in column order, starting with the first column.
|
/// row, in column order, starting with the first column.
|
||||||
///
|
///
|
||||||
/// This is a lazily-evaluated iterable.
|
/// This is a lazily-evaluated iterable.
|
||||||
|
// flutter_ignore: no_sync_async_star
|
||||||
Iterable<RenderBox> row(int y) sync* {
|
Iterable<RenderBox> row(int y) sync* {
|
||||||
final int start = y * columns;
|
final int start = y * columns;
|
||||||
final int end = (y + 1) * columns;
|
final int end = (y + 1) * columns;
|
||||||
|
@ -1718,37 +1718,40 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<RenderSliver> get childrenInPaintOrder sync* {
|
Iterable<RenderSliver> get childrenInPaintOrder {
|
||||||
|
final List<RenderSliver> children = <RenderSliver>[];
|
||||||
if (firstChild == null)
|
if (firstChild == null)
|
||||||
return;
|
return children;
|
||||||
RenderSliver? child = firstChild;
|
RenderSliver? child = firstChild;
|
||||||
while (child != center) {
|
while (child != center) {
|
||||||
yield child!;
|
children.add(child!);
|
||||||
child = childAfter(child);
|
child = childAfter(child);
|
||||||
}
|
}
|
||||||
child = lastChild;
|
child = lastChild;
|
||||||
while (true) {
|
while (true) {
|
||||||
yield child!;
|
children.add(child!);
|
||||||
if (child == center)
|
if (child == center)
|
||||||
return;
|
return children;
|
||||||
child = childBefore(child);
|
child = childBefore(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<RenderSliver> get childrenInHitTestOrder sync* {
|
Iterable<RenderSliver> get childrenInHitTestOrder {
|
||||||
|
final List<RenderSliver> children = <RenderSliver>[];
|
||||||
if (firstChild == null)
|
if (firstChild == null)
|
||||||
return;
|
return children;
|
||||||
RenderSliver? child = center;
|
RenderSliver? child = center;
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
yield child;
|
children.add(child);
|
||||||
child = childAfter(child);
|
child = childAfter(child);
|
||||||
}
|
}
|
||||||
child = childBefore(center!);
|
child = childBefore(center!);
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
yield child;
|
children.add(child);
|
||||||
child = childBefore(child);
|
child = childBefore(child);
|
||||||
}
|
}
|
||||||
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -2030,20 +2033,24 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||||||
String labelForChild(int index) => 'child $index';
|
String labelForChild(int index) => 'child $index';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<RenderSliver> get childrenInPaintOrder sync* {
|
Iterable<RenderSliver> get childrenInPaintOrder {
|
||||||
|
final List<RenderSliver> children = <RenderSliver>[];
|
||||||
RenderSliver? child = lastChild;
|
RenderSliver? child = lastChild;
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
yield child;
|
children.add(child);
|
||||||
child = childBefore(child);
|
child = childBefore(child);
|
||||||
}
|
}
|
||||||
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<RenderSliver> get childrenInHitTestOrder sync* {
|
Iterable<RenderSliver> get childrenInHitTestOrder {
|
||||||
|
final List<RenderSliver> children = <RenderSliver>[];
|
||||||
RenderSliver? child = firstChild;
|
RenderSliver? child = firstChild;
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
yield child;
|
children.add(child);
|
||||||
child = childAfter(child);
|
child = childAfter(child);
|
||||||
}
|
}
|
||||||
|
return children;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,13 +288,13 @@ mixin SchedulerBinding on BindingBase {
|
|||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<TimingsCallback>(
|
DiagnosticsProperty<TimingsCallback>(
|
||||||
'The TimingsCallback that gets executed was',
|
'The TimingsCallback that gets executed was',
|
||||||
callback,
|
callback,
|
||||||
style: DiagnosticsTreeStyle.errorProperty,
|
style: DiagnosticsTreeStyle.errorProperty,
|
||||||
);
|
),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
@ -467,13 +467,15 @@ mixin SchedulerBinding on BindingBase {
|
|||||||
stack: exceptionStack,
|
stack: exceptionStack,
|
||||||
library: 'scheduler library',
|
library: 'scheduler library',
|
||||||
context: ErrorDescription('during a task callback'),
|
context: ErrorDescription('during a task callback'),
|
||||||
informationCollector: (callbackStack == null) ? null : () sync* {
|
informationCollector: (callbackStack == null) ? null : () {
|
||||||
yield DiagnosticsStackTrace(
|
return <DiagnosticsNode>[
|
||||||
'\nThis exception was thrown in the context of a scheduler callback. '
|
DiagnosticsStackTrace(
|
||||||
'When the scheduler callback was _registered_ (as opposed to when the '
|
'\nThis exception was thrown in the context of a scheduler callback. '
|
||||||
'exception was thrown), this was the stack',
|
'When the scheduler callback was _registered_ (as opposed to when the '
|
||||||
callbackStack,
|
'exception was thrown), this was the stack',
|
||||||
);
|
callbackStack,
|
||||||
|
),
|
||||||
|
];
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -566,24 +568,21 @@ mixin SchedulerBinding on BindingBase {
|
|||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
exception: reason,
|
exception: reason,
|
||||||
library: 'scheduler library',
|
library: 'scheduler library',
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
if (count == 1) {
|
if (count == 1)
|
||||||
// TODO(jacobr): I have added an extra line break in this case.
|
// TODO(jacobr): I have added an extra line break in this case.
|
||||||
yield ErrorDescription(
|
ErrorDescription(
|
||||||
'There was one transient callback left. '
|
'There was one transient callback left. '
|
||||||
'The stack trace for when it was registered is as follows:',
|
'The stack trace for when it was registered is as follows:',
|
||||||
);
|
)
|
||||||
} else {
|
else
|
||||||
yield ErrorDescription(
|
ErrorDescription(
|
||||||
'There were $count transient callbacks left. '
|
'There were $count transient callbacks left. '
|
||||||
'The stack traces for when they were registered are as follows:',
|
'The stack traces for when they were registered are as follows:',
|
||||||
);
|
),
|
||||||
}
|
for (final int id in callbacks.keys)
|
||||||
for (final int id in callbacks.keys) {
|
DiagnosticsStackTrace('── callback $id ──', callbacks[id]!.debugStack, showSeparator: false),
|
||||||
final _FrameCallbackEntry entry = callbacks[id]!;
|
],
|
||||||
yield DiagnosticsStackTrace('── callback $id ──', entry.debugStack, showSeparator: false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1149,13 +1148,15 @@ mixin SchedulerBinding on BindingBase {
|
|||||||
stack: exceptionStack,
|
stack: exceptionStack,
|
||||||
library: 'scheduler library',
|
library: 'scheduler library',
|
||||||
context: ErrorDescription('during a scheduler callback'),
|
context: ErrorDescription('during a scheduler callback'),
|
||||||
informationCollector: (callbackStack == null) ? null : () sync* {
|
informationCollector: (callbackStack == null) ? null : () {
|
||||||
yield DiagnosticsStackTrace(
|
return <DiagnosticsNode>[
|
||||||
'\nThis exception was thrown in the context of a scheduler callback. '
|
DiagnosticsStackTrace(
|
||||||
'When the scheduler callback was _registered_ (as opposed to when the '
|
'\nThis exception was thrown in the context of a scheduler callback. '
|
||||||
'exception was thrown), this was the stack',
|
'When the scheduler callback was _registered_ (as opposed to when the '
|
||||||
callbackStack,
|
'exception was thrown), this was the stack',
|
||||||
);
|
callbackStack,
|
||||||
|
),
|
||||||
|
];
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,9 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
|
|||||||
LicenseRegistry.addLicense(_addLicenses);
|
LicenseRegistry.addLicense(_addLicenses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(dnfield): Refactor the license logic.
|
||||||
|
// https://github.com/flutter/flutter/issues/95043
|
||||||
|
// flutter_ignore: no_sync_async_star
|
||||||
Stream<LicenseEntry> _addLicenses() async* {
|
Stream<LicenseEntry> _addLicenses() async* {
|
||||||
// Using _something_ here to break
|
// Using _something_ here to break
|
||||||
// this into two parts is important because isolates take a while to copy
|
// this into two parts is important because isolates take a while to copy
|
||||||
|
@ -516,9 +516,9 @@ class HardwareKeyboard {
|
|||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<KeyEvent>('Event', event);
|
DiagnosticsProperty<KeyEvent>('Event', event),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
@ -833,9 +833,9 @@ class KeyEventManager {
|
|||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<KeyMessage>('KeyMessage', message);
|
DiagnosticsProperty<KeyMessage>('KeyMessage', message),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
|
@ -680,9 +680,9 @@ class RawKeyboard {
|
|||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<RawKeyEvent>('Event', event);
|
DiagnosticsProperty<RawKeyEvent>('Event', event),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
|
@ -345,13 +345,13 @@ abstract class Action<T extends Intent> with Diagnosticable {
|
|||||||
for (final ActionListenerCallback listener in localListeners) {
|
for (final ActionListenerCallback listener in localListeners) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<Action<T>>(
|
DiagnosticsProperty<Action<T>>(
|
||||||
'The $runtimeType sending notification was',
|
'The $runtimeType sending notification was',
|
||||||
this,
|
this,
|
||||||
style: DiagnosticsTreeStyle.errorProperty,
|
style: DiagnosticsTreeStyle.errorProperty,
|
||||||
);
|
),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
try {
|
try {
|
||||||
|
@ -1472,10 +1472,12 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
|
|||||||
// of a particular LocalizationsDelegate.type is loaded so the
|
// of a particular LocalizationsDelegate.type is loaded so the
|
||||||
// localizationsDelegate parameter can be used to override
|
// localizationsDelegate parameter can be used to override
|
||||||
// WidgetsLocalizations.delegate.
|
// WidgetsLocalizations.delegate.
|
||||||
Iterable<LocalizationsDelegate<dynamic>> get _localizationsDelegates sync* {
|
Iterable<LocalizationsDelegate<dynamic>> get _localizationsDelegates {
|
||||||
if (widget.localizationsDelegates != null)
|
return <LocalizationsDelegate<dynamic>>[
|
||||||
yield* widget.localizationsDelegates!;
|
if (widget.localizationsDelegates != null)
|
||||||
yield DefaultWidgetsLocalizations.delegate;
|
...widget.localizationsDelegates!,
|
||||||
|
DefaultWidgetsLocalizations.delegate,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// BUILDER
|
// BUILDER
|
||||||
@ -1496,33 +1498,33 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
|
|||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
exception: "Warning: This application's locale, $appLocale, is not supported by all of its localization delegates.",
|
exception: "Warning: This application's locale, $appLocale, is not supported by all of its localization delegates.",
|
||||||
library: 'widgets',
|
library: 'widgets',
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
for (final Type unsupportedType in unsupportedTypes) {
|
for (final Type unsupportedType in unsupportedTypes)
|
||||||
yield ErrorDescription(
|
ErrorDescription(
|
||||||
'• A $unsupportedType delegate that supports the $appLocale locale was not found.',
|
'• A $unsupportedType delegate that supports the $appLocale locale was not found.',
|
||||||
);
|
),
|
||||||
}
|
ErrorSpacer(),
|
||||||
yield ErrorSpacer();
|
if (unsupportedTypes.length == 1 && unsupportedTypes.single.toString() == 'CupertinoLocalizations')
|
||||||
if (unsupportedTypes.length == 1 && unsupportedTypes.single.toString() == 'CupertinoLocalizations') {
|
|
||||||
// We previously explicitly avoided checking for this class so it's not uncommon for applications
|
// We previously explicitly avoided checking for this class so it's not uncommon for applications
|
||||||
// to have omitted importing the required delegate.
|
// to have omitted importing the required delegate.
|
||||||
yield ErrorHint(
|
...<DiagnosticsNode>[
|
||||||
'If the application is built using GlobalMaterialLocalizations.delegate, consider using '
|
ErrorHint(
|
||||||
'GlobalMaterialLocalizations.delegates (plural) instead, as that will automatically declare '
|
'If the application is built using GlobalMaterialLocalizations.delegate, consider using '
|
||||||
'the appropriate Cupertino localizations.'
|
'GlobalMaterialLocalizations.delegates (plural) instead, as that will automatically declare '
|
||||||
);
|
'the appropriate Cupertino localizations.'
|
||||||
yield ErrorSpacer();
|
),
|
||||||
}
|
ErrorSpacer(),
|
||||||
yield ErrorHint(
|
],
|
||||||
|
ErrorHint(
|
||||||
'The declared supported locales for this app are: ${widget.supportedLocales.join(", ")}'
|
'The declared supported locales for this app are: ${widget.supportedLocales.join(", ")}'
|
||||||
);
|
),
|
||||||
yield ErrorSpacer();
|
ErrorSpacer(),
|
||||||
yield ErrorDescription(
|
ErrorDescription(
|
||||||
'See https://flutter.dev/tutorials/internationalization/ for more '
|
'See https://flutter.dev/tutorials/internationalization/ for more '
|
||||||
"information about configuring an app's locale, supportedLocales, "
|
"information about configuring an app's locale, supportedLocales, "
|
||||||
'and localizationsDelegates parameters.',
|
'and localizationsDelegates parameters.',
|
||||||
);
|
),
|
||||||
},
|
],
|
||||||
));
|
));
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
|
@ -905,17 +905,19 @@ class _DragAvatar<T extends Object> extends Drag {
|
|||||||
_activeTarget = newTarget;
|
_activeTarget = newTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<_DragTargetState<Object>> _getDragTargets(Iterable<HitTestEntry> path) sync* {
|
Iterable<_DragTargetState<Object>> _getDragTargets(Iterable<HitTestEntry> path) {
|
||||||
// Look for the RenderBoxes that corresponds to the hit target (the hit target
|
// Look for the RenderBoxes that corresponds to the hit target (the hit target
|
||||||
// widgets build RenderMetaData boxes for us for this purpose).
|
// widgets build RenderMetaData boxes for us for this purpose).
|
||||||
|
final List<_DragTargetState<Object>> targets = <_DragTargetState<Object>>[];
|
||||||
for (final HitTestEntry entry in path) {
|
for (final HitTestEntry entry in path) {
|
||||||
final HitTestTarget target = entry.target;
|
final HitTestTarget target = entry.target;
|
||||||
if (target is RenderMetaData) {
|
if (target is RenderMetaData) {
|
||||||
final dynamic metaData = target.metaData;
|
final dynamic metaData = target.metaData;
|
||||||
if (metaData is _DragTargetState && metaData.isExpectedDataType(data, T))
|
if (metaData is _DragTargetState && metaData.isExpectedDataType(data, T))
|
||||||
yield metaData;
|
targets.add(metaData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _leaveAllEntered() {
|
void _leaveAllEntered() {
|
||||||
|
@ -1520,13 +1520,13 @@ class FocusManager with DiagnosticableTreeMixin, ChangeNotifier {
|
|||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
InformationCollector? collector;
|
InformationCollector? collector;
|
||||||
assert(() {
|
assert(() {
|
||||||
collector = () sync* {
|
collector = () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<FocusManager>(
|
DiagnosticsProperty<FocusManager>(
|
||||||
'The $runtimeType sending notification was',
|
'The $runtimeType sending notification was',
|
||||||
this,
|
this,
|
||||||
style: DiagnosticsTreeStyle.errorProperty,
|
style: DiagnosticsTreeStyle.errorProperty,
|
||||||
);
|
),
|
||||||
};
|
];
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
|
@ -1455,35 +1455,34 @@ abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget {
|
|||||||
required ParentData? parentData,
|
required ParentData? parentData,
|
||||||
RenderObjectWidget? parentDataCreator,
|
RenderObjectWidget? parentDataCreator,
|
||||||
DiagnosticsNode? ownershipChain,
|
DiagnosticsNode? ownershipChain,
|
||||||
}) sync* {
|
}) {
|
||||||
assert(T != dynamic);
|
assert(T != dynamic);
|
||||||
assert(T != ParentData);
|
assert(T != ParentData);
|
||||||
assert(debugTypicalAncestorWidgetClass != null);
|
assert(debugTypicalAncestorWidgetClass != null);
|
||||||
|
|
||||||
final String description = 'The ParentDataWidget $this wants to apply ParentData of type $T to a RenderObject';
|
final String description = 'The ParentDataWidget $this wants to apply ParentData of type $T to a RenderObject';
|
||||||
if (parentData == null) {
|
return <DiagnosticsNode>[
|
||||||
yield ErrorDescription(
|
if (parentData == null)
|
||||||
'$description, which has not been set up to receive any ParentData.',
|
ErrorDescription(
|
||||||
);
|
'$description, which has not been set up to receive any ParentData.',
|
||||||
} else {
|
)
|
||||||
yield ErrorDescription(
|
else
|
||||||
'$description, which has been set up to accept ParentData of incompatible type ${parentData.runtimeType}.',
|
ErrorDescription(
|
||||||
);
|
'$description, which has been set up to accept ParentData of incompatible type ${parentData.runtimeType}.',
|
||||||
}
|
),
|
||||||
yield ErrorHint(
|
ErrorHint(
|
||||||
'Usually, this means that the $runtimeType widget has the wrong ancestor RenderObjectWidget. '
|
'Usually, this means that the $runtimeType widget has the wrong ancestor RenderObjectWidget. '
|
||||||
'Typically, $runtimeType widgets are placed directly inside $debugTypicalAncestorWidgetClass widgets.',
|
'Typically, $runtimeType widgets are placed directly inside $debugTypicalAncestorWidgetClass widgets.',
|
||||||
);
|
),
|
||||||
if (parentDataCreator != null) {
|
if (parentDataCreator != null)
|
||||||
yield ErrorHint(
|
ErrorHint(
|
||||||
'The offending $runtimeType is currently placed inside a ${parentDataCreator.runtimeType} widget.',
|
'The offending $runtimeType is currently placed inside a ${parentDataCreator.runtimeType} widget.',
|
||||||
);
|
),
|
||||||
}
|
if (ownershipChain != null)
|
||||||
if (ownershipChain != null) {
|
ErrorDescription(
|
||||||
yield ErrorDescription(
|
'The ownership chain for the RenderObject that received the incompatible parent data was:\n $ownershipChain',
|
||||||
'The ownership chain for the RenderObject that received the incompatible parent data was:\n $ownershipChain',
|
),
|
||||||
);
|
];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the data from this widget into the given render object's parent data.
|
/// Write the data from this widget into the given render object's parent data.
|
||||||
@ -2630,14 +2629,14 @@ class BuildOwner {
|
|||||||
ErrorDescription('while rebuilding dirty elements'),
|
ErrorDescription('while rebuilding dirty elements'),
|
||||||
e,
|
e,
|
||||||
stack,
|
stack,
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
if (index < _dirtyElements.length) {
|
if (kDebugMode && index < _dirtyElements.length)
|
||||||
yield DiagnosticsDebugCreator(DebugCreator(element));
|
DiagnosticsDebugCreator(DebugCreator(element)),
|
||||||
yield element.describeElement('The element being rebuilt at the time was index $index of $dirtyCount');
|
if (index < _dirtyElements.length)
|
||||||
} else {
|
element.describeElement('The element being rebuilt at the time was index $index of $dirtyCount')
|
||||||
yield ErrorHint('The element being rebuilt at the time was index $index of $dirtyCount, but _dirtyElements only had ${_dirtyElements.length} entries. This suggests some confusion in the framework internals.');
|
else
|
||||||
}
|
ErrorHint('The element being rebuilt at the time was index $index of $dirtyCount, but _dirtyElements only had ${_dirtyElements.length} entries. This suggests some confusion in the framework internals.'),
|
||||||
},
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!kReleaseMode && debugProfileBuildsEnabled)
|
if (!kReleaseMode && debugProfileBuildsEnabled)
|
||||||
@ -4721,9 +4720,10 @@ abstract class ComponentElement extends Element {
|
|||||||
ErrorDescription('building $this'),
|
ErrorDescription('building $this'),
|
||||||
e,
|
e,
|
||||||
stack,
|
stack,
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsDebugCreator(DebugCreator(this));
|
if (kDebugMode)
|
||||||
},
|
DiagnosticsDebugCreator(DebugCreator(this)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
@ -4741,9 +4741,10 @@ abstract class ComponentElement extends Element {
|
|||||||
ErrorDescription('building $this'),
|
ErrorDescription('building $this'),
|
||||||
e,
|
e,
|
||||||
stack,
|
stack,
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsDebugCreator(DebugCreator(this));
|
if (kDebugMode)
|
||||||
},
|
DiagnosticsDebugCreator(DebugCreator(this)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
_child = updateChild(null, built, slot);
|
_child = updateChild(null, built, slot);
|
||||||
|
@ -127,9 +127,10 @@ class _LayoutBuilderElement<ConstraintType extends Constraints> extends RenderOb
|
|||||||
ErrorDescription('building $widget'),
|
ErrorDescription('building $widget'),
|
||||||
e,
|
e,
|
||||||
stack,
|
stack,
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsDebugCreator(DebugCreator(this));
|
if (kDebugMode)
|
||||||
},
|
DiagnosticsDebugCreator(DebugCreator(this)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -142,9 +143,10 @@ class _LayoutBuilderElement<ConstraintType extends Constraints> extends RenderOb
|
|||||||
ErrorDescription('building $widget'),
|
ErrorDescription('building $widget'),
|
||||||
e,
|
e,
|
||||||
stack,
|
stack,
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsDebugCreator(DebugCreator(this));
|
if (kDebugMode)
|
||||||
},
|
DiagnosticsDebugCreator(DebugCreator(this)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
_child = updateChild(null, built, slot);
|
_child = updateChild(null, built, slot);
|
||||||
|
@ -3515,9 +3515,11 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
|
|||||||
/// The overlay this navigator uses for its visual presentation.
|
/// The overlay this navigator uses for its visual presentation.
|
||||||
OverlayState? get overlay => _overlayKey.currentState;
|
OverlayState? get overlay => _overlayKey.currentState;
|
||||||
|
|
||||||
Iterable<OverlayEntry> get _allRouteOverlayEntries sync* {
|
Iterable<OverlayEntry> get _allRouteOverlayEntries {
|
||||||
for (final _RouteEntry entry in _history)
|
return <OverlayEntry>[
|
||||||
yield* entry.route.overlayEntries;
|
for (final _RouteEntry entry in _history)
|
||||||
|
...entry.route.overlayEntries,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
String? _lastAnnouncedRouteName;
|
String? _lastAnnouncedRouteName;
|
||||||
|
@ -1133,9 +1133,9 @@ class _NestedScrollController extends ScrollController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<_NestedScrollPosition> get nestedPositions sync* {
|
Iterable<_NestedScrollPosition> get nestedPositions {
|
||||||
// TODO(vegorov): use instance method version of castFrom when it is available.
|
// TODO(vegorov): use instance method version of castFrom when it is available.
|
||||||
yield* Iterable.castFrom<ScrollPosition, _NestedScrollPosition>(positions);
|
return Iterable.castFrom<ScrollPosition, _NestedScrollPosition>(positions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,13 +809,13 @@ class _CallbackHookProvider<T> {
|
|||||||
stack: stack,
|
stack: stack,
|
||||||
library: 'widget library',
|
library: 'widget library',
|
||||||
context: ErrorDescription('while invoking the callback for $runtimeType'),
|
context: ErrorDescription('while invoking the callback for $runtimeType'),
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<_CallbackHookProvider<T>>(
|
DiagnosticsProperty<_CallbackHookProvider<T>>(
|
||||||
'The $runtimeType that invoked the callback was',
|
'The $runtimeType that invoked the callback was',
|
||||||
this,
|
this,
|
||||||
style: DiagnosticsTreeStyle.errorProperty,
|
style: DiagnosticsTreeStyle.errorProperty,
|
||||||
);
|
),
|
||||||
},
|
],
|
||||||
));
|
));
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
@ -1634,9 +1634,11 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
|
|||||||
late OverlayEntry _modalScope;
|
late OverlayEntry _modalScope;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<OverlayEntry> createOverlayEntries() sync* {
|
Iterable<OverlayEntry> createOverlayEntries() {
|
||||||
yield _modalBarrier = OverlayEntry(builder: _buildModalBarrier);
|
return <OverlayEntry>[
|
||||||
yield _modalScope = OverlayEntry(builder: _buildModalScope, maintainState: maintainState);
|
_modalBarrier = OverlayEntry(builder: _buildModalBarrier),
|
||||||
|
_modalScope = OverlayEntry(builder: _buildModalScope, maintainState: maintainState),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -139,13 +139,13 @@ class ScrollNotificationObserverState extends State<ScrollNotificationObserver>
|
|||||||
stack: stack,
|
stack: stack,
|
||||||
library: 'widget library',
|
library: 'widget library',
|
||||||
context: ErrorDescription('while dispatching notifications for $runtimeType'),
|
context: ErrorDescription('while dispatching notifications for $runtimeType'),
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsProperty<ScrollNotificationObserverState>(
|
DiagnosticsProperty<ScrollNotificationObserverState>(
|
||||||
'The $runtimeType sending notification was',
|
'The $runtimeType sending notification was',
|
||||||
this,
|
this,
|
||||||
style: DiagnosticsTreeStyle.errorProperty,
|
style: DiagnosticsTreeStyle.errorProperty,
|
||||||
);
|
),
|
||||||
},
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,8 +483,8 @@ class SingleActivator with Diagnosticable implements ShortcutActivator {
|
|||||||
final bool meta;
|
final bool meta;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<LogicalKeyboardKey> get triggers sync* {
|
Iterable<LogicalKeyboardKey> get triggers {
|
||||||
yield trigger;
|
return <LogicalKeyboardKey>[trigger];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -2916,9 +2916,9 @@ bool _isDebugCreator(DiagnosticsNode node) => node is DiagnosticsDebugCreator;
|
|||||||
/// in [WidgetsBinding.initInstances].
|
/// in [WidgetsBinding.initInstances].
|
||||||
///
|
///
|
||||||
/// This is meant to be called only in debug mode. In other modes, it yields an empty list.
|
/// This is meant to be called only in debug mode. In other modes, it yields an empty list.
|
||||||
Iterable<DiagnosticsNode> debugTransformDebugCreator(Iterable<DiagnosticsNode> properties) sync* {
|
Iterable<DiagnosticsNode> debugTransformDebugCreator(Iterable<DiagnosticsNode> properties) {
|
||||||
if (!kDebugMode) {
|
if (!kDebugMode) {
|
||||||
return;
|
return <DiagnosticsNode>[];
|
||||||
}
|
}
|
||||||
final List<DiagnosticsNode> pending = <DiagnosticsNode>[];
|
final List<DiagnosticsNode> pending = <DiagnosticsNode>[];
|
||||||
ErrorSummary? errorSummary;
|
ErrorSummary? errorSummary;
|
||||||
@ -2929,20 +2929,22 @@ Iterable<DiagnosticsNode> debugTransformDebugCreator(Iterable<DiagnosticsNode> p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool foundStackTrace = false;
|
bool foundStackTrace = false;
|
||||||
|
final List<DiagnosticsNode> result = <DiagnosticsNode>[];
|
||||||
for (final DiagnosticsNode node in properties) {
|
for (final DiagnosticsNode node in properties) {
|
||||||
if (!foundStackTrace && node is DiagnosticsStackTrace)
|
if (!foundStackTrace && node is DiagnosticsStackTrace)
|
||||||
foundStackTrace = true;
|
foundStackTrace = true;
|
||||||
if (_isDebugCreator(node)) {
|
if (_isDebugCreator(node)) {
|
||||||
yield* _parseDiagnosticsNode(node, errorSummary);
|
result.addAll(_parseDiagnosticsNode(node, errorSummary));
|
||||||
} else {
|
} else {
|
||||||
if (foundStackTrace) {
|
if (foundStackTrace) {
|
||||||
pending.add(node);
|
pending.add(node);
|
||||||
} else {
|
} else {
|
||||||
yield node;
|
result.add(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield* pending;
|
result.addAll(pending);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transform the input [DiagnosticsNode].
|
/// Transform the input [DiagnosticsNode].
|
||||||
@ -2951,23 +2953,24 @@ Iterable<DiagnosticsNode> debugTransformDebugCreator(Iterable<DiagnosticsNode> p
|
|||||||
Iterable<DiagnosticsNode> _parseDiagnosticsNode(
|
Iterable<DiagnosticsNode> _parseDiagnosticsNode(
|
||||||
DiagnosticsNode node,
|
DiagnosticsNode node,
|
||||||
ErrorSummary? errorSummary,
|
ErrorSummary? errorSummary,
|
||||||
) sync* {
|
) {
|
||||||
assert(_isDebugCreator(node));
|
assert(_isDebugCreator(node));
|
||||||
try {
|
try {
|
||||||
final DebugCreator debugCreator = node.value! as DebugCreator;
|
final DebugCreator debugCreator = node.value! as DebugCreator;
|
||||||
final Element element = debugCreator.element;
|
final Element element = debugCreator.element;
|
||||||
yield* _describeRelevantUserCode(element, errorSummary);
|
return _describeRelevantUserCode(element, errorSummary);
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
scheduleMicrotask(() {
|
scheduleMicrotask(() {
|
||||||
FlutterError.reportError(FlutterErrorDetails(
|
FlutterError.reportError(FlutterErrorDetails(
|
||||||
exception: error,
|
exception: error,
|
||||||
stack: stack,
|
stack: stack,
|
||||||
library: 'widget inspector',
|
library: 'widget inspector',
|
||||||
informationCollector: () sync* {
|
informationCollector: () => <DiagnosticsNode>[
|
||||||
yield DiagnosticsNode.message('This exception was caught while trying to describe the user-relevant code of another error.');
|
DiagnosticsNode.message('This exception was caught while trying to describe the user-relevant code of another error.'),
|
||||||
}
|
],
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
return <DiagnosticsNode>[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,6 +379,11 @@ void main() {
|
|||||||
expect(output, isEmpty);
|
expect(output, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('ListTile.divideTiles with single item list', (WidgetTester tester) async {
|
||||||
|
final Iterable<Widget> output = ListTile.divideTiles(tiles: const <Widget>[SizedBox()], color: Colors.grey);
|
||||||
|
expect(output.single, isA<SizedBox>());
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('ListTile.divideTiles only runs the generator once', (WidgetTester tester) async {
|
testWidgets('ListTile.divideTiles only runs the generator once', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/pull/78879
|
// Regression test for https://github.com/flutter/flutter/pull/78879
|
||||||
int callCount = 0;
|
int callCount = 0;
|
||||||
|
@ -740,26 +740,22 @@ class PubspecYaml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This returns all the explicit dependencies that this pubspec.yaml lists under dependencies.
|
/// This returns all the explicit dependencies that this pubspec.yaml lists under dependencies.
|
||||||
Iterable<PubspecDependency> get dependencies sync* {
|
Iterable<PubspecDependency> get dependencies {
|
||||||
// It works by iterating over the parsed data from _parse above, collecting
|
// It works by iterating over the parsed data from _parse above, collecting
|
||||||
// all the dependencies that were found, ignoring any that are flagged as as
|
// all the dependencies that were found, ignoring any that are flagged as as
|
||||||
// overridden by subsequent entries in the same file and any that have the
|
// overridden by subsequent entries in the same file and any that have the
|
||||||
// magic comment flagging them as auto-generated transitive dependencies
|
// magic comment flagging them as auto-generated transitive dependencies
|
||||||
// that we added in a previous run.
|
// that we added in a previous run.
|
||||||
for (final PubspecLine data in inputData) {
|
return inputData
|
||||||
if (data is PubspecDependency && data.kind != DependencyKind.overridden && !data.isTransitive && !data.isDevDependency) {
|
.whereType<PubspecDependency>()
|
||||||
yield data;
|
.where((PubspecDependency data) => data.kind != DependencyKind.overridden && !data.isTransitive && !data.isDevDependency);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This returns all regular dependencies and all dev dependencies.
|
/// This returns all regular dependencies and all dev dependencies.
|
||||||
Iterable<PubspecDependency> get allDependencies sync* {
|
Iterable<PubspecDependency> get allDependencies {
|
||||||
for (final PubspecLine data in inputData) {
|
return inputData
|
||||||
if (data is PubspecDependency && data.kind != DependencyKind.overridden && !data.isTransitive) {
|
.whereType<PubspecDependency>()
|
||||||
yield data;
|
.where((PubspecDependency data) => data.kind != DependencyKind.overridden && !data.isTransitive);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take a dependency graph with explicit version numbers, and apply them to
|
/// Take a dependency graph with explicit version numbers, and apply them to
|
||||||
@ -1412,23 +1408,26 @@ class PubDependencyTree {
|
|||||||
String package, {
|
String package, {
|
||||||
@required Set<String> seen,
|
@required Set<String> seen,
|
||||||
@required Set<String> exclude,
|
@required Set<String> exclude,
|
||||||
}) sync* {
|
List<String>/*?*/ result,
|
||||||
|
}) {
|
||||||
assert(seen != null);
|
assert(seen != null);
|
||||||
assert(exclude != null);
|
assert(exclude != null);
|
||||||
|
result ??= <String>[];
|
||||||
if (!_dependencyTree.containsKey(package)) {
|
if (!_dependencyTree.containsKey(package)) {
|
||||||
// We have no transitive dependencies extracted for flutter_sdk packages
|
// We have no transitive dependencies extracted for flutter_sdk packages
|
||||||
// because they were omitted from pubspec.yaml used for 'pub upgrade' run.
|
// because they were omitted from pubspec.yaml used for 'pub upgrade' run.
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
for (final String dependency in _dependencyTree[package]) {
|
for (final String dependency in _dependencyTree[package]) {
|
||||||
if (!seen.contains(dependency)) {
|
if (!seen.contains(dependency)) {
|
||||||
if (!exclude.contains(dependency)) {
|
if (!exclude.contains(dependency)) {
|
||||||
yield dependency;
|
result.add(dependency);
|
||||||
}
|
}
|
||||||
seen.add(dependency);
|
seen.add(dependency);
|
||||||
yield* getTransitiveDependenciesFor(dependency, seen: seen, exclude: exclude);
|
getTransitiveDependenciesFor(dependency, seen: seen, exclude: exclude, result: result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The version that a particular package ended up with.
|
/// The version that a particular package ended up with.
|
||||||
|
@ -635,9 +635,9 @@ abstract class Device {
|
|||||||
@override
|
@override
|
||||||
String toString() => name;
|
String toString() => name;
|
||||||
|
|
||||||
static Stream<String> descriptions(List<Device> devices) async* {
|
static Future<List<String>> descriptions(List<Device> devices) async {
|
||||||
if (devices.isEmpty) {
|
if (devices.isEmpty) {
|
||||||
return;
|
return const <String>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract device information
|
// Extract device information
|
||||||
@ -665,13 +665,14 @@ abstract class Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Join columns into lines of text
|
// Join columns into lines of text
|
||||||
for (final List<String> row in table) {
|
return <String>[
|
||||||
yield indices.map<String>((int i) => row[i].padRight(widths[i])).followedBy(<String>[row.last]).join(' • ');
|
for (final List<String> row in table)
|
||||||
}
|
indices.map<String>((int i) => row[i].padRight(widths[i])).followedBy(<String>[row.last]).join(' • '),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> printDevices(List<Device> devices, Logger logger) async {
|
static Future<void> printDevices(List<Device> devices, Logger logger) async {
|
||||||
await descriptions(devices).forEach(logger.printStatus);
|
(await descriptions(devices)).forEach(logger.printStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<String> devicesPlatformTypes(List<Device> devices) {
|
static List<String> devicesPlatformTypes(List<Device> devices) {
|
||||||
|
@ -520,7 +520,7 @@ class DeviceValidator extends DoctorValidator {
|
|||||||
final List<Device> devices = await _deviceManager.getAllConnectedDevices();
|
final List<Device> devices = await _deviceManager.getAllConnectedDevices();
|
||||||
List<ValidationMessage> installedMessages = <ValidationMessage>[];
|
List<ValidationMessage> installedMessages = <ValidationMessage>[];
|
||||||
if (devices.isNotEmpty) {
|
if (devices.isNotEmpty) {
|
||||||
installedMessages = await Device.descriptions(devices)
|
installedMessages = (await Device.descriptions(devices))
|
||||||
.map<ValidationMessage>((String msg) => ValidationMessage(msg)).toList();
|
.map<ValidationMessage>((String msg) => ValidationMessage(msg)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1372,7 +1372,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
final StringBuffer result = StringBuffer();
|
final StringBuffer result = StringBuffer();
|
||||||
result.writeln(userMessages.flutterFoundButUnsupportedDevices);
|
result.writeln(userMessages.flutterFoundButUnsupportedDevices);
|
||||||
result.writeAll(
|
result.writeAll(
|
||||||
await Device.descriptions(unsupportedDevices)
|
(await Device.descriptions(unsupportedDevices))
|
||||||
.map((String desc) => desc)
|
.map((String desc) => desc)
|
||||||
.toList(),
|
.toList(),
|
||||||
'\n',
|
'\n',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user