diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart index a37bcffa32ef..d47decca51f1 100644 --- a/pkg/analyzer/lib/dart/element/element.dart +++ b/pkg/analyzer/lib/dart/element/element.dart @@ -592,6 +592,9 @@ abstract class Element implements AnalysisTarget { /// Return `true` if this element has an annotation of the form `@protected`. bool get hasProtected; + /// Return `true` if this element has an annotation of the form `@reopen`. + bool get hasReopen; + /// Return `true` if this element has an annotation of the form `@required`. bool get hasRequired; @@ -831,6 +834,10 @@ abstract class ElementAnnotation implements ConstantEvaluationTarget { /// implementing a proxy object. bool get isProxy; + /// Return `true` if this annotation marks the associated member as being + /// reopened. + bool get isReopen; + /// Return `true` if this annotation marks the associated member as being /// required. bool get isRequired; diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index 2acbd85687fa..8d0f2e274571 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -1983,6 +1983,10 @@ class ElementAnnotationImpl implements ElementAnnotation { /// protected. static const String _protectedVariableName = 'protected'; + /// The name of the top-level variable used to mark a class or mixin as being + /// reopened. + static const String _reopenVariableName = 'reopen'; + /// The name of the class used to mark a parameter as being required. static const String _requiredClassName = 'Required'; @@ -2119,6 +2123,9 @@ class ElementAnnotationImpl implements ElementAnnotation { @override bool get isProxy => false; + @override + bool get isReopen => _isPackageMetaGetter(_reopenVariableName); + @override bool get isRequired => _isConstructor( @@ -2503,6 +2510,18 @@ abstract class ElementImpl implements Element { return false; } + @override + bool get hasReopen { + final metadata = this.metadata; + for (var i = 0; i < metadata.length; i++) { + var annotation = metadata[i]; + if (annotation.isReopen) { + return true; + } + } + return false; + } + @override bool get hasRequired { final metadata = this.metadata; @@ -5090,6 +5109,9 @@ class MultiplyDefinedElementImpl implements MultiplyDefinedElement { @override bool get hasProtected => false; + @override + bool get hasReopen => false; + @override bool get hasRequired => false; diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart index e46a7ebfe944..a537763f7f74 100644 --- a/pkg/analyzer/lib/src/dart/element/member.dart +++ b/pkg/analyzer/lib/src/dart/element/member.dart @@ -569,6 +569,9 @@ abstract class Member implements Element { @override bool get hasProtected => _declaration.hasProtected; + @override + bool get hasReopen => _declaration.hasReopen; + @override bool get hasRequired => _declaration.hasRequired; diff --git a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart index d6c64beff708..6dd9139d13a3 100644 --- a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart +++ b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart @@ -84,6 +84,8 @@ const _OptionalTypeArgs optionalTypeArgs = _OptionalTypeArgs(); const _Protected protected = _Protected(); +const _Reopen reopen = _Reopen(); + const Required required = Required(); const _Sealed sealed = _Sealed(); @@ -103,6 +105,14 @@ class Immutable { const Immutable([this.reason = '']); } +@Target({ + TargetKind.classType, + TargetKind.mixinType, +}) +class _Reopen { + const _Reopen(); +} + class Required { final String reason;