Skip to content
This repository was archived by the owner on Jul 16, 2023. It is now read-only.

fix: ignore Providers for avoid-returning-widgets #1121

Merged
merged 2 commits into from
Dec 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

## Unreleased

* feat: add [`use-setstate-synchronously`](https://dartcodemetrics.dev/docs/rules/flutter/use-setstate-synchronously)
* fix: ignore Providers for ['avoid-returning-widgets'](https://dartcodemetrics.dev/docs/rules/common/avoid-returning-widgets).
* feat: add [`use-setstate-synchronously`](https://dartcodemetrics.dev/docs/rules/flutter/use-setstate-synchronously).

## 5.3.0

Expand Down
40 changes: 36 additions & 4 deletions lib/src/utils/flutter_types_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import 'package:analyzer/dart/element/type.dart';
import 'package:collection/collection.dart';

bool hasWidgetType(DartType type) =>
isWidgetOrSubclass(type) ||
_isIterable(type) ||
_isList(type) ||
_isFuture(type);
(isWidgetOrSubclass(type) ||
_isIterable(type) ||
_isList(type) ||
_isFuture(type)) &&
!(_isMultiProvider(type) ||
_isSubclassOfInheritedProvider(type) ||
_isIterableInheritedProvider(type) ||
_isListInheritedProvider(type) ||
_isFutureInheritedProvider(type));

bool isWidgetOrSubclass(DartType? type) =>
_isWidget(type) || _isSubclassOfWidget(type);
Expand Down Expand Up @@ -92,3 +97,30 @@ bool _isRenderObjectElement(DartType? type) =>

bool _isSubclassOfRenderObjectElement(DartType? type) =>
type is InterfaceType && type.allSupertypes.any(_isRenderObjectElement);

bool _isMultiProvider(DartType? type) =>
type?.getDisplayString(withNullability: false) == 'MultiProvider';

bool _isSubclassOfInheritedProvider(DartType? type) =>
type is InterfaceType && type.allSupertypes.any(_isInheritedProvider);

bool _isInheritedProvider(DartType? type) =>
type != null &&
type
.getDisplayString(withNullability: false)
.startsWith('InheritedProvider<');

bool _isIterableInheritedProvider(DartType type) =>
type.isDartCoreIterable &&
type is InterfaceType &&
_isSubclassOfInheritedProvider(type.typeArguments.firstOrNull);

bool _isListInheritedProvider(DartType type) =>
type.isDartCoreList &&
type is InterfaceType &&
_isSubclassOfInheritedProvider(type.typeArguments.firstOrNull);

bool _isFutureInheritedProvider(DartType type) =>
type.isDartAsyncFuture &&
type is InterfaceType &&
_isSubclassOfInheritedProvider(type.typeArguments.firstOrNull);
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import '../../../../../helpers/rule_test_helper.dart';
const _examplePath = 'avoid_returning_widgets/examples/example.dart';
const _notNamedParameterExamplePath =
'avoid_returning_widgets/examples/not_named_parameter_example.dart';
const _providerExamplePath =
'avoid_returning_widgets/examples/provider_example.dart';

void main() {
group('AvoidReturningWidgetsRule', () {
Expand Down Expand Up @@ -113,5 +115,12 @@ void main() {

RuleTestHelper.verifyNoIssues(issues);
});

test('reports no issues for providers', () async {
final unit = await RuleTestHelper.resolveFromFile(_providerExamplePath);
final issues = AvoidReturningWidgetsRule().check(unit);

RuleTestHelper.verifyNoIssues(issues);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class MyWidget extends StatelessWidget {
List<Provider> _getProvidersList() => [Provider()];

MultiProvider _getMultiProvider() => MultiProvider(providers: []);

@override
Widget build(BuildContext context) {
_getProvidersList();

_getMultiProvider();

return Container();
}
}

class StatelessWidget extends Widget {}

class Widget {}

class Container extends Widget {
final Widget? child;

const Container({this.child});
}

class MultiProvider {
final List<Widget> providers;

const MultiProvider({required this.providers});
}

class Provider<T> extends InheritedProvider<T> {
final Widget? child;

const Provider(this.child);
}

class InheritedProvider<T> extends Widget {}