Skip to content

Commit

Permalink
Elements. Migrate ElementNameUnion.
Browse files Browse the repository at this point in the history
Change-Id: I163fb60cea95f8e7a53b4be75239864b65bdfbd1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/403925
Reviewed-by: Paul Berry <[email protected]>
Commit-Queue: Konstantin Shcheglov <[email protected]>
Reviewed-by: Brian Wilkerson <[email protected]>
  • Loading branch information
scheglov authored and Commit Queue committed Jan 13, 2025
1 parent 01f5956 commit 519e288
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 77 deletions.
37 changes: 25 additions & 12 deletions pkg/analyzer/lib/src/dart/element/element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5562,18 +5562,23 @@ abstract class InstanceElementImpl2 extends ElementImpl2
LibraryElement2 get enclosingElement2 => firstFragment.library;

@override
List<FieldElement2> get fields2 =>
fields.map((e) => e.asElement2 as FieldElement2?).nonNulls.toList();
List<FieldElement2> get fields2 {
_readMembers();
return fields.map((e) => e.asElement2 as FieldElement2?).nonNulls.toList();
}

@override
InstanceElementImpl get firstFragment;

@override
List<GetterElement> get getters2 => accessors
.where((e) => e.isGetter)
.map((e) => e.asElement2 as GetterElement?)
.nonNulls
.toList();
List<GetterElement> get getters2 {
_readMembers();
return accessors
.where((e) => e.isGetter)
.map((e) => e.asElement2 as GetterElement?)
.nonNulls
.toList();
}

@override
String get identifier => name3 ?? firstFragment.identifier;
Expand Down Expand Up @@ -5613,11 +5618,14 @@ abstract class InstanceElementImpl2 extends ElementImpl2
AnalysisSession? get session => firstFragment.session;

@override
List<SetterElement> get setters2 => accessors
.where((e) => e.isSetter)
.map((e) => e.asElement2 as SetterElement?)
.nonNulls
.toList();
List<SetterElement> get setters2 {
_readMembers();
return accessors
.where((e) => e.isSetter)
.map((e) => e.asElement2 as SetterElement?)
.nonNulls
.toList();
}

@override
List<TypeParameterElementImpl2> get typeParameters2 =>
Expand Down Expand Up @@ -5892,6 +5900,11 @@ abstract class InstanceElementImpl2 extends ElementImpl2
Iterable<PropertyAccessorElement2> _implementationsOfSetter2(String name) {
return _implementationsOfSetter(name).map((e) => e.asElement2);
}

void _readMembers() {
// TODO(scheglov): use better implementation
firstFragment.element;
}
}

abstract class InterfaceElementImpl extends InstanceElementImpl
Expand Down
44 changes: 27 additions & 17 deletions pkg/analyzer/lib/src/dart/element/name_union.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// ignore_for_file: analyzer_use_new_elements

import 'dart:typed_data';

import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/visitor2.dart';

/// Union of a set of names.
class ElementNameUnion {
Expand Down Expand Up @@ -92,33 +90,45 @@ class ElementNameUnion {
return true;
}

static ElementNameUnion forLibrary(LibraryElement libraryElement) {
static ElementNameUnion forLibrary(LibraryElement2 libraryElement) {
var result = ElementNameUnion.empty();
libraryElement.accept(
_ElementVisitor(result),
libraryElement.accept2(
_ElementVisitor2(result),
);
return result;
}

static bool _hasInterestingElements(Element2 element) {
if (element is ExecutableElement2) {
return false;
}
return true;
}

static bool _isInterestingElement(Element2 element) {
return element.enclosingElement2 is LibraryElement2 ||
element is FieldElement2 ||
element is MethodElement2 ||
element is PropertyAccessorElement2;
}
}

class _ElementVisitor extends GeneralizingElementVisitor<void> {
class _ElementVisitor2 extends GeneralizingElementVisitor2<void> {
final ElementNameUnion union;

_ElementVisitor(this.union);
_ElementVisitor2(this.union);

@override
void visitElement(Element element) {
var enclosing = element.enclosingElement3;
if (enclosing is CompilationUnitElement ||
element is FieldElement ||
element is MethodElement ||
element is PropertyAccessorElement) {
var name = element.name;
void visitElement(Element2 element) {
if (ElementNameUnion._isInterestingElement(element)) {
var name = element.name3;
if (name != null) {
union.add(name);
}
}

super.visitElement(element);
if (ElementNameUnion._hasInterestingElements(element)) {
super.visitElement(element);
}
}
}
135 changes: 87 additions & 48 deletions pkg/analyzer/test/src/dart/element/name_union_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// ignore_for_file: analyzer_use_new_elements

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/src/dart/element/name_union.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../resolution/context_collection_resolution.dart';
import '../../summary/elements_base.dart';

main() {
defineReflectiveSuite(() {
Expand All @@ -20,54 +14,99 @@ main() {
}

@reflectiveTest
class ElementNameUnionTest extends PubPackageResolutionTest {
test_it() async {
await _checkLibrary('dart:async');
await _checkLibrary('dart:core');
await _checkLibrary('dart:math');
}
class ElementNameUnionTest extends ElementsBaseTest {
@override
bool get keepLinkingLibraries => false;

test_class() async {
var library = await buildLibrary(r'''
class MyClass {
final myField = 0;
int get myGetter => 0;
set mySetter(int _) {}
void myMethod() {}
}
''');

var nameUnion = library.nameUnion;
expect(nameUnion.contains('MyClass'), isTrue);
expect(nameUnion.contains('NotMyClass'), isFalse);

Future<void> _checkLibrary(String uriStr) async {
var analysisContext = contextFor(testFile);
var analysisSession = analysisContext.currentSession;
expect(nameUnion.contains('myField'), isTrue);
expect(nameUnion.contains('NotMyField'), isFalse);

var result = await analysisSession.getLibraryByUri(uriStr);
result as LibraryElementResult;
var element = result.element;
expect(nameUnion.contains('myGetter'), isTrue);
expect(nameUnion.contains('NotMyGetter'), isFalse);

var union = ElementNameUnion.forLibrary(element);
element.accept(
_ElementVisitor(union),
);
expect(nameUnion.contains('mySetter'), isTrue);
expect(nameUnion.contains('NotMySetter'), isFalse);

expect(nameUnion.contains('myMethod'), isTrue);
expect(nameUnion.contains('NotMyMethod'), isFalse);
}

test_enum() async {
var library = await buildLibrary(r'''
enum MyEnum {
myValue
}
''');

var nameUnion = library.nameUnion;
expect(nameUnion.contains('MyEnum'), isTrue);
expect(nameUnion.contains('NotMyEnum'), isFalse);

/// Checks that the name of every interesting element is in [union].
class _ElementVisitor extends GeneralizingElementVisitor<void> {
final ElementNameUnion union;
expect(nameUnion.contains('MyValue'), isTrue);
expect(nameUnion.contains('NotMyValue'), isFalse);
}

_ElementVisitor(this.union);
test_extension() async {
var library = await buildLibrary(r'''
extension MyExtension on int {}
''');

@override
void visitElement(Element element) {
var enclosing = element.enclosingElement3;
if (enclosing is CompilationUnitElement ||
element is FieldElement ||
element is MethodElement ||
element is PropertyAccessorElement) {
var name = element.name;
if (name != null) {
expect(union.contains(name), isTrue, reason: 'Expected to find $name');
// This might fail, but the probability is low. If this does fail, try
// adding another `z` to the prefix.
expect(
union.contains('zz$name'),
isFalse,
reason: 'Expected to not find $name',
);
}
}

super.visitElement(element);
var nameUnion = library.nameUnion;
expect(nameUnion.contains('MyExtension'), isTrue);
expect(nameUnion.contains('NotMyExtension'), isFalse);
}

test_extensionType() async {
var library = await buildLibrary(r'''
extension type MyExtensionType(int it) {}
''');

var nameUnion = library.nameUnion;
expect(nameUnion.contains('MyExtensionType'), isTrue);
expect(nameUnion.contains('NotMyExtensionType'), isFalse);
}

test_mixin() async {
var library = await buildLibrary(r'''
mixin MyMixin {}
''');

var nameUnion = library.nameUnion;
expect(nameUnion.contains('MyMixin'), isTrue);
expect(nameUnion.contains('NotMyMixin'), isFalse);
}

test_topLevelVariable() async {
var library = await buildLibrary(r'''
final myVariable = 0;
''');

var nameUnion = library.nameUnion;
expect(nameUnion.contains('myVariable'), isTrue);
expect(nameUnion.contains('NotMyVariable'), isFalse);
}

test_typedef() async {
var library = await buildLibrary(r'''
typedef MyTypedef = int;
''');

var nameUnion = library.nameUnion;
expect(nameUnion.contains('MyTypedef'), isTrue);
expect(nameUnion.contains('NotMyTypedef'), isFalse);
}
}

0 comments on commit 519e288

Please sign in to comment.