Add a LibraryElement.accessibleExtensions getter.

This saves the ExtensionMemberResolver from having to access the
current scope in order to find out what extensions are available.
This will help prepare for a follow-up CL in which I separate the
"scope lookup" and "type analysis" phases of resolution.

As a side benefit, the analysis server no longer needs to go through
`package:analyzer/src` in order to include extensions in completion
results.

Change-Id: I6098eae219b0f7ef52b7c68f1d64c149d9e66823
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208922
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Paul Berry 2021-08-05 17:44:42 +00:00 committed by commit-bot@chromium.org
parent 846af57d99
commit ddfc60a41e
5 changed files with 10 additions and 28 deletions

View file

@ -10,7 +10,6 @@ import 'package:analysis_server/src/utilities/extensions/element.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
/// A contributor that produces suggestions based on the members of an
/// extension.
@ -113,8 +112,7 @@ class ExtensionMemberContributor extends DartCompletionContributor {
void _addExtensionMembers(LibraryElement containingLibrary,
CompletionSuggestionKind? kind, DartType type) {
var typeSystem = containingLibrary.typeSystem;
var nameScope = containingLibrary.scope;
for (var extension in nameScope.extensions) {
for (var extension in containingLibrary.accessibleExtensions) {
var extendedType =
extension.resolvedExtendedType(containingLibrary, type);
if (extendedType != null && typeSystem.isSubtypeOf(type, extendedType)) {

View file

@ -1300,6 +1300,10 @@ abstract class LabelElement implements Element {
///
/// Clients may not extend, implement or mix-in this class.
abstract class LibraryElement implements _ExistingElement {
/// Returns a list containing all of the extension elements accessible within
/// this library.
List<ExtensionElement> get accessibleExtensions;
/// Return the compilation unit that defines this library.
CompilationUnitElement get definingCompilationUnit;

View file

@ -3688,6 +3688,9 @@ class LibraryElementImpl extends _ExistingElementImpl
: linkedData = null,
super(name, offset);
@override
List<ExtensionElement> get accessibleExtensions => scope.extensions;
@override
CompilationUnitElement get definingCompilationUnit =>
_definingCompilationUnit;
@ -3942,7 +3945,7 @@ class LibraryElementImpl extends _ExistingElementImpl
}
@override
Scope get scope {
LibraryScope get scope {
return _scope ??= LibraryScope(this);
}

View file

@ -6,7 +6,6 @@ import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/syntactic_entity.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/error/listener.dart';
@ -19,7 +18,6 @@ import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/element/type_schema.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/resolution_result.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/util/either.dart';
@ -37,8 +35,6 @@ class ExtensionMemberResolver {
bool get _genericMetadataIsEnabled =>
_resolver.definingLibrary.featureSet.isEnabled(Feature.generic_metadata);
Scope get _nameScope => _resolver.nameScope;
TypeProvider get _typeProvider => _resolver.typeProvider;
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
@ -397,7 +393,7 @@ class ExtensionMemberResolver {
}
}
for (var extension in _nameScope.extensions) {
for (var extension in _resolver.definingLibrary.accessibleExtensions) {
checkExtension(extension);
}
return candidates;

View file

@ -6,9 +6,7 @@ import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/scope.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/engine.dart';
@ -350,20 +348,3 @@ class PrefixedNamespace implements Namespace {
return null;
}
}
extension ScopeExtension on Scope {
List<ExtensionElement> get extensions {
return _enclosingLibraryScope.extensions;
}
LibraryScope get _enclosingLibraryScope {
Scope? scope = this;
while (scope != null) {
if (scope is LibraryScope) {
return scope;
}
scope = (scope as EnclosedScope).parent;
}
throw StateError('Can only be used in a LibraryScope.');
}
}