From 4a4bca6c4e58c59c9c0bb2ca2cdf91ed0a87b65e Mon Sep 17 00:00:00 2001 From: pq Date: Wed, 25 Jan 2023 22:23:27 +0000 Subject: [PATCH] element support for `@reopen` See: https://github.com/dart-lang/linter/issues/3917 Change-Id: I9652fabcbac37644cfca89227b6830e32a79576d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279657 Reviewed-by: Brian Wilkerson Commit-Queue: Phil Quitslund --- pkg/analyzer/lib/dart/element/element.dart | 7 ++++++ .../lib/src/dart/element/element.dart | 22 +++++++++++++++++++ pkg/analyzer/lib/src/dart/element/member.dart | 3 +++ .../lib/src/test_utilities/mock_packages.dart | 10 +++++++++ 4 files changed, 42 insertions(+) diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart index a37bcffa32e..d47decca51f 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 2acbd85687f..8d0f2e27457 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 e46a7ebfe94..a537763f7f7 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 d6c64beff70..6dd9139d13a 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;