From dd671fae53d37eb15e0f8fc94cd52c2f2ff147ee Mon Sep 17 00:00:00 2001 From: Muhammad Kamel Date: Wed, 21 May 2025 18:33:24 +0300 Subject: [PATCH] fix(widget_inspector): add null check for flex factor property to prevent exception (#167890) Null check exception appears while opening Widget Inspector as the attached screenshots and video. ![null_check_flex_factor](https://github.com/user-attachments/assets/325ee0b6-7c95-40bf-a717-e6eb354f9ad6) https://github.com/user-attachments/assets/a250765a-0bb4-4b45-9451-db4b51347ca2 ## Pre-launch Checklist - [X] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [X] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [X] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [X] I signed the [CLA]. - [X] I listed at least one issue that this PR fixes in the description above. - [X] I updated/added relevant documentation (doc comments with `///`). - [X] I added new tests to check the change I am making, or this PR is [test-exempt]. - [X] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [X] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Ben Konyi --- .../lib/src/widgets/widget_inspector.dart | 2 +- .../test/widgets/widget_inspector_test.dart | 40 ++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/flutter/lib/src/widgets/widget_inspector.dart b/packages/flutter/lib/src/widgets/widget_inspector.dart index f525b4fcdd5..91515815a38 100644 --- a/packages/flutter/lib/src/widgets/widget_inspector.dart +++ b/packages/flutter/lib/src/widgets/widget_inspector.dart @@ -2346,7 +2346,7 @@ mixin WidgetInspectorService { final ParentData? parentData = renderObject.parentData; if (parentData is FlexParentData) { - additionalJson['flexFactor'] = parentData.flex!; + additionalJson['flexFactor'] = parentData.flex ?? 0; additionalJson['flexFit'] = (parentData.fit ?? FlexFit.tight).name; } else if (parentData is BoxParentData) { final Offset offset = parentData.offset; diff --git a/packages/flutter/test/widgets/widget_inspector_test.dart b/packages/flutter/test/widgets/widget_inspector_test.dart index 322417530a1..41588d1e5f5 100644 --- a/packages/flutter/test/widgets/widget_inspector_test.dart +++ b/packages/flutter/test/widgets/widget_inspector_test.dart @@ -5137,6 +5137,44 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { }, ); + testWidgets('getLayoutExplorerNode omits flexFactor when flex is null', ( + WidgetTester tester, + ) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: Row( + children: [ + Align( + alignment: Alignment.topLeft, + child: ColoredBox( + color: Color(0xFF000000), + child: SizedBox(width: 14, height: 14), + ), + ), + ], + ), + ), + ); + + final Element boxElement = tester.element(find.byType(ColoredBox).first); + service.setSelection(boxElement, group); + + final String id = service.toId(boxElement, group)!; + final Map result = + (await service.testExtension( + WidgetInspectorServiceExtensions.getLayoutExplorerNode.name, + {'id': id, 'groupName': group, 'subtreeDepth': '1'}, + ))! + as Map; + + final Map? parentData = result['parentData'] as Map?; + expect(parentData, isNotNull); + expect(parentData!['flexFactor'], isNull); + expect(parentData['flexFit'], isNull); + expect(tester.takeException(), isNull); + }); + testWidgets('ext.flutter.inspector.getLayoutExplorerNode for RenderBox with FlexParentData', ( WidgetTester tester, ) async { @@ -5180,8 +5218,6 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { expect(result['flexFactor'], equals(1)); expect(result['flexFit'], equals('loose')); - - expect(result['parentData'], isNull); }); testWidgets('ext.flutter.inspector.getLayoutExplorerNode for RenderView', (