Add NotAugmentedXyzElementImpl implements AugmentedXyzElement.

So, that we don't have to copy all class members for 99% cases when
there are no augmentaitons.

Change-Id: I5c225905a0460ce5162543553e207a2d4412ecb9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/313082
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Konstantin Shcheglov 2023-07-11 02:22:35 +00:00 committed by Commit Queue
parent 8be3439ce3
commit 7a258fa43b
9 changed files with 428 additions and 63 deletions

View file

@ -1644,13 +1644,6 @@ abstract class InterfaceElement
@override
InterfaceType get thisType;
/// The unnamed constructor declared directly in this class.
///
/// If the class does not declare any constructors, a synthetic default
/// constructor will be returned.
/// TODO(scheglov) Deprecate and remove it.
ConstructorElement? get unnamedConstructor;
/// The field (synthetic or explicit) defined directly in this class or
/// augmentation that has the given [name].
/// TODO(scheglov) Deprecate and remove it.
@ -1666,11 +1659,6 @@ abstract class InterfaceElement
/// TODO(scheglov) Deprecate and remove it.
MethodElement? getMethod(String name);
/// The constructor defined directly in this class or augmentation
/// that has the given [name].
/// TODO(scheglov) Deprecate and remove it.
ConstructorElement? getNamedConstructor(String name);
/// The setter (synthetic or explicit) defined directly in this class or
/// augmentation that has the given [name].
/// TODO(scheglov) Deprecate and remove it.
@ -2255,6 +2243,18 @@ abstract class NamedInstanceElement
@override
AugmentedNamedInstanceElement get augmented;
/// The unnamed constructor declared directly in this class.
///
/// If the class does not declare any constructors, a synthetic default
/// constructor will be returned.
/// TODO(scheglov) Deprecate and remove it.
ConstructorElement? get unnamedConstructor;
/// The constructor defined directly in this class or augmentation
/// that has the given [name].
/// TODO(scheglov) Deprecate and remove it.
ConstructorElement? getNamedConstructor(String name);
/// Create the [DartType] for this element with the given [typeArguments]
/// and [nullabilitySuffix].
DartType instantiate({

View file

@ -87,7 +87,7 @@ import 'package:analyzer/src/utilities/uri_cache.dart';
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
static const int DATA_VERSION = 283;
static const int DATA_VERSION = 284;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.

View file

@ -232,8 +232,8 @@ class ClassAugmentationElementImpl extends InterfaceAugmentationElementImpl
class ClassElementImpl extends ClassOrMixinElementImpl
with ClassOrAugmentationElementMixin
implements ClassElement {
@override
final AugmentedClassElementImpl augmented = AugmentedClassElementImpl();
late AugmentedClassElement augmentedInternal =
NotAugmentedClassElementImpl(this);
/// Initialize a newly created class element to have the given [name] at the
/// given [offset] in the file that contains the declaration of this element.
@ -285,6 +285,12 @@ class ClassElementImpl extends ClassOrMixinElementImpl
return null;
}
@override
AugmentedClassElement get augmented {
linkedData?.read(this);
return augmentedInternal;
}
@override
ClassElementImpl get augmentedDeclaration => this;
@ -3637,7 +3643,7 @@ abstract class InterfaceElementImpl extends NamedInstanceElementImpl
}
@override
AugmentedInterfaceElementImpl get augmented {
AugmentedInterfaceElement get augmented {
throw UnimplementedError();
}
@ -3691,11 +3697,6 @@ abstract class InterfaceElementImpl extends NamedInstanceElementImpl
return _thisType!;
}
@override
ConstructorElement? get unnamedConstructor {
return constructors.firstWhereOrNull((element) => element.name.isEmpty);
}
@override
FieldElement? getField(String name) {
return fields.firstWhereOrNull((fieldElement) => name == fieldElement.name);
@ -3712,15 +3713,6 @@ abstract class InterfaceElementImpl extends NamedInstanceElementImpl
return methods.firstWhereOrNull((method) => method.name == methodName);
}
@override
ConstructorElement? getNamedConstructor(String name) {
if (name == 'new') {
// A constructor declared as `C.new` is unnamed, and is modeled as such.
name = '';
}
return constructors.firstWhereOrNull((element) => element.name == name);
}
@override
PropertyAccessorElement? getSetter(String setterName) {
return getSetterFromAccessors(setterName, accessors);
@ -5095,15 +5087,15 @@ class MixinElementImpl extends ClassOrMixinElementImpl
/// The list will be empty if this class is not a mixin declaration.
late List<String> superInvokedNames;
final AugmentedMixinElementImpl augmentedInternal =
AugmentedMixinElementImpl();
late AugmentedMixinElement augmentedInternal =
NotAugmentedMixinElementImpl(this);
/// Initialize a newly created class element to have the given [name] at the
/// given [offset] in the file that contains the declaration of this element.
MixinElementImpl(super.name, super.offset);
@override
AugmentedMixinElementImpl get augmented {
AugmentedMixinElement get augmented {
linkedData?.read(this);
return augmentedInternal;
}
@ -5607,6 +5599,20 @@ abstract class NamedInstanceElementImpl extends InstanceElementImpl
with NamedInstanceOrAugmentationElementMixin
implements NamedInstanceElement {
NamedInstanceElementImpl(super.name, super.nameOffset);
@override
ConstructorElement? get unnamedConstructor {
return constructors.firstWhereOrNull((element) => element.name.isEmpty);
}
@override
ConstructorElement? getNamedConstructor(String name) {
if (name == 'new') {
// A constructor declared as `C.new` is unnamed, and is modeled as such.
name = '';
}
return constructors.firstWhereOrNull((element) => element.name == name);
}
}
mixin NamedInstanceOrAugmentationElementMixin
@ -5701,6 +5707,155 @@ abstract class NonParameterVariableElementImpl extends VariableElementImpl
}
}
class NotAugmentedClassElementImpl extends NotAugmentedInterfaceElementImpl
implements AugmentedClassElement {
@override
final ClassElementImpl element;
NotAugmentedClassElementImpl(this.element);
}
class NotAugmentedEnumElementImpl extends NotAugmentedInterfaceElementImpl
implements AugmentedEnumElement {
@override
final EnumElementImpl element;
NotAugmentedEnumElementImpl(this.element);
}
class NotAugmentedExtensionElementImpl extends AugmentedInstanceElementImpl
implements AugmentedExtensionElement {
final ExtensionElementImpl element;
NotAugmentedExtensionElementImpl(this.element);
}
class NotAugmentedInlineClassElementImpl
extends NotAugmentedNamedInstanceElementImpl
implements AugmentedInlineClassElement {
@override
final InlineClassElementImpl element;
NotAugmentedInlineClassElementImpl(this.element);
}
abstract class NotAugmentedInstanceElementImpl
implements AugmentedInstanceElement {
@override
List<PropertyAccessorElement> get accessors {
return element.accessors;
}
InstanceElementImpl get element;
@override
List<FieldElement> get fields {
return element.fields;
}
@override
List<ElementAnnotation> get metadata {
return element.metadata;
}
@override
List<MethodElement> get methods {
return element.methods;
}
@override
FieldElement? getField(String name) {
for (final field in fields) {
if (field.name == name) {
return field;
}
}
return null;
}
@override
PropertyAccessorElement? getGetter(String name) {
for (final getter in accessors) {
if (getter.isGetter && getter.name == name) {
return getter;
}
}
return null;
}
@override
MethodElement? getMethod(String name) {
for (final method in methods) {
if (method.name == name) {
return method;
}
}
return null;
}
@override
PropertyAccessorElement? getSetter(String name) {
for (final setter in accessors) {
if (setter.isSetter && setter.name == name) {
return setter;
}
}
return null;
}
}
abstract class NotAugmentedInterfaceElementImpl
extends NotAugmentedNamedInstanceElementImpl
implements AugmentedInterfaceElement {
@override
InterfaceElementImpl get element;
@override
List<InterfaceType> get interfaces {
return element.interfaces;
}
@override
List<InterfaceType> get mixins {
return element.mixins;
}
}
class NotAugmentedMixinElementImpl extends NotAugmentedInterfaceElementImpl
implements AugmentedMixinElement {
@override
final MixinElementImpl element;
NotAugmentedMixinElementImpl(this.element);
@override
List<InterfaceType> get superclassConstraints {
return element.superclassConstraints;
}
}
abstract class NotAugmentedNamedInstanceElementImpl
extends NotAugmentedInstanceElementImpl
implements AugmentedNamedInstanceElement {
@override
List<ConstructorElement> get constructors {
return element.constructors;
}
@override
NamedInstanceElementImpl get element;
@override
ConstructorElement? get unnamedConstructor {
return element.unnamedConstructor;
}
@override
ConstructorElement? getNamedConstructor(String name) {
return element.getNamedConstructor(name);
}
}
/// A concrete implementation of a [ParameterElement].
class ParameterElementImpl extends VariableElementImpl
with ParameterElementMixin

View file

@ -151,8 +151,14 @@ class ClassElementLinkedData extends ElementLinkedData<ClassElementImpl> {
element.interfaces = reader._readInterfaceTypeList();
element.augmentation =
reader.readElement() as ClassAugmentationElementImpl?;
element.augmented.mixins = reader._readInterfaceTypeList();
element.augmented.interfaces = reader._readInterfaceTypeList();
if (reader.readBool()) {
final augmented = AugmentedClassElementImpl();
element.augmentedInternal = augmented;
augmented.mixins = reader._readInterfaceTypeList();
augmented.interfaces = reader._readInterfaceTypeList();
}
applyConstantOffsets?.perform();
}
}
@ -1727,8 +1733,14 @@ class MixinElementLinkedData extends ElementLinkedData<MixinElementImpl> {
element.interfaces = reader._readInterfaceTypeList();
element.augmentation =
reader.readElement() as MixinAugmentationElementImpl?;
element.augmented.superclassConstraints = reader._readInterfaceTypeList();
element.augmented.interfaces = reader._readInterfaceTypeList();
if (reader.readBool()) {
final augmented = AugmentedMixinElementImpl();
element.augmentedInternal = augmented;
augmented.superclassConstraints = reader._readInterfaceTypeList();
augmented.interfaces = reader._readInterfaceTypeList();
}
applyConstantOffsets?.perform();
}
}
@ -1782,6 +1794,10 @@ class ResolutionReader {
return _elementFactory.libraryOfUri2(uri);
}
bool readBool() {
return _reader.readBool();
}
int readByte() {
return _reader.readByte();
}

View file

@ -182,8 +182,13 @@ class BundleWriter {
_resolutionSink._writeTypeList(element.mixins);
_resolutionSink._writeTypeList(element.interfaces);
_resolutionSink.writeElement(element.augmentation);
_resolutionSink._writeTypeList(element.augmented.mixins);
_resolutionSink._writeTypeList(element.augmented.interfaces);
_resolutionSink.writeIfType<AugmentedClassElementImpl>(
element.augmented,
(augmented) {
_resolutionSink._writeTypeList(augmented.mixins);
_resolutionSink._writeTypeList(augmented.interfaces);
},
);
if (!element.isMixinApplication) {
var membersOffset = _sink.offset;
@ -466,8 +471,13 @@ class BundleWriter {
_resolutionSink._writeTypeList(element.superclassConstraints);
_resolutionSink._writeTypeList(element.interfaces);
_resolutionSink.writeElement(element.augmentation);
_resolutionSink._writeTypeList(element.augmented.superclassConstraints);
_resolutionSink._writeTypeList(element.augmented.interfaces);
_resolutionSink.writeIfType<AugmentedMixinElementImpl>(
element.augmented,
(augmented) {
_resolutionSink._writeTypeList(augmented.superclassConstraints);
_resolutionSink._writeTypeList(augmented.interfaces);
},
);
_writeList(
element.fields.where((e) => !e.isSynthetic).toList(),

View file

@ -121,6 +121,18 @@ class BufferedSink {
addByte(byte);
}
void writeIfType<T extends Object>(
Object? object,
void Function(T t) ifTrue,
) {
if (object is T) {
writeBool(true);
ifTrue(object);
} else {
writeBool(false);
}
}
void writeList<T>(List<T> items, void Function(T x) writeItem) {
writeUInt30(items.length);
for (var i = 0; i < items.length; i++) {

View file

@ -168,9 +168,12 @@ class TypesBuilder {
node.implementsClause?.interfaces,
);
final augmented = element.augmented;
augmented.mixins.addAll(element.mixins);
augmented.interfaces.addAll(element.interfaces);
if (element.augmentation != null) {
final augmented = AugmentedClassElementImpl();
element.augmentedInternal = augmented;
augmented.mixins.addAll(element.mixins);
augmented.interfaces.addAll(element.interfaces);
}
}
void _classTypeAlias(ClassTypeAlias node) {
@ -373,9 +376,12 @@ class TypesBuilder {
node.implementsClause?.interfaces,
);
final augmented = element.augmented;
augmented.superclassConstraints.addAll(element.superclassConstraints);
augmented.interfaces.addAll(element.interfaces);
if (element.augmentation != null) {
final augmented = AugmentedMixinElementImpl();
element.augmentedInternal = augmented;
augmented.superclassConstraints.addAll(element.superclassConstraints);
augmented.interfaces.addAll(element.interfaces);
}
}
NullabilitySuffix _nullability(AstNode node, bool hasQuestion) {

View file

@ -40,6 +40,7 @@ String getLibraryText({
class ElementTextConfiguration {
bool Function(Object) filter;
bool withAugmentedWithoutAugmentation = false;
bool withCodeRanges = false;
bool withConstantInitializers = true;
bool withConstructors = true;
@ -200,17 +201,20 @@ class _ElementWriter {
// No augmentation, not interesting.
if (e.augmentation == null) {
return;
expect(e.augmented, TypeMatcher<NotAugmentedInstanceElementImpl>());
if (!configuration.withAugmentedWithoutAugmentation) {
return;
}
}
_sink.writelnWithIndent('augmented');
_sink.withIndent(() {
final augmented = e.augmented;
switch (augmented) {
case AugmentedClassElementImpl():
case AugmentedClassElement():
_elementPrinter.writeTypeList('mixins', augmented.mixins);
_elementPrinter.writeTypeList('interfaces', augmented.interfaces);
case AugmentedMixinElementImpl():
case AugmentedMixinElement():
_elementPrinter.writeTypeList(
'superclassConstraints',
augmented.superclassConstraints,

View file

@ -26,19 +26,43 @@ main() {
mixin ClassAugmentationElementsMixin on ElementsBaseTest {
test_augmentationTarget() async {
newFile('$testPackageLibPath/a.dart', r'''
newFile('$testPackageLibPath/a1.dart', r'''
library augment 'test.dart';
import augment 'b.dart';
import augment 'a11.dart';
import augment 'a12.dart';
augment class A {}
''');
newFile('$testPackageLibPath/b.dart', r'''
library augment 'a.dart';
newFile('$testPackageLibPath/a11.dart', r'''
library augment 'a1.dart';
augment class A {}
''');
newFile('$testPackageLibPath/a12.dart', r'''
library augment 'a1.dart';
augment class A {}
''');
newFile('$testPackageLibPath/a2.dart', r'''
library augment 'test.dart';
import augment 'a21.dart';
import augment 'a22.dart';
augment class A {}
''');
newFile('$testPackageLibPath/a21.dart', r'''
library augment 'a2.dart';
augment class A {}
''');
newFile('$testPackageLibPath/a22.dart', r'''
library augment 'a2.dart';
augment class A {}
''');
var library = await buildLibrary(r'''
import augment 'a.dart';
import augment 'a1.dart';
import augment 'a2.dart';
class A {}
''');
@ -46,25 +70,54 @@ class A {}
library
definingUnit
classes
class A @31
augmentation: self::@augmentation::package:test/a.dart::@classAugmentation::A
class A @58
augmentation: self::@augmentation::package:test/a1.dart::@classAugmentation::A
constructors
synthetic @-1
augmented
augmentationImports
package:test/a.dart
package:test/a1.dart
definingUnit
classAugmentations
augment class A @68
augment class A @97
augmentationTarget: self::@class::A
augmentedDeclaration: self::@class::A
augmentation: self::@augmentation::package:test/b.dart::@classAugmentation::A
augmentation: self::@augmentation::package:test/a11.dart::@classAugmentation::A
augmentationImports
package:test/b.dart
package:test/a11.dart
definingUnit
classAugmentations
augment class A @40
augmentationTarget: self::@augmentation::package:test/a.dart::@classAugmentation::A
augment class A @41
augmentationTarget: self::@augmentation::package:test/a1.dart::@classAugmentation::A
augmentedDeclaration: self::@class::A
augmentation: self::@augmentation::package:test/a12.dart::@classAugmentation::A
package:test/a12.dart
definingUnit
classAugmentations
augment class A @41
augmentationTarget: self::@augmentation::package:test/a11.dart::@classAugmentation::A
augmentedDeclaration: self::@class::A
augmentation: self::@augmentation::package:test/a2.dart::@classAugmentation::A
package:test/a2.dart
definingUnit
classAugmentations
augment class A @97
augmentationTarget: self::@augmentation::package:test/a12.dart::@classAugmentation::A
augmentedDeclaration: self::@class::A
augmentation: self::@augmentation::package:test/a21.dart::@classAugmentation::A
augmentationImports
package:test/a21.dart
definingUnit
classAugmentations
augment class A @41
augmentationTarget: self::@augmentation::package:test/a2.dart::@classAugmentation::A
augmentedDeclaration: self::@class::A
augmentation: self::@augmentation::package:test/a22.dart::@classAugmentation::A
package:test/a22.dart
definingUnit
classAugmentations
augment class A @41
augmentationTarget: self::@augmentation::package:test/a21.dart::@classAugmentation::A
augmentedDeclaration: self::@class::A
''');
}
@ -342,6 +395,61 @@ library
''');
}
test_notAugmented_interfaces() async {
var library = await buildLibrary(r'''
class A implements I {}
class I {}
''');
configuration.withAugmentedWithoutAugmentation = true;
checkElementText(library, r'''
library
definingUnit
classes
class A @6
interfaces
I
constructors
synthetic @-1
augmented
interfaces
I
class I @30
constructors
synthetic @-1
augmented
''');
}
test_notAugmented_mixins() async {
var library = await buildLibrary(r'''
class A implements M {}
mixin M {}
''');
configuration.withAugmentedWithoutAugmentation = true;
checkElementText(library, r'''
library
definingUnit
classes
class A @6
interfaces
M
constructors
synthetic @-1
augmented
interfaces
M
mixins
mixin M @30
superclassConstraints
Object
augmented
superclassConstraints
Object
''');
}
test_notSimplyBounded_self() async {
newFile('$testPackageLibPath/a.dart', r'''
library augment 'test.dart';
@ -45341,6 +45449,60 @@ library
''');
}
test_notAugmented_interfaces() async {
var library = await buildLibrary(r'''
mixin A implements I {}
class I {}
''');
configuration.withAugmentedWithoutAugmentation = true;
checkElementText(library, r'''
library
definingUnit
classes
class I @30
constructors
synthetic @-1
augmented
mixins
mixin A @6
superclassConstraints
Object
interfaces
I
augmented
superclassConstraints
Object
interfaces
I
''');
}
test_notAugmented_superclassConstraints() async {
var library = await buildLibrary(r'''
mixin A on B {}
class B {}
''');
configuration.withAugmentedWithoutAugmentation = true;
checkElementText(library, r'''
library
definingUnit
classes
class B @22
constructors
synthetic @-1
augmented
mixins
mixin A @6
superclassConstraints
B
augmented
superclassConstraints
B
''');
}
test_notSimplyBounded_self() async {
newFile('$testPackageLibPath/a.dart', r'''
library augment 'test.dart';