Skip to content

Commit a2fe6ce

Browse files
srawlinsCommit Queue
authored andcommitted
analyzer: Replace ClassElement.isExtendableIn with getter
For the third use of `ClassElement.isExtendableIn` (https://dart-review.googlesource.com/c/sdk/+/442705), I found that I would have to "make up" an outside library to check. It was suggested that we can change the API to not require the user specify an outside library, but instead we can just answer "is this ClassElement extendable "outside." (Same with `ClassElement.isImplementableIn`, `ClassElement.isMixableIn`, and `MixinElement.isImplementableIn`.) Change-Id: Id03ef622132474ae686daaa5ed5564e979dad8a5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/443628 Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]>
1 parent c562e61 commit a2fe6ce

File tree

6 files changed

+138
-78
lines changed

6 files changed

+138
-78
lines changed

pkg/analysis_server/lib/src/cider/local_library_contributor.dart

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,21 @@ class LibraryElementSuggestionBuilder
6161
@override
6262
void visitClassElement(ClassElement element) {
6363
AstNode node = request.target.containingNode;
64-
var libraryElement = request.libraryElement;
65-
if (node is ExtendsClause && !element.isExtendableIn(libraryElement)) {
66-
return;
67-
} else if (node is ImplementsClause &&
68-
!element.isImplementableIn(libraryElement)) {
69-
return;
70-
} else if (node is WithClause && !element.isMixableIn(libraryElement)) {
71-
return;
64+
if (node is ExtendsClause) {
65+
if (element.library != request.libraryElement &&
66+
!element.isExtendableOutside) {
67+
return;
68+
}
69+
} else if (node is ImplementsClause) {
70+
if (element.library != request.libraryElement &&
71+
!element.isImplementableOutside) {
72+
return;
73+
}
74+
} else if (node is WithClause) {
75+
if (element.library != request.libraryElement &&
76+
!element.isMixableOutside) {
77+
return;
78+
}
7279
}
7380
_visitInterfaceElement(element);
7481
}
@@ -128,7 +135,8 @@ class LibraryElementSuggestionBuilder
128135
visitMixinElement(MixinElement element) {
129136
AstNode node = request.target.containingNode;
130137
if (node is ImplementsClause &&
131-
!element.isImplementableIn(request.libraryElement)) {
138+
request.libraryElement != element.library &&
139+
!element.isImplementableOutside) {
132140
return;
133141
}
134142
_visitInterfaceElement(element);

pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,35 +1741,50 @@ class DeclarationHelper {
17411741

17421742
/// Adds a suggestion for the class represented by the [element].
17431743
void _suggestClass(ClassElement element, ImportData? importData) {
1744-
if (visibilityTracker.isVisible(element: element, importData: importData)) {
1745-
if ((mustBeExtendable &&
1746-
!element.isExtendableIn(request.libraryElement)) ||
1747-
(mustBeImplementable &&
1748-
!element.isImplementableIn(request.libraryElement)) ||
1749-
(mustBeMixable && !element.isMixableIn(request.libraryElement))) {
1744+
if (!visibilityTracker.isVisible(
1745+
element: element,
1746+
importData: importData,
1747+
)) {
1748+
return;
1749+
}
1750+
if (mustBeExtendable) {
1751+
if (request.libraryElement != element.library &&
1752+
!element.isExtendableOutside) {
17501753
return;
17511754
}
1752-
if (!(mustBeConstant && !objectPatternAllowed) && !excludeTypeNames) {
1753-
var matcherScore = state.matcher.score(element.displayName);
1754-
if (matcherScore != -1) {
1755-
var suggestion = ClassSuggestion(
1756-
importData: importData,
1757-
element: element,
1758-
matcherScore: matcherScore,
1759-
);
1760-
collector.addSuggestion(suggestion);
1761-
}
1755+
}
1756+
if (mustBeImplementable) {
1757+
if (request.libraryElement != element.library &&
1758+
!element.isImplementableOutside) {
1759+
return;
17621760
}
1763-
if (!mustBeType) {
1764-
_suggestStaticFields(element.fields, importData);
1765-
_suggestConstructors(
1766-
element.constructors,
1767-
importData,
1768-
allowNonFactory: !element.isAbstract,
1769-
checkVisibility: false,
1761+
}
1762+
if (mustBeMixable) {
1763+
if (request.libraryElement != element.library &&
1764+
!element.isMixableOutside) {
1765+
return;
1766+
}
1767+
}
1768+
if (!(mustBeConstant && !objectPatternAllowed) && !excludeTypeNames) {
1769+
var matcherScore = state.matcher.score(element.displayName);
1770+
if (matcherScore != -1) {
1771+
var suggestion = ClassSuggestion(
1772+
importData: importData,
1773+
element: element,
1774+
matcherScore: matcherScore,
17701775
);
1776+
collector.addSuggestion(suggestion);
17711777
}
17721778
}
1779+
if (!mustBeType) {
1780+
_suggestStaticFields(element.fields, importData);
1781+
_suggestConstructors(
1782+
element.constructors,
1783+
importData,
1784+
allowNonFactory: !element.isAbstract,
1785+
checkVisibility: false,
1786+
);
1787+
}
17731788
}
17741789

17751790
/// Adds a suggestion for the constructor represented by the [element].
@@ -2083,10 +2098,12 @@ class DeclarationHelper {
20832098
/// Adds a suggestion for the mixin represented by the [element].
20842099
void _suggestMixin(MixinElement element, ImportData? importData) {
20852100
if (visibilityTracker.isVisible(element: element, importData: importData)) {
2086-
if (mustBeExtendable ||
2087-
(mustBeImplementable &&
2088-
!element.isImplementableIn(request.libraryElement))) {
2089-
return;
2101+
if (mustBeExtendable) return;
2102+
if (mustBeImplementable) {
2103+
if (request.libraryElement != element.library &&
2104+
!element.isImplementableOutside) {
2105+
return;
2106+
}
20902107
}
20912108
var matcherScore = state.matcher.score(element.displayName);
20922109
if (matcherScore != -1) {

pkg/analyzer/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
* Deprecate `DartObject.variable2`, use `variable` instead.
1414
* Deprecate `DartObject.toFunctionValue2`, use `toFunctionValue` instead.
1515
* Deprecate `Annotatable`, use `documentationComment` and `metadata` of `Element` or `Fragment` directly.
16+
* Deprecate `ClassElement.isExtendableIn`; use `isExtendableOutside` instead.
17+
* Deprecate `ClassElement.isImplementableIn`; use `isImplementableOutside` instead.
18+
* Deprecate `ClassElement.isMixableIn`; use `isMixableOutside` instead.
19+
* Deprecate `MixinElement.isImplementableIn`; use `isImplementableOutside` instead.
1620

1721
## 8.0.0
1822
* Remove deprecated element model V1.

pkg/analyzer/api.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3308,17 +3308,20 @@ package:analyzer/dart/element/element.dart:
33083308
isDartCoreEnum (getter: bool)
33093309
isDartCoreObject (getter: bool)
33103310
isExhaustive (getter: bool)
3311+
isExtendableOutside (getter: bool)
33113312
isFinal (getter: bool)
3313+
isImplementableOutside (getter: bool)
33123314
isInterface (getter: bool)
3315+
isMixableOutside (getter: bool)
33133316
isMixinApplication (getter: bool)
33143317
isMixinClass (getter: bool)
33153318
isSealed (getter: bool)
33163319
isValidMixin (getter: bool)
3317-
isExtendableIn (method: bool Function(LibraryElement))
3320+
isExtendableIn (method: bool Function(LibraryElement), deprecated)
33183321
isExtendableIn2 (method: bool Function(LibraryElement), deprecated)
3319-
isImplementableIn (method: bool Function(LibraryElement))
3322+
isImplementableIn (method: bool Function(LibraryElement), deprecated)
33203323
isImplementableIn2 (method: bool Function(LibraryElement), deprecated)
3321-
isMixableIn (method: bool Function(LibraryElement))
3324+
isMixableIn (method: bool Function(LibraryElement), deprecated)
33223325
isMixableIn2 (method: bool Function(LibraryElement), deprecated)
33233326
ClassFragment (class extends Object implements InterfaceFragment):
33243327
new (constructor: ClassFragment Function())
@@ -3989,8 +3992,9 @@ package:analyzer/dart/element/element.dart:
39893992
firstFragment (getter: MixinFragment)
39903993
fragments (getter: List<MixinFragment>)
39913994
isBase (getter: bool)
3995+
isImplementableOutside (getter: bool)
39923996
superclassConstraints (getter: List<InterfaceType>)
3993-
isImplementableIn (method: bool Function(LibraryElement))
3997+
isImplementableIn (method: bool Function(LibraryElement), deprecated)
39943998
isImplementableIn2 (method: bool Function(LibraryElement), deprecated)
39953999
MixinFragment (class extends Object implements InterfaceFragment):
39964000
new (constructor: MixinFragment Function())

pkg/analyzer/lib/dart/element/element.dart

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ abstract class ClassElement implements InterfaceElement {
268268
/// you have covered all possible instances of the type.
269269
bool get isExhaustive;
270270

271+
/// Whether this class can be extended outside of its library.
272+
bool get isExtendableOutside;
273+
271274
/// Whether the class is a final class.
272275
///
273276
/// A class is a final class if it has an explicit `final` modifier, or the
@@ -276,6 +279,9 @@ abstract class ClassElement implements InterfaceElement {
276279
/// or mixed in.
277280
bool get isFinal;
278281

282+
/// Whether the class can be implemented outside of its library.
283+
bool get isImplementableOutside;
284+
279285
/// Whether the class is an interface class.
280286
///
281287
/// A class is an interface class if it has an explicit `interface` modifier,
@@ -284,6 +290,9 @@ abstract class ClassElement implements InterfaceElement {
284290
/// not extended or mixed in.
285291
bool get isInterface;
286292

293+
/// Whether the class can be mixed-in outside of its library.
294+
bool get isMixableOutside;
295+
287296
/// Whether the class is a mixin application.
288297
///
289298
/// A class is a mixin application if it was declared using the syntax
@@ -314,31 +323,34 @@ abstract class ClassElement implements InterfaceElement {
314323
/// </blockquote>
315324
bool get isValidMixin;
316325

317-
/// Whether the class, assuming that it is within scope, can be extended by
318-
/// classes in the given [library].
326+
/// Whether the class, assuming that it is within scope, can be extended in
327+
/// the given [library].
328+
@Deprecated('Use isExtendableOutside instead')
319329
bool isExtendableIn(LibraryElement library);
320330

321-
/// Whether the class, assuming that it is within scope, can be extended by
322-
/// classes in the given [library].
323-
@Deprecated('Use isExtendableIn instead')
331+
/// Whether the class, assuming that it is within scope, can be extended in
332+
/// the given [library].
333+
@Deprecated('Use isExtendableOutside instead')
324334
bool isExtendableIn2(LibraryElement library);
325335

326-
/// Whether the class, assuming that it is within scope, can be implemented by
327-
/// classes, mixins, and enums in the given [library].
336+
/// Whether the class, assuming that it is within scope, can be implemented in
337+
/// the given [library].
338+
@Deprecated('Use isImplementableOutside instead')
328339
bool isImplementableIn(LibraryElement library);
329340

330-
/// Whether the class, assuming that it is within scope, can be implemented by
331-
/// classes, mixins, and enums in the given [library].
332-
@Deprecated('Use isImplementableIn instead')
341+
/// Whether the class, assuming that it is within scope, can be implemented in
342+
/// the given [library].
343+
@Deprecated('Use isImplementableOutside instead')
333344
bool isImplementableIn2(LibraryElement library);
334345

335-
/// Whether the class, assuming that it is within scope, can be mixed-in by
336-
/// classes and enums in the given [library].
346+
/// Whether the class, assuming that it is within scope, can be mixed-in in
347+
/// the given [library].
348+
@Deprecated('Use isMixableOutside instead')
337349
bool isMixableIn(LibraryElement library);
338350

339-
/// Whether the class, assuming that it is within scope, can be mixed-in by
340-
/// classes and enums in the given [library].
341-
@Deprecated('Use isMixableIn instead')
351+
/// Whether the class, assuming that it is within scope, can be mixed-in in
352+
/// the given [library].
353+
@Deprecated('Use isMixableOutside instead')
342354
bool isMixableIn2(LibraryElement library);
343355
}
344356

@@ -3286,6 +3298,10 @@ abstract class MixinElement implements InterfaceElement {
32863298
/// The base modifier allows a mixin to be mixed in, but not implemented.
32873299
bool get isBase;
32883300

3301+
/// Whether the mixin can be implemented by declarations outside of its
3302+
/// library.
3303+
bool get isImplementableOutside;
3304+
32893305
/// The superclass constraints defined for this mixin.
32903306
///
32913307
/// If the declaration does not have an `on` clause, then the list will
@@ -3298,13 +3314,14 @@ abstract class MixinElement implements InterfaceElement {
32983314
/// guard against infinite loops.
32993315
List<InterfaceType> get superclassConstraints;
33003316

3301-
/// Whether the element, assuming that it is within scope, is
3302-
/// implementable to classes, mixins, and enums in the given [library].
3317+
/// Whether the mixin, assuming that it is within scope, is implementable by
3318+
/// declarations in the given [library].
3319+
@Deprecated('Use isImplementableOutside instead')
33033320
bool isImplementableIn(LibraryElement library);
33043321

3305-
/// Whether the element, assuming that it is within scope, is
3306-
/// implementable to classes, mixins, and enums in the given [library].
3307-
@Deprecated('Use isImplementableIn instead')
3322+
/// Whether the mixin, assuming that it is within scope, is implementable by
3323+
/// declarations in the given [library].
3324+
@Deprecated('Use isImplementableOutside instead')
33083325
bool isImplementableIn2(LibraryElement library);
33093326
}
33103327

0 commit comments

Comments
 (0)