@@ -315,6 +315,7 @@ class AddHapticFeedbackOnUserInteractionRule extends _SolvroRule {
315315 RuleContext context,
316316 ) {
317317 final hapticWrappers = _configuredHapticWrappers (context);
318+ final hapticOwningWidgets = _configuredHapticOwningWidgets (context);
318319
319320 registry.addNamedExpression (
320321 this ,
@@ -326,6 +327,11 @@ class AddHapticFeedbackOnUserInteractionRule extends _SolvroRule {
326327 }.contains (node.name.label.name)) {
327328 return ;
328329 }
330+
331+ if (_isCallbackInHapticOwningWidget (node, hapticOwningWidgets)) {
332+ return ;
333+ }
334+
329335 final source = node.expression.toString ();
330336 if (! hapticWrappers.any (source.contains)) {
331337 reportAtNode (node);
@@ -334,28 +340,66 @@ class AddHapticFeedbackOnUserInteractionRule extends _SolvroRule {
334340 );
335341 }
336342
343+ static bool _isCallbackInHapticOwningWidget (
344+ NamedExpression node,
345+ List <String > hapticOwningWidgets,
346+ ) {
347+ final argumentList = node.parent;
348+ final creation = argumentList? .parent;
349+ if (argumentList is ! ArgumentList ||
350+ creation is ! InstanceCreationExpression ) {
351+ return false ;
352+ }
353+
354+ final widgetName = creation.constructorName.type.name.lexeme;
355+ return hapticOwningWidgets.contains (widgetName);
356+ }
357+
337358 static List <String > _configuredHapticWrappers (RuleContext context) {
359+ return _configuredStrings (
360+ context,
361+ singularName: "haptic_wrapper" ,
362+ pluralName: "haptic_wrappers" ,
363+ defaultValues: _defaultHapticWrappers,
364+ );
365+ }
366+
367+ static List <String > _configuredHapticOwningWidgets (RuleContext context) {
368+ return _configuredStrings (
369+ context,
370+ singularName: "haptic_owning_widget" ,
371+ pluralName: "haptic_owning_widgets" ,
372+ defaultValues: const [],
373+ );
374+ }
375+
376+ static List <String > _configuredStrings (
377+ RuleContext context, {
378+ required String singularName,
379+ required String pluralName,
380+ required List <String > defaultValues,
381+ }) {
338382 final package = context.package;
339383 if (package == null ) {
340- return _defaultHapticWrappers ;
384+ return defaultValues ;
341385 }
342386
343387 final optionsFile = package.root.getChildAssumingFile (
344388 "analysis_options.yaml" ,
345389 );
346390 if (! optionsFile.exists) {
347- return _defaultHapticWrappers ;
391+ return defaultValues ;
348392 }
349393
350394 try {
351395 final options = loadYamlNode (optionsFile.readAsStringSync ());
352396 if (options is ! YamlMap ) {
353- return _defaultHapticWrappers ;
397+ return defaultValues ;
354398 }
355399
356400 final plugins = options["plugins" ];
357401 if (plugins is ! YamlMap ) {
358- return _defaultHapticWrappers ;
402+ return defaultValues ;
359403 }
360404
361405 for (final pluginName in ["solvro_config" , "solvro_custom_linter" ]) {
@@ -364,33 +408,36 @@ class AddHapticFeedbackOnUserInteractionRule extends _SolvroRule {
364408 continue ;
365409 }
366410
367- final wrappers = < String > [];
368- _addConfiguredWrappers (wrappers , pluginConfig["haptic_wrapper" ]);
369- _addConfiguredWrappers (wrappers , pluginConfig["haptic_wrappers" ]);
411+ final configuredStrings = < String > [];
412+ _addConfiguredStrings (configuredStrings , pluginConfig[singularName ]);
413+ _addConfiguredStrings (configuredStrings , pluginConfig[pluralName ]);
370414
371- if (wrappers .isNotEmpty) {
372- return wrappers ;
415+ if (configuredStrings .isNotEmpty) {
416+ return configuredStrings ;
373417 }
374418 }
375419 } on YamlException {
376- return _defaultHapticWrappers ;
420+ return defaultValues ;
377421 } on Exception {
378- return _defaultHapticWrappers ;
422+ return defaultValues ;
379423 }
380424
381- return _defaultHapticWrappers ;
425+ return defaultValues ;
382426 }
383427
384- static void _addConfiguredWrappers (List <String > wrappers, Object ? value) {
428+ static void _addConfiguredStrings (
429+ List <String > configuredStrings,
430+ Object ? value,
431+ ) {
385432 if (value is String && value.isNotEmpty) {
386- wrappers .add (value);
433+ configuredStrings .add (value);
387434 return ;
388435 }
389436
390437 if (value is YamlList ) {
391438 for (final item in value) {
392439 if (item is String && item.isNotEmpty) {
393- wrappers .add (item);
440+ configuredStrings .add (item);
394441 }
395442 }
396443 }
0 commit comments