diff --git a/tools/analyzer_plugin/lib/src/util/prop_declarations/get_all_props.dart b/tools/analyzer_plugin/lib/src/util/prop_declarations/get_all_props.dart index 9933ed06f..28c48c966 100644 --- a/tools/analyzer_plugin/lib/src/util/prop_declarations/get_all_props.dart +++ b/tools/analyzer_plugin/lib/src/util/prop_declarations/get_all_props.dart @@ -52,7 +52,7 @@ List getAllProps(InterfaceElement propsElement) { final isMixinBasedPropsMixin = interface is MixinElement && interface.superclassConstraints.any((s) => s.element.name == 'UiProps'); late final isLegacyPropsOrPropsMixinConsumerClass = - !isFromGeneratedFile && interface.metadata.any(_isPropsOrPropsMixinAnnotation); + !isFromGeneratedFile && interface.metadata.any(_isOneOfThePropsAnnotations); if (!isMixinBasedPropsMixin && !isLegacyPropsOrPropsMixinConsumerClass) { continue; @@ -74,10 +74,11 @@ List getAllProps(InterfaceElement propsElement) { return allProps; } -bool _isPropsOrPropsMixinAnnotation(ElementAnnotation e) { +bool _isOneOfThePropsAnnotations(ElementAnnotation e) { // [2] final element = e.element; - return element is ConstructorElement && const {'Props', 'PropsMixin'}.contains(element.enclosingElement.name); + return element is ConstructorElement && + const {'Props', 'PropsMixin', 'AbstractProps'}.contains(element.enclosingElement.name); } bool _isPropsMixinAnnotation(ElementAnnotation e) { diff --git a/tools/analyzer_plugin/test/unit/util/prop_declaration/get_all_props_test.dart b/tools/analyzer_plugin/test/unit/util/prop_declaration/get_all_props_test.dart index 71b08afa8..9ee5f879d 100644 --- a/tools/analyzer_plugin/test/unit/util/prop_declaration/get_all_props_test.dart +++ b/tools/analyzer_plugin/test/unit/util/prop_declaration/get_all_props_test.dart @@ -56,6 +56,15 @@ void main() { ]); }); + test('concrete props class', () { + final propsElement = getInterfaceElement(result, 'V2AbstractProps'); + verifyAllProps(getAllProps(propsElement), expectedNames: [ + 'v2_lateRequiredProp', + 'v2_optionalProp', + 'v2_annotationRequiredProp', + ]); + }); + test('props mixin', () { final propsElement = getInterfaceElement(result, 'V2PropsMixin'); verifyAllProps(getAllProps(propsElement), expectedNames: [ diff --git a/tools/analyzer_plugin/test/unit/util/prop_declaration/required_props_test.dart b/tools/analyzer_plugin/test/unit/util/prop_declaration/required_props_test.dart index 561ed09e1..815d7ba4f 100644 --- a/tools/analyzer_plugin/test/unit/util/prop_declaration/required_props_test.dart +++ b/tools/analyzer_plugin/test/unit/util/prop_declaration/required_props_test.dart @@ -215,6 +215,15 @@ void main() { }); }); + test('abstract props class', () { + final propsElement = getInterfaceElement(result, 'V2Props'); + verifyRequiredProps(getAllRequiredProps(propsElement), expected: { + 'v2_lateRequiredProp': PropRequiredness.late, + 'v2_optionalProp': PropRequiredness.none, + 'v2_annotationRequiredProp': PropRequiredness.annotation, + }); + }); + test('props mixin', () { final propsElement = getInterfaceElement(result, 'V2PropsMixin'); verifyRequiredProps(getAllRequiredProps(propsElement), expected: { diff --git a/tools/analyzer_plugin/test/unit/util/prop_declaration/shared_test_source.dart b/tools/analyzer_plugin/test/unit/util/prop_declaration/shared_test_source.dart index 296ca216e..50c29ff39 100644 --- a/tools/analyzer_plugin/test/unit/util/prop_declaration/shared_test_source.dart +++ b/tools/analyzer_plugin/test/unit/util/prop_declaration/shared_test_source.dart @@ -67,6 +67,52 @@ class V2Component extends UiComponent2 { render() {} } +// ignore: undefined_class, mixin_of_non_class +abstract class V2AbstractProps extends _$V2AbstractProps with _$V2AbstractPropsAccessorsMixin { + // ignore: undefined_identifier, const_initialized_with_non_constant_value, invalid_assignment + static const PropsMeta meta = _$metaForV2AbstractProps; +} + +@AbstractProps() +// ignore: mixin_of_non_class,undefined_class +abstract class _$V2AbstractProps extends UiProps { + late String v2_lateRequiredProp; + String? v2_optionalProp; + @requiredProp + String? v2_annotationRequiredProp; + + // + // Non-props: edge-cases + // + @Accessor(doNotGenerate: true) + String? v2_doNotGenerate; + + // + // Non-props: instance members + // + String get v2_getter => ''; + // ignore: avoid_setters_without_getters + set v2_setter(_) => ''; + String get v2_getterAndSetter => ''; + set v2_getterAndSetter(String _) {} + + // + // Non-props: static members + // + static String v2_static_field = ''; + static String get v2_static_getter => ''; + // ignore: avoid_setters_without_getters + static set v2_static_setter(_) => ''; + static String get v2_static_getterAndSetter => ''; + static set v2_static_getterAndSetter(String _) {} +} + +@AbstractComponent() +abstract class V2AbstractComponent extends UiComponent2 { + @override + render() {} +} + @Factory() UiFactory V3 = castUiFactory(_$V3);