Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 93fa1cf

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Add Scope and LibraryElement.scope to API.
Change-Id: I5cfda9ed6c52fde38252d82ee1bc9c9152b906f0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/154141 Commit-Queue: Konstantin Shcheglov <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 0506475 commit 93fa1cf

File tree

7 files changed

+186
-4
lines changed

7 files changed

+186
-4
lines changed

pkg/analyzer/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Added `InterfaceType.allSupertypes`.
77
* Added `InterfaceType.asInstanceOf(ClassElement)`.
88
* Removed deprecated internal `bogus-disabled` and `bogus-enabled`.
9+
* Added `Scope` and `LibraryElement.scope`.
910

1011
## 0.39.12
1112
* Deprecated `canUseSummaries` in `DartSdkManager` constructor.

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

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import 'package:analyzer/dart/analysis/session.dart';
3838
import 'package:analyzer/dart/constant/value.dart';
3939
import 'package:analyzer/dart/element/nullability_suffix.dart';
40+
import 'package:analyzer/dart/element/scope.dart';
4041
import 'package:analyzer/dart/element/type.dart';
4142
import 'package:analyzer/dart/element/type_provider.dart';
4243
import 'package:analyzer/dart/element/type_system.dart';
@@ -1375,6 +1376,10 @@ abstract class LibraryElement implements Element {
13751376
/// computed yet.
13761377
Namespace get publicNamespace;
13771378

1379+
/// Return the name lookup scope for this library. It consists of elements
1380+
/// that are either declared in the library, or imported into it.
1381+
Scope get scope;
1382+
13781383
/// Return the top-level elements defined in each of the compilation units
13791384
/// that are included in this library. This includes both public and private
13801385
/// elements, but does not include imports, exports, or synthetic elements.
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analyzer/dart/element/element.dart';
6+
import 'package:meta/meta.dart';
7+
8+
/// Scopes are used to resolve names to elements.
9+
abstract class Scope {
10+
/// Return the element with the name `id` or `id=` (if [setter] is `true`),
11+
/// `null` if the name is not defined within this scope.
12+
Element lookup({@required String id, @required bool setter});
13+
}

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

+12-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:analyzer/dart/ast/token.dart';
1010
import 'package:analyzer/dart/constant/value.dart';
1111
import 'package:analyzer/dart/element/element.dart';
1212
import 'package:analyzer/dart/element/nullability_suffix.dart';
13+
import 'package:analyzer/dart/element/scope.dart';
1314
import 'package:analyzer/dart/element/type.dart';
1415
import 'package:analyzer/error/error.dart';
1516
import 'package:analyzer/src/dart/analysis/experiments.dart';
@@ -20,11 +21,13 @@ import 'package:analyzer/src/dart/constant/value.dart';
2021
import 'package:analyzer/src/dart/element/display_string_builder.dart';
2122
import 'package:analyzer/src/dart/element/member.dart';
2223
import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
24+
import 'package:analyzer/src/dart/element/scope.dart';
2325
import 'package:analyzer/src/dart/element/type.dart';
2426
import 'package:analyzer/src/dart/element/type_algebra.dart';
2527
import 'package:analyzer/src/dart/element/type_provider.dart';
2628
import 'package:analyzer/src/dart/element/type_system.dart';
27-
import 'package:analyzer/src/dart/resolver/scope.dart';
29+
import 'package:analyzer/src/dart/resolver/scope.dart'
30+
show Namespace, NamespaceBuilder;
2831
import 'package:analyzer/src/dart/resolver/variance.dart';
2932
import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
3033
import 'package:analyzer/src/generated/element_type_provider.dart';
@@ -5208,6 +5211,9 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement {
52085211
/// The cached list of prefixes.
52095212
List<PrefixElement> _prefixes;
52105213

5214+
/// The scope of this library, `null` if it has not been created yet.
5215+
LibraryScope _scope;
5216+
52115217
/// Initialize a newly created library element in the given [context] to have
52125218
/// the given [name] and [offset].
52135219
LibraryElementImpl(this.context, this.session, String name, int offset,
@@ -5581,6 +5587,11 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement {
55815587
_publicNamespace = publicNamespace;
55825588
}
55835589

5590+
@override
5591+
Scope get scope {
5592+
return _scope ??= LibraryScope(this);
5593+
}
5594+
55845595
@override
55855596
Source get source {
55865597
if (_definingCompilationUnit == null) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
6+
import 'package:analyzer/dart/ast/token.dart';
7+
import 'package:analyzer/dart/element/element.dart';
8+
import 'package:analyzer/dart/element/scope.dart';
9+
import 'package:analyzer/src/dart/ast/token.dart';
10+
import 'package:analyzer/src/dart/resolver/scope.dart' as impl;
11+
import 'package:meta/meta.dart';
12+
13+
class LibraryScope implements Scope {
14+
final LibraryElement _libraryElement;
15+
final impl.LibraryScope _implScope;
16+
17+
LibraryScope(LibraryElement libraryElement)
18+
: _libraryElement = libraryElement,
19+
_implScope = impl.LibraryScope(libraryElement);
20+
21+
@override
22+
Element lookup({@required String id, @required bool setter}) {
23+
var name = setter ? '$id=' : id;
24+
var token = SyntheticStringToken(TokenType.IDENTIFIER, name, 0);
25+
var identifier = astFactory.simpleIdentifier(token);
26+
return _implScope.lookup(identifier, _libraryElement);
27+
}
28+
}

pkg/analyzer/test/src/dart/resolution/library_element_test.dart

+118
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,124 @@ class A {}
123123
await _assertLanguageVersionCurrent('package:aaa/c.dart');
124124
}
125125

126+
test_scope() async {
127+
await assertNoErrorsInCode(r'''
128+
int foo;
129+
''');
130+
131+
var scope = result.libraryElement.scope;
132+
133+
assertElement(
134+
scope.lookup(id: 'foo', setter: false),
135+
findElement.topGet('foo'),
136+
);
137+
assertElement(
138+
scope.lookup(id: 'foo', setter: true),
139+
findElement.topSet('foo'),
140+
);
141+
}
142+
143+
test_scope_implicitCoreImport() async {
144+
await assertNoErrorsInCode('');
145+
146+
var scope = result.libraryElement.scope;
147+
148+
assertElement(
149+
scope.lookup(id: 'int', setter: false),
150+
intElement,
151+
);
152+
}
153+
154+
test_scope_notFound() async {
155+
await assertNoErrorsInCode('');
156+
157+
var scope = result.libraryElement.scope;
158+
159+
assertElementNull(
160+
scope.lookup(id: 'noSuchGetter', setter: false),
161+
);
162+
163+
assertElementNull(
164+
scope.lookup(id: 'noSuchSetter', setter: true),
165+
);
166+
}
167+
168+
test_scope_prefersLocal() async {
169+
await assertNoErrorsInCode(r'''
170+
// ignore:unused_import
171+
import 'dart:math';
172+
173+
int sin() => 3;
174+
''');
175+
176+
var scope = result.libraryElement.scope;
177+
178+
assertElement(
179+
scope.lookup(id: 'sin', setter: false),
180+
findElement.topFunction('sin'),
181+
);
182+
183+
assertElement(
184+
scope.lookup(id: 'cos', setter: false),
185+
findElement.importFind('dart:math').topFunction('cos'),
186+
);
187+
}
188+
189+
test_scope_prefix() async {
190+
await assertNoErrorsInCode(r'''
191+
// ignore:unused_import
192+
import 'dart:math' as math;
193+
''');
194+
195+
var scope = result.libraryElement.scope;
196+
197+
assertElement(
198+
scope.lookup(id: 'math', setter: false),
199+
findElement.prefix('math'),
200+
);
201+
}
202+
203+
test_scope_respectsCombinator_hide() async {
204+
await assertNoErrorsInCode(r'''
205+
// ignore:unused_import
206+
import 'dart:math' hide sin;
207+
''');
208+
209+
var scope = result.libraryElement.scope;
210+
211+
assertElementNull(
212+
scope.lookup(id: 'sin', setter: false),
213+
);
214+
215+
var mathFind = findElement.importFind('dart:math');
216+
assertElement(
217+
scope.lookup(id: 'cos', setter: false),
218+
mathFind.topFunction('cos'),
219+
);
220+
assertElement(
221+
scope.lookup(id: 'tan', setter: false),
222+
mathFind.topFunction('tan'),
223+
);
224+
}
225+
226+
test_scope_respectsCombinator_show() async {
227+
await assertNoErrorsInCode(r'''
228+
// ignore:unused_import
229+
import 'dart:math' show sin;
230+
''');
231+
232+
var scope = result.libraryElement.scope;
233+
234+
assertElement(
235+
scope.lookup(id: 'sin', setter: false),
236+
findElement.importFind('dart:math').topFunction('sin'),
237+
);
238+
239+
assertElementNull(
240+
scope.lookup(id: 'cos', setter: false),
241+
);
242+
}
243+
126244
Future<void> _assertLanguageVersion({
127245
@required String uriStr,
128246
@required Version package,

pkg/analyzer/test/src/dart/resolution/resolution.dart

+9-3
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,15 @@ mixin ResolutionTest implements ResourceProviderMixin {
206206
}
207207
}
208208

209-
void assertElementNull(Expression node) {
210-
Element actual = getNodeElement(node);
211-
expect(actual, isNull);
209+
void assertElementNull(Object nodeOrElement) {
210+
Element element;
211+
if (nodeOrElement is AstNode) {
212+
element = getNodeElement(nodeOrElement);
213+
} else {
214+
element = nodeOrElement as Element;
215+
}
216+
217+
expect(element, isNull);
212218
}
213219

214220
void assertElementString(Element element, String expected) {

0 commit comments

Comments
 (0)