Elements. Remove constructors from AugmentedInterfaceElement.

Change-Id: If49bf51b36c0a638ed0b1052a5cc85edb0b7a1b9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/414181
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
This commit is contained in:
Konstantin Shcheglov
2025-03-06 16:39:37 -08:00
committed by Commit Queue
parent 91de656811
commit 79ab37f4cd
20 changed files with 36 additions and 174 deletions
@@ -474,6 +474,7 @@ void f() {
assertHasFileTarget(convertPath(testFilePath), 76, 3);
}
@SkippedTest() // TODO(scheglov): implement augmentation
Future<void> test_class_augmentation_constructor() async {
var aFile = newFile(augmentFilePath, r'''
part of 'test.dart';
@@ -178,6 +178,7 @@ class Foo {
);
}
@SkippedTest() // TODO(scheglov): implement augmentation
Future<void> test_constructorCall_to_augmentation() async {
var code = TestCode.parse('''
part 'other.dart';
@@ -1699,6 +1700,7 @@ class A {
);
}
@SkippedTest() // TODO(scheglov): implement augmentation
Future<void> test_constructor_from_augmentation() async {
var code = TestCode.parse('''
part 'other.dart';
-3
View File
@@ -3019,11 +3019,8 @@ package:analyzer/dart/element/element.dart:
getSetter (method: PropertyAccessorElement? Function(String))
AugmentedInterfaceElement (class extends Object implements AugmentedInstanceElement):
new (constructor: AugmentedInterfaceElement Function())
constructors (getter: List<ConstructorElement>)
firstFragment (getter: InterfaceElement)
thisType (getter: InterfaceType)
unnamedConstructor (getter: ConstructorElement?)
getNamedConstructor (method: ConstructorElement? Function(String))
AugmentedMixinElement (class extends AugmentedInterfaceElement):
new (constructor: AugmentedMixinElement Function())
superclassConstraints (getter: List<InterfaceType>)
@@ -148,23 +148,11 @@ abstract class AugmentedInstanceElement {
///
/// Clients may not extend, implement or mix-in this class.
abstract class AugmentedInterfaceElement implements AugmentedInstanceElement {
/// The constructors declared in this element.
///
/// `ConstructorAugmentationElement`s replace corresponding elements,
/// other [ConstructorElement]s are appended.
List<ConstructorElement> get constructors;
@override
InterfaceElement get firstFragment;
@override
InterfaceType get thisType;
/// The unnamed constructor from [constructors].
ConstructorElement? get unnamedConstructor;
/// Returns the constructor from [constructors] that has the given [name].
ConstructorElement? getNamedConstructor(String name);
}
/// The result of applying augmentations to a [MixinElement].
@@ -100,7 +100,7 @@ import 'package:meta/meta.dart';
// TODO(scheglov): Clean up the list of implicitly analyzed files.
class AnalysisDriver {
/// The version of data format, should be incremented on every format change.
static const int DATA_VERSION = 437;
static const int DATA_VERSION = 440;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
+9 -63
View File
@@ -497,11 +497,6 @@ class ClassElementImpl extends ClassOrMixinElementImpl
implicitConstructor.nameOffset = -1;
implicitConstructor.name2 = superclassConstructor.name2;
implicitConstructor.element = ConstructorElementImpl2(
superclassConstructor.element.name3,
implicitConstructor,
);
var containerRef = reference!.getChild('@constructor');
var referenceName = name.ifNotEmptyOrElse('new');
var implicitReference = containerRef.getChild(referenceName);
@@ -587,8 +582,6 @@ class ClassElementImpl extends ClassOrMixinElementImpl
return implicitConstructor;
}).toList(growable: false);
augmentedInternal.constructors = _constructors;
}
}
@@ -695,7 +688,7 @@ class ClassElementImpl2 extends InterfaceElementImpl2
}
// With only private non-factory constructors.
for (var constructor in constructors) {
for (var constructor in constructors2) {
if (constructor.isPublic || constructor.isFactory) {
return false;
}
@@ -1406,6 +1399,9 @@ class ConstLocalVariableElementImpl extends LocalVariableElementImpl
class ConstructorElementImpl extends ExecutableElementImpl
with AugmentableElement<ConstructorElementImpl>, ConstructorElementMixin
implements ConstructorElement, ConstructorFragment {
late final ConstructorElementImpl2 element =
ConstructorElementImpl2(name.ifNotEmptyOrElse('new'), this);
/// The super-constructor which this constructor is invoking, or `null` if
/// this constructor is not generative, or is redirecting, or the
/// super-constructor is not resolved, or the enclosing class is `Object`.
@@ -1447,9 +1443,6 @@ class ConstructorElementImpl extends ExecutableElementImpl
@override
bool isConstantEvaluated = false;
/// The element corresponding to this fragment.
ConstructorElementImpl2? _element;
/// Initialize a newly created constructor element to have the given [name]
/// and [offset].
ConstructorElementImpl(super.name, super.offset);
@@ -1492,32 +1485,6 @@ class ConstructorElementImpl extends ExecutableElementImpl
}
}
@override
ConstructorElementImpl2 get element {
if (_element != null) {
return _element!;
}
ConstructorFragment firstFragment = this;
var previousFragment = firstFragment.previousFragment;
while (previousFragment != null) {
firstFragment = previousFragment;
previousFragment = firstFragment.previousFragment;
}
firstFragment as ConstructorElementImpl;
// As a side-effect of creating the element, all of the fragments in the
// chain will have their `_element` set to the newly created element.
return ConstructorElementImpl2(
firstFragment.name2,
firstFragment,
);
}
set element(ConstructorElementImpl2 element) {
_element = element;
}
@override
InterfaceElementImpl get enclosingElement3 =>
super.enclosingElement3 as InterfaceElementImpl;
@@ -1675,13 +1642,7 @@ class ConstructorElementImpl2 extends ExecutableElementImpl2
@override
final ConstructorElementImpl firstFragment;
ConstructorElementImpl2(this.name3, this.firstFragment) {
ConstructorElementImpl? fragment = firstFragment;
while (fragment != null) {
fragment.element = this;
fragment = fragment.nextFragment;
}
}
ConstructorElementImpl2(this.name3, this.firstFragment);
@override
ConstructorElementImpl2 get baseElement => this;
@@ -6683,9 +6644,6 @@ abstract class InterfaceElementImpl2 extends InstanceElementImpl2
/// Should be used only when the element has no type parameters.
InterfaceTypeImpl? _nullableInstance;
@override
List<ConstructorElementMixin> constructors = [];
InterfaceTypeImpl? _thisType;
@override
@@ -6702,8 +6660,8 @@ abstract class InterfaceElementImpl2 extends InstanceElementImpl2
@override
List<ConstructorElementImpl2> get constructors2 {
_readMembers();
return constructors
.map((constructor) => constructor.declaration.element)
return firstFragment.constructors
.map((constructor) => constructor.element)
.toList();
}
@@ -6781,16 +6739,10 @@ abstract class InterfaceElementImpl2 extends InstanceElementImpl2
}
@override
ConstructorElementMixin? get unnamedConstructor {
// TODO(scheglov): this is a hack
firstFragment.constructors;
return constructors.firstWhereOrNull((element) => element.name.isEmpty);
ConstructorElementMixin2? get unnamedConstructor2 {
return getNamedConstructor2('new');
}
@override
ConstructorElementMixin2? get unnamedConstructor2 =>
unnamedConstructor?.asElement2;
@override
ExecutableElement2? getInheritedConcreteMember(Name name) =>
inheritedConcreteMembers[name];
@@ -6807,12 +6759,6 @@ abstract class InterfaceElementImpl2 extends InstanceElementImpl2
.inheritanceManager
.getMember4(this, name);
@override
ConstructorElementMixin? getNamedConstructor(String name) {
name = name.ifEqualThen('new', '');
return constructors.firstWhereOrNull((element) => element.name == name);
}
@override
ConstructorElementMixin2? getNamedConstructor2(String name) {
return constructors2.firstWhereOrNull((e) => e.name3 == name);
+2 -17
View File
@@ -961,23 +961,8 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
@Deprecated('Use lookUpConstructor2() instead')
@override
ConstructorElementMixin? lookUpConstructor(
String? constructorName, LibraryElement library) {
var augmented = element.element;
// prepare base ConstructorElement
ConstructorElementMixin? constructorElement;
if (constructorName == null) {
constructorElement = augmented.unnamedConstructor;
} else {
constructorElement = augmented.getNamedConstructor(constructorName);
}
// not found or not accessible
if (constructorElement == null ||
!constructorElement.isAccessibleIn(library)) {
return null;
}
// return member
return ConstructorMember.from(constructorElement, this);
String? constructorName, covariant LibraryElementImpl library) {
return lookUpConstructor2(constructorName ?? 'new', library)?.asElement;
}
@override
@@ -489,8 +489,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
var moreChecks = _checkClassInheritance(
declarationElement, node, superclass, withClause, implementsClause);
if (moreChecks) {
_checkForNoDefaultSuperConstructorImplicit(
declaredFragment, augmented);
_checkForNoDefaultSuperConstructorImplicit(declaredFragment);
}
}
@@ -4670,22 +4669,21 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
}
}
/// Check that if the given class [element] implicitly calls default
/// Check that if the given class [fragment] implicitly calls default
/// constructor of its superclass, there should be such default constructor -
/// implicit or explicit.
///
/// See [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT].
void _checkForNoDefaultSuperConstructorImplicit(
ClassElementImpl element,
AugmentedClassElement augmented,
ClassElementImpl fragment,
) {
// do nothing if there is explicit constructor
var constructors = augmented.constructors;
var constructors = fragment.element.constructors2;
if (!constructors[0].isSynthetic) {
return;
}
// prepare super
var superType = element.supertype;
var superType = fragment.supertype;
if (superType == null) {
return;
}
@@ -4695,11 +4693,11 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
if (superUnnamedConstructor != null) {
if (superUnnamedConstructor.isFactory) {
errorReporter.atElement2(
element.asElement2,
fragment.asElement2,
CompileTimeErrorCode.NON_GENERATIVE_IMPLICIT_CONSTRUCTOR,
arguments: [
superElement.name,
element.name,
fragment.name,
superUnnamedConstructor,
],
);
@@ -4714,9 +4712,9 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
// Don't report this diagnostic for non-subtypable classes because the
// real problem was already reported.
errorReporter.atElement2(
element.asElement2,
fragment.asElement2,
CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT,
arguments: [superType, element.displayName],
arguments: [superType, fragment.displayName],
);
}
}
@@ -273,12 +273,6 @@ abstract class InstanceElementBuilder<E extends InstanceElementImpl2,
element.fields.addAll(firstFragment.fields);
element.accessors.addAll(firstFragment.accessors);
if (element is InterfaceElementImpl2) {
if (firstFragment is InterfaceElementImpl) {
element.constructors.addAll(firstFragment.constructors);
}
}
if (element is MixinElementImpl2) {
if (firstFragment is MixinElementImpl) {
element.superclassConstraints.addAll(
@@ -301,7 +295,6 @@ abstract class InstanceElementBuilder<E extends InstanceElementImpl2,
void _updatedAugmented(InstanceElementImpl augmentation) {
var element = this.element;
var firstFragment = this.firstFragment;
var firstTypeParameters = element.typeParameters2;
MapSubstitution toFirstFragment;
@@ -327,24 +320,6 @@ abstract class InstanceElementBuilder<E extends InstanceElementImpl2,
);
}
if (augmentation is InterfaceElementImpl &&
firstFragment is InterfaceElementImpl &&
element is InterfaceElementImpl2) {
element.constructors = [
...element.constructors.notAugmented,
...augmentation.constructors.notAugmented.map((element) {
if (toFirstFragment.map.isEmpty) {
return element;
}
return ConstructorMember(
declaration: element,
augmentationSubstitution: toFirstFragment,
substitution: Substitution.empty,
);
}),
];
}
element.fields = [
...element.fields.notAugmented,
...augmentation.fields.notAugmented.map((element) {
@@ -143,7 +143,6 @@ class ClassElementLinkedData extends ElementLinkedData<ClassElementImpl> {
if (element.augmentationTarget == null) {
var augmented = element.augmentedInternal;
augmented.fields = reader.readElementList();
augmented.constructors = reader.readElementList();
augmented.accessors = reader.readElementList();
}
@@ -381,7 +380,6 @@ class EnumElementLinkedData extends ElementLinkedData<EnumElementImpl> {
if (element.augmentationTarget == null) {
var augmented = element.augmentedInternal;
augmented.fields = reader.readElementList();
augmented.constructors = reader.readElementList();
augmented.accessors = reader.readElementList();
}
applyConstantOffsets?.perform();
@@ -449,7 +447,6 @@ class ExtensionTypeElementLinkedData
var augmented = element.augmentedInternal;
augmented.fields = reader.readElementList();
augmented.accessors = reader.readElementList();
augmented.constructors = reader.readElementList();
augmented
..primaryConstructor = element.constructors.first
..representation = element.fields.first
@@ -160,7 +160,6 @@ class BundleWriter {
if (fragment.augmentationTarget == null) {
var element = fragment.element;
_resolutionSink._writeElementList(element.fields);
_resolutionSink._writeElementList(element.constructors);
_resolutionSink._writeElementList(element.accessors);
}
@@ -251,7 +250,6 @@ class BundleWriter {
if (fragment.augmentationTarget == null) {
var element = fragment.element;
_resolutionSink._writeElementList(element.fields);
_resolutionSink._writeElementList(element.constructors);
_resolutionSink._writeElementList(element.accessors);
}
@@ -344,7 +342,6 @@ class BundleWriter {
var element = fragment.element;
_resolutionSink._writeElementList(element.fields);
_resolutionSink._writeElementList(element.accessors);
_resolutionSink._writeElementList(element.constructors);
_resolutionSink.writeType(element.typeErasure);
}
@@ -141,19 +141,11 @@ class LibraryBuilder {
}
void buildClassSyntheticConstructors() {
bool hasConstructor(ClassElementImpl element) {
if (element.constructors.isNotEmpty) return true;
if (element.augmentation case var augmentation?) {
return hasConstructor(augmentation);
}
return false;
}
for (var classFragment in element.topLevelElements) {
if (classFragment is! ClassElementImpl) continue;
if (classFragment.isMixinApplication) continue;
if (classFragment.augmentationTarget != null) continue;
if (hasConstructor(classFragment)) continue;
if (classFragment.constructors.isNotEmpty) continue;
var constructor = ConstructorElementImpl('', -1)..isSynthetic = true;
var containerRef = classFragment.reference!.getChild('@constructor');
@@ -164,7 +156,6 @@ class LibraryBuilder {
constructor.name2 = 'new';
classFragment.constructors = [constructor].toFixedList();
classFragment.element.constructors = classFragment.constructors;
}
}
@@ -209,8 +200,8 @@ class LibraryBuilder {
void buildEnumSyntheticConstructors() {
bool hasConstructor(EnumElementImpl fragment) {
for (var constructor in fragment.element.constructors) {
if (constructor.isGenerative || constructor.name == '') {
for (var constructor in fragment.element.constructors2) {
if (constructor.isGenerative || constructor.name3 == 'new') {
return true;
}
}
@@ -236,8 +227,6 @@ class LibraryBuilder {
...enumFragment.constructors,
constructor,
].toFixedList();
enumFragment.element.constructors = enumFragment.constructors;
}
}
@@ -285,7 +274,7 @@ class LibraryBuilder {
if (classFragment is! ClassElementImpl) continue;
if (classFragment.isMixinApplication) continue;
if (classFragment.isAugmentation) continue;
var hasConst = classFragment.element.constructors.any((e) => e.isConst);
var hasConst = classFragment.element.constructors2.any((e) => e.isConst);
if (hasConst) {
withConstConstructors.add(classFragment);
}
@@ -945,7 +945,6 @@ class _MockSdkElementsBuilder {
void _buildClassElement(ClassElementImpl fragment) {
var element = fragment.element;
element.fields = fragment.fields;
element.constructors = fragment.constructors;
element.accessors = fragment.accessors;
}
@@ -845,6 +845,7 @@ class C {
''');
}
@SkippedTest() // TODO(scheglov): implement augmentation
test_searchReferences_class_constructor_declaredInAugmentation() async {
newFile('$testPackageLibPath/a.dart', r'''
part of 'test.dart';
@@ -2050,17 +2050,6 @@ class _ElementWriter extends _AbstractElementWriter {
_elementPrinter.writeElementList('fields', sorted);
}
void writeConstructors() {
if (!configuration.withConstructors) {
return;
}
if (element is InterfaceElementImpl2) {
var sorted = element.constructors.sortedBy((e) => e.name);
expect(sorted, isNotEmpty);
_elementPrinter.writeElementList('constructors', sorted);
}
}
void writeAccessors() {
var sorted = element.accessors.sortedBy((e) => e.name);
_elementPrinter.writeElementList('accessors', sorted);
@@ -2073,7 +2062,6 @@ class _ElementWriter extends _AbstractElementWriter {
_elementPrinter.writeTypeList('mixins', element.mixins);
_elementPrinter.writeTypeList('interfaces', element.interfaces);
writeFields();
writeConstructors();
writeAccessors();
case EnumElementImpl2():
_elementPrinter.writeTypeList('mixins', element.mixins);
@@ -2083,7 +2071,6 @@ class _ElementWriter extends _AbstractElementWriter {
'constants',
element.constants.sortedBy((e) => e.name),
);
writeConstructors();
writeAccessors();
case ExtensionElementImpl2():
writeFields();
@@ -2091,7 +2078,6 @@ class _ElementWriter extends _AbstractElementWriter {
case ExtensionTypeElementImpl2():
_elementPrinter.writeTypeList('interfaces', element.interfaces);
writeFields();
writeConstructors();
writeAccessors();
case MixinElementImpl2():
_elementPrinter.writeTypeList(
@@ -10914,8 +10914,6 @@ library
fields
<testLibraryFragment>::@class::C::@field::foo::@def::0
<testLibraryFragment>::@class::C::@field::foo::@def::1
constructors
<testLibraryFragment>::@class::C::@constructor::new
accessors
<testLibraryFragment>::@class::C::@getter::foo::@def::0
<testLibraryFragment>::@class::C::@getter::foo::@def::1
@@ -11059,8 +11057,6 @@ library
fields
<testLibraryFragment>::@class::C::@field::foo::@def::0
<testLibraryFragment>::@class::C::@field::foo::@def::1
constructors
<testLibraryFragment>::@class::C::@constructor::new
accessors
<testLibraryFragment>::@class::C::@getter::foo
<testLibraryFragment>::@class::C::@setter::foo::@def::0
@@ -1043,8 +1043,6 @@ library
reference: <testLibraryFragment>::@class::A::@constructor::new
enclosingElement3: <testLibraryFragment>::@class::A
augmented
constructors
<testLibraryFragment>::@class::A::@constructor::new
<testLibrary>::@fragment::package:test/a.dart
enclosingElement3: <testLibraryFragment>
classes
@@ -17,6 +17,7 @@ class AvoidFieldInitializersInConstClassesTest extends LintRuleTest {
@override
String get lintRule => LintNames.avoid_field_initializers_in_const_classes;
@SkippedTest() // TODO(scheglov): implement augmentation
test_augmentationClass_nonConstConstructor() async {
var a = newFile('$testPackageLibPath/a.dart', r'''
part 'b.dart';
@@ -80,6 +81,7 @@ augment class A {
''');
}
@SkippedTest() // TODO(scheglov): implement augmentation
test_augmentedClass_constructorInitializer() async {
newFile('$testPackageLibPath/a.dart', r'''
part 'test.dart';
@@ -100,6 +102,7 @@ augment class A {
);
}
@SkippedTest() // TODO(scheglov): implement augmentation
test_augmentedClass_constructorInitializer_multipleConstructors() async {
newFile('$testPackageLibPath/a.dart', r'''
part 'test.dart';
@@ -17,6 +17,7 @@ class UseEnumsTest extends LintRuleTest {
@override
String get lintRule => LintNames.use_enums;
@SkippedTest() // TODO(scheglov): implement augmentation
test_augmentation() async {
var a = newFile('$testPackageLibPath/a.dart', r'''
part 'b.dart';
@@ -55,6 +55,7 @@ abstract class MyWidget extends StatelessWidget {
);
}
@SkippedTest() // TODO(scheglov): implement augmentation
test_constructorInAugmentedClass() async {
newFile('$testPackageLibPath/a.dart', r'''
import 'package:flutter/widgets.dart';
@@ -82,6 +83,7 @@ augment class W {
);
}
@SkippedTest() // TODO(scheglov): implement augmentation
test_constructorInAugmentedClass_noKeyParam() async {
newFile('$testPackageLibPath/a.dart', r'''
import 'package:flutter/widgets.dart';
@@ -149,6 +151,7 @@ abstract class MyWidget extends StatelessWidget {
''');
}
@SkippedTest() // TODO(scheglov): implement augmentation
test_keyUse_inAugmentedConstructor() async {
newFile('$testPackageLibPath/a.dart', r'''
part of 'test.dart';