diff --git a/lib/lints/no_magic_number/no_magic_number_rule.dart b/lib/lints/no_magic_number/no_magic_number_rule.dart index be55635b..693ace70 100644 --- a/lib/lints/no_magic_number/no_magic_number_rule.dart +++ b/lib/lints/no_magic_number/no_magic_number_rule.dart @@ -22,7 +22,9 @@ // SOFTWARE. import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/listener.dart'; +import 'package:collection/collection.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; import 'package:solid_lints/lints/no_magic_number/models/no_magic_number_parameters.dart'; import 'package:solid_lints/lints/no_magic_number/no_magic_number_visitor.dart'; @@ -71,7 +73,8 @@ class NoMagicNumberRule extends SolidLintRule { .where(_isNotInsideIndexExpression) .where(_isNotInsideEnumConstantArguments) .where(_isNotDefaultValue) - .where(_isNotInConstructorInitializer); + .where(_isNotInConstructorInitializer) + .where(_isNotWidgetParameter); for (final magicNumber in magicNumbers) { reporter.reportErrorForNode(code, magicNumber); @@ -132,4 +135,22 @@ class NoMagicNumberRule extends SolidLintRule { bool _isNotInConstructorInitializer(Literal literal) { return literal.thisOrAncestorOfType() == null; } + + bool _isNotWidgetParameter(Literal literal) { + final instanceCreationExpression = + literal.thisOrAncestorOfType(); + + if (instanceCreationExpression == null) return true; + + final staticType = instanceCreationExpression.staticType; + + if (staticType is! InterfaceType) return true; + + final widgetSupertype = staticType.allSupertypes.firstWhereOrNull( + (supertype) => + supertype.getDisplayString(withNullability: false) == 'Widget', + ); + + return widgetSupertype == null; + } } diff --git a/lint_test/no_magic_number_test.dart b/lint_test/no_magic_number_test.dart index 454ca326..0d6df357 100644 --- a/lint_test/no_magic_number_test.dart +++ b/lint_test/no_magic_number_test.dart @@ -86,3 +86,18 @@ class ConstructorInitializer { ConstructorInitializer() : value = 10; } + +// Allowed for numbers in a Widget subtype parameters. +abstract interface class Widget {} + +class StatelessWidget implements Widget {} + +class MyWidget extends StatelessWidget { + final int size; + + MyWidget({required this.size}); +} + +Widget build() { + return MyWidget(size: 12); +}