blob: f829f81a1f5b0bb76b4efb9eb16875dd43f806d6 [file] [log] [blame]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// 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.
import '../base/problems.dart';
import '../builder/builder.dart';
import '../builder/constructor_reference_builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/member_builder.dart';
import '../builder/name_iterator.dart';
import 'source_factory_builder.dart';
import 'source_library_builder.dart';
/// Common interface for builders for a class declarations in source code, such
/// as a regular class declaration and an extension type declaration.
// TODO(johnniwinther): Should this be renamed now that inline classes are
// renamed to extension type declarations?
abstract class ClassDeclaration
implements IDeclarationBuilder, ClassMemberAccess {
@override
SourceLibraryBuilder get libraryBuilder;
bool get isMixinDeclaration;
int resolveConstructors(SourceLibraryBuilder library);
/// [Iterator] for all members declared directly in this class, including
/// augmenting members.
///
/// Duplicates are _not_ included.
///
/// For instance:
///
/// class Class {
/// // Declared, so it is included for this class but not for the
/// // augmentation class below.
/// method() {}
/// // Declared, so it is included for this class but not for the
/// // augmentation class below.
/// method2() {}
/// method2() {} // Duplicate, so it is *not* included.
/// }
///
/// augment class Class {
/// // Augmenting, so it is included for this augmentation class but
/// // not for the origin class above.
/// augment method() {}
/// // Declared, so it is included for this augmentation class but not
/// // for the origin class above.
/// extra() {}
/// }
///
Iterator<T> localMemberIterator<T extends Builder>();
/// [Iterator] for all constructors declared directly in this class, including
/// augmenting constructors.
///
/// For instance:
///
/// class Class {
/// // Declared, so it is included for this class but not for the
/// // augmentation class below.
/// Class();
/// // Declared, so it is included for this class but not for the
/// // augmentation class below.
/// Class.named();
/// Class.named(); // Duplicate, so it is *not* included.
/// }
///
/// augment class Class {
/// // Augmenting, so it is included for this augmentation class but
/// // not for the origin class above.
/// augment Class();
/// // Declared, so it is included for this augmentation class but not
/// // for the origin class above.
/// Class.extra();
/// }
///
Iterator<T> localConstructorIterator<T extends MemberBuilder>();
}
mixin ClassDeclarationMixin implements ClassDeclaration {
List<ConstructorReferenceBuilder>? get constructorReferences;
@override
int resolveConstructors(SourceLibraryBuilder library) {
if (constructorReferences == null) return 0;
for (ConstructorReferenceBuilder ref in constructorReferences!) {
ref.resolveIn(scope, library);
}
int count = constructorReferences!.length;
if (count != 0) {
Iterator<MemberBuilder> iterator = nameSpace.filteredConstructorIterator(
parent: this, includeDuplicates: true, includeAugmentations: true);
while (iterator.moveNext()) {
MemberBuilder declaration = iterator.current;
if (declaration.declarationBuilder?.origin != origin) {
unexpected("$fileUri", "${declaration.declarationBuilder!.fileUri}",
fileOffset, fileUri);
}
if (declaration is SourceFactoryBuilder) {
declaration.resolveRedirectingFactory();
}
}
}
return count;
}
}
abstract class ClassDeclarationAugmentationAccess<D extends ClassDeclaration> {
D getOrigin(D classDeclaration);
Iterable<D>? getAugmentations(D classDeclaration);
}
class ClassDeclarationMemberIterator<D extends ClassDeclaration,
T extends Builder> implements Iterator<T> {
Iterator<T>? _iterator;
Iterator<D>? augmentationBuilders;
final bool includeDuplicates;
factory ClassDeclarationMemberIterator.full(
ClassDeclarationAugmentationAccess<D> access, D classBuilder,
{required bool includeDuplicates}) {
return new ClassDeclarationMemberIterator._(access.getOrigin(classBuilder),
access.getAugmentations(classBuilder)?.iterator,
includeDuplicates: includeDuplicates);
}
// Coverage-ignore(suite): Not run.
factory ClassDeclarationMemberIterator.local(D classBuilder,
{required bool includeDuplicates}) {
return new ClassDeclarationMemberIterator._(classBuilder, null,
includeDuplicates: includeDuplicates);
}
ClassDeclarationMemberIterator._(
D classDeclaration, this.augmentationBuilders,
{required this.includeDuplicates})
: _iterator = classDeclaration.nameSpace.filteredIterator<T>(
parent: classDeclaration,
includeDuplicates: includeDuplicates,
includeAugmentations: false);
@override
bool moveNext() {
if (_iterator != null) {
if (_iterator!.moveNext()) {
return true;
}
}
if (augmentationBuilders != null && augmentationBuilders!.moveNext()) {
D augmentationClassDeclaration = augmentationBuilders!.current;
_iterator = augmentationClassDeclaration.nameSpace.filteredIterator<T>(
parent: augmentationClassDeclaration,
includeDuplicates: includeDuplicates,
includeAugmentations: false);
}
if (_iterator != null) {
if (_iterator!.moveNext()) {
return true;
}
}
return false;
}
@override
T get current =>
_iterator?.current ?? // Coverage-ignore(suite): Not run.
(throw new StateError('No element'));
}
// Coverage-ignore(suite): Not run.
class ClassDeclarationMemberNameIterator<D extends ClassDeclaration,
T extends Builder> implements NameIterator<T> {
NameIterator<T>? _iterator;
Iterator<D>? augmentationBuilders;
final bool includeDuplicates;
factory ClassDeclarationMemberNameIterator(
ClassDeclarationAugmentationAccess<D> access, D classBuilder,
{required bool includeDuplicates}) {
return new ClassDeclarationMemberNameIterator._(
access.getOrigin(classBuilder),
access.getAugmentations(classBuilder)?.iterator,
includeDuplicates: includeDuplicates);
}
ClassDeclarationMemberNameIterator._(
D classDeclaration, this.augmentationBuilders,
{required this.includeDuplicates})
: _iterator = classDeclaration.nameSpace.filteredNameIterator<T>(
parent: classDeclaration,
includeDuplicates: includeDuplicates,
includeAugmentations: false);
@override
bool moveNext() {
if (_iterator != null) {
if (_iterator!.moveNext()) {
return true;
}
}
if (augmentationBuilders != null && augmentationBuilders!.moveNext()) {
D augmentationClassDeclaration = augmentationBuilders!.current;
_iterator = augmentationClassDeclaration.nameSpace
.filteredNameIterator<T>(
parent: augmentationClassDeclaration,
includeDuplicates: includeDuplicates,
includeAugmentations: false);
}
if (_iterator != null) {
if (_iterator!.moveNext()) {
return true;
}
}
return false;
}
@override
T get current => _iterator?.current ?? (throw new StateError('No element'));
@override
String get name => _iterator?.name ?? (throw new StateError('No element'));
}
class ClassDeclarationConstructorIterator<D extends ClassDeclaration,
T extends MemberBuilder> implements Iterator<T> {
Iterator<T>? _iterator;
Iterator<D>? augmentationBuilders;
final bool includeDuplicates;
factory ClassDeclarationConstructorIterator.full(
ClassDeclarationAugmentationAccess<D> access, D classBuilder,
{required bool includeDuplicates}) {
return new ClassDeclarationConstructorIterator._(
access.getOrigin(classBuilder),
access.getAugmentations(classBuilder)?.iterator,
includeDuplicates: includeDuplicates);
}
// Coverage-ignore(suite): Not run.
factory ClassDeclarationConstructorIterator.local(D classBuilder,
{required bool includeDuplicates}) {
return new ClassDeclarationConstructorIterator._(classBuilder, null,
includeDuplicates: includeDuplicates);
}
ClassDeclarationConstructorIterator._(
D classDeclaration, this.augmentationBuilders,
{required this.includeDuplicates})
: _iterator = classDeclaration.nameSpace.filteredConstructorIterator<T>(
parent: classDeclaration,
includeDuplicates: includeDuplicates,
includeAugmentations: false);
@override
bool moveNext() {
if (_iterator != null) {
if (_iterator!.moveNext()) {
return true;
}
}
if (augmentationBuilders != null && augmentationBuilders!.moveNext()) {
D augmentationClassDeclaration = augmentationBuilders!.current;
_iterator = augmentationClassDeclaration.nameSpace
.filteredConstructorIterator<T>(
parent: augmentationClassDeclaration,
includeDuplicates: includeDuplicates,
includeAugmentations: false);
}
if (_iterator != null) {
if (_iterator!.moveNext()) {
return true;
}
}
return false;
}
@override
T get current =>
_iterator?.current ?? // Coverage-ignore(suite): Not run.
(throw new StateError('No element'));
}
class ClassDeclarationConstructorNameIterator<D extends ClassDeclaration,
T extends MemberBuilder> implements NameIterator<T> {
NameIterator<T>? _iterator;
Iterator<D>? augmentationBuilders;
final bool includeDuplicates;
factory ClassDeclarationConstructorNameIterator(
ClassDeclarationAugmentationAccess<D> access, D classDeclaration,
{required bool includeDuplicates}) {
return new ClassDeclarationConstructorNameIterator._(
access.getOrigin(classDeclaration),
access.getAugmentations(classDeclaration)?.iterator,
includeDuplicates: includeDuplicates);
}
ClassDeclarationConstructorNameIterator._(
D classBuilder, this.augmentationBuilders,
{required this.includeDuplicates})
: _iterator = classBuilder.nameSpace.filteredConstructorNameIterator<T>(
parent: classBuilder,
includeDuplicates: includeDuplicates,
includeAugmentations: false);
@override
bool moveNext() {
if (_iterator != null) {
if (_iterator!.moveNext()) {
return true;
}
}
if (augmentationBuilders != null && augmentationBuilders!.moveNext()) {
D augmentationClassDeclaration = augmentationBuilders!.current;
_iterator = augmentationClassDeclaration.nameSpace
.filteredConstructorNameIterator<T>(
parent: augmentationClassDeclaration,
includeDuplicates: includeDuplicates,
includeAugmentations: false);
}
if (_iterator != null) {
if (_iterator!.moveNext()) {
return true;
}
}
return false;
}
@override
T get current =>
_iterator?.current ?? // Coverage-ignore(suite): Not run.
(throw new StateError('No element'));
@override
String get name =>
_iterator?.name ?? // Coverage-ignore(suite): Not run.
(throw new StateError('No element'));
}