Deprecate ClassOrMixinDeclaration, use ClassDeclaration or MixinDeclaration.

Change-Id: I23e292e9f7c4413edf9b068f057dd02794db21a8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/254064
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2022-08-08 21:40:40 +00:00 committed by Commit Bot
parent 11e2bf94e3
commit 75b8b916d6
36 changed files with 326 additions and 132 deletions

View file

@ -27,10 +27,12 @@ class DartUnitOverridesComputer {
/// Returns the computed occurrences, not `null`.
List<proto.Override> compute() {
for (var unitMember in _unit.declarations) {
if (unitMember is ClassOrMixinDeclaration) {
if (unitMember is ClassDeclaration) {
_classMembers(unitMember.members);
} else if (unitMember is EnumDeclaration) {
_classMembers(unitMember.members);
} else if (unitMember is MixinDeclaration) {
_classMembers(unitMember.members);
}
}
return _overrides;

View file

@ -33,7 +33,7 @@ class ExtensionMemberContributor extends DartCompletionContributor {
return;
}
var thisClassType = request.target.enclosingClassElement?.thisType;
var thisClassType = request.target.enclosingInterfaceElement?.thisType;
if (thisClassType != null) {
_addExtensionMembers(extensions, defaultKind, thisClassType);
} else {

View file

@ -83,18 +83,21 @@ class LocalReferenceContributor extends DartCompletionContributor {
if (request.includeIdentifiers) {
var member = _enclosingMember(request.target);
if (member != null) {
var classOrMixin = member.parent;
if (classOrMixin is ClassOrMixinDeclaration) {
var declaredElement = classOrMixin.declaredElement;
if (declaredElement != null) {
memberBuilder = MemberSuggestionBuilder(request, builder);
_computeSuggestionsForClass(declaredElement);
}
var enclosingNode = member.parent;
if (enclosingNode is ClassDeclaration) {
_addForInterface(enclosingNode.declaredElement!);
} else if (enclosingNode is MixinDeclaration) {
_addForInterface(enclosingNode.declaredElement!);
}
}
}
}
void _addForInterface(InterfaceElement interface) {
memberBuilder = MemberSuggestionBuilder(request, builder);
_computeSuggestionsForClass(interface);
}
void _addSuggestionsForType(InterfaceType type, double inheritanceDistance,
{bool isFunctionalArgument = false}) {
var opType = request.opType;
@ -142,14 +145,14 @@ class LocalReferenceContributor extends DartCompletionContributor {
}
}
void _computeSuggestionsForClass(ClassElement classElement) {
void _computeSuggestionsForClass(InterfaceElement interface) {
var isFunctionalArgument = request.target.isFunctionalArgument();
classMemberSuggestionKind = isFunctionalArgument
? CompletionSuggestionKind.IDENTIFIER
: CompletionSuggestionKind.INVOCATION;
for (var type in classElement.allSupertypes) {
for (var type in interface.allSupertypes) {
var inheritanceDistance = request.featureComputer
.inheritanceDistanceFeature(classElement, type.element2);
.inheritanceDistanceFeature(interface, type.element2);
_addSuggestionsForType(type, inheritanceDistance,
isFunctionalArgument: isFunctionalArgument);
}

View file

@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
@ -19,23 +20,18 @@ class OverrideContributor extends DartCompletionContributor {
if (target == null) {
return;
}
var classDecl =
target.enclosingNode.thisOrAncestorOfType<ClassOrMixinDeclaration>();
if (classDecl == null) {
return;
}
var inheritance = InheritanceManager3();
// Generate a collection of inherited members
var classElem = classDecl.declaredElement;
if (classElem == null) {
var interfaceElement = target.enclosingNode.enclosingInterfaceElement;
if (interfaceElement == null) {
return;
}
var interface = inheritance.getInterface(classElem);
var interface = inheritance.getInterface(interfaceElement);
var interfaceMap = interface.map;
var namesToOverride =
_namesToOverride(classElem.librarySource.uri, interface);
_namesToOverride(interfaceElement.librarySource.uri, interface);
// Build suggestions
for (var name in namesToOverride) {
@ -52,7 +48,12 @@ class OverrideContributor extends DartCompletionContributor {
/// then return that identifier, otherwise return `null`.
_Target? _getTargetId(CompletionTarget target) {
var node = target.containingNode;
if (node is ClassOrMixinDeclaration) {
if (node is ClassDeclaration) {
var entity = target.entity;
if (entity is FieldDeclaration) {
return _getTargetIdFromVarList(entity.fields);
}
} else if (node is MixinDeclaration) {
var entity = target.entity;
if (entity is FieldDeclaration) {
return _getTargetIdFromVarList(entity.fields);

View file

@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analyzer/dart/ast/ast.dart';
/// A contributor that produces suggestions for constructors that are being
@ -23,9 +24,7 @@ class RedirectingContributor extends DartCompletionContributor {
var containingConstructor =
parent.thisOrAncestorOfType<ConstructorDeclaration>();
var constructorElement = containingConstructor?.declaredElement;
var containingClass = containingConstructor
?.thisOrAncestorOfType<ClassOrMixinDeclaration>();
var classElement = containingClass?.declaredElement;
var classElement = constructorElement?.enclosingElement3;
if (classElement != null) {
for (var constructor in classElement.constructors) {
if (constructor != constructorElement) {
@ -35,10 +34,8 @@ class RedirectingContributor extends DartCompletionContributor {
}
} else if (parent is SuperConstructorInvocation) {
// C() : super.^
var containingClass =
parent.thisOrAncestorOfType<ClassOrMixinDeclaration>();
var superclassElement =
containingClass?.declaredElement?.supertype?.element2;
parent.enclosingInterfaceElement?.supertype?.element2;
if (superclassElement != null) {
for (var constructor in superclassElement.constructors) {
if (constructor.isAccessibleIn2(request.libraryElement)) {
@ -55,9 +52,7 @@ class RedirectingContributor extends DartCompletionContributor {
var containingConstructor =
parent.thisOrAncestorOfType<ConstructorDeclaration>();
var constructorElement = containingConstructor?.declaredElement;
var containingClass =
parent.thisOrAncestorOfType<ClassOrMixinDeclaration>();
var classElement = containingClass?.declaredElement;
var classElement = constructorElement?.enclosingElement3;
var libraryElement = request.libraryElement;
if (classElement == null) {
return;

View file

@ -52,12 +52,11 @@ abstract class CorrectionProducer extends SingleCorrectionProducer {
Future<void> compute(ChangeBuilder builder);
/// Return the class, enum or mixin declaration for the given [element].
Future<ClassOrMixinDeclaration?> getClassOrMixinDeclaration(
InterfaceElement element) async {
/// Return the class for the given [element].
Future<ClassDeclaration?> getClassDeclaration(ClassElement element) async {
var result = await sessionHelper.getElementDeclaration(element);
var node = result?.node;
if (node is ClassOrMixinDeclaration) {
if (node is ClassDeclaration) {
return node;
}
return null;
@ -74,6 +73,16 @@ abstract class CorrectionProducer extends SingleCorrectionProducer {
return null;
}
/// Return the mixin declaration for the given [element].
Future<MixinDeclaration?> getMixinDeclaration(MixinElement element) async {
var result = await sessionHelper.getElementDeclaration(element);
var node = result?.node;
if (node is MixinDeclaration) {
return node;
}
return null;
}
/// Return the class element associated with the [target], or `null` if there
/// is no such class element.
InterfaceElement? getTargetClassElement(Expression target) {

View file

@ -38,7 +38,7 @@ class AddDiagnosticPropertyReference extends CorrectionProducer {
return;
}
var classDeclaration = node.thisOrAncestorOfType<ClassOrMixinDeclaration>();
final classDeclaration = node.thisOrAncestorOfType<ClassDeclaration>();
if (classDeclaration == null ||
!flutter.isDiagnosticable(classDeclaration.declaredElement!.thisType)) {
return;

View file

@ -5,6 +5,7 @@
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
@ -89,7 +90,7 @@ class CreateField extends CorrectionProducer {
staticModifier = targetElement.kind == ElementKind.CLASS;
}
} else {
targetClassElement = getEnclosingClassElement(node);
targetClassElement = node.enclosingInterfaceElement;
staticModifier = inStaticContext;
}
if (targetClassElement == null) {
@ -106,7 +107,10 @@ class CreateField extends CorrectionProducer {
return;
}
var targetNode = targetDeclarationResult.node;
if (targetNode is! ClassOrMixinDeclaration) {
if (targetNode is! CompilationUnitMember) {
return;
}
if (!(targetNode is ClassDeclaration || targetNode is MixinDeclaration)) {
return;
}
// prepare location

View file

@ -5,6 +5,7 @@
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@ -64,7 +65,7 @@ class CreateGetter extends CorrectionProducer {
}
} else {
targetElement =
getEnclosingClassElement(node) ?? getEnclosingExtensionElement(node);
node.enclosingInterfaceElement ?? node.enclosingExtensionElement;
if (targetElement == null) {
return;
}
@ -85,8 +86,9 @@ class CreateGetter extends CorrectionProducer {
}
var targetNode = targetDeclarationResult.node;
if (targetNode is CompilationUnitMember) {
if (targetDeclarationResult.node is! ClassOrMixinDeclaration &&
targetDeclarationResult.node is! ExtensionDeclaration) {
if (targetDeclarationResult.node is! ClassDeclaration &&
targetDeclarationResult.node is! ExtensionDeclaration &&
targetDeclarationResult.node is! MixinDeclaration) {
return;
}
} else {

View file

@ -156,7 +156,11 @@ class CreateMethod extends CorrectionProducer {
return;
}
// prepare target ClassDeclaration
targetNode = await getClassOrMixinDeclaration(targetClassElement);
if (targetClassElement is MixinElement) {
targetNode = await getMixinDeclaration(targetClassElement);
} else if (targetClassElement is ClassElement) {
targetNode = await getClassDeclaration(targetClassElement);
}
if (targetNode == null) {
return;
}

View file

@ -5,6 +5,7 @@
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
@ -43,9 +44,7 @@ class CreateMethodOrFunction extends CorrectionProducer {
return;
}
} else {
var enclosingClass =
node.thisOrAncestorOfType<ClassOrMixinDeclaration>();
targetElement = enclosingClass?.declaredElement;
targetElement = node.enclosingInterfaceElement;
argument = nameNode;
}
}
@ -145,15 +144,23 @@ class CreateMethodOrFunction extends CorrectionProducer {
// prepare environment
var targetSource = targetClassElement.source;
// prepare insert offset
var targetNode = await getClassOrMixinDeclaration(targetClassElement);
if (targetNode == null) {
CompilationUnitMember? targetNode;
List<ClassMember>? classMembers;
if (targetClassElement is MixinElement) {
final node = targetNode = await getMixinDeclaration(targetClassElement);
classMembers = node?.members;
} else if (targetClassElement is ClassElement) {
final node = targetNode = await getClassDeclaration(targetClassElement);
classMembers = node?.members;
}
if (targetNode == null || classMembers == null) {
return;
}
var insertOffset = targetNode.end - 1;
// prepare prefix
var prefix = ' ';
String sourcePrefix;
if (targetNode.members.isEmpty) {
if (classMembers.isEmpty) {
sourcePrefix = '';
} else {
sourcePrefix = eol;

View file

@ -5,6 +5,7 @@
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@ -63,7 +64,7 @@ class CreateSetter extends CorrectionProducer {
}
} else {
targetElement =
getEnclosingClassElement(node) ?? getEnclosingExtensionElement(node);
node.enclosingInterfaceElement ?? node.enclosingExtensionElement;
if (targetElement == null) {
return;
}
@ -84,7 +85,8 @@ class CreateSetter extends CorrectionProducer {
}
var targetNode = targetDeclarationResult.node;
if (targetNode is CompilationUnitMember) {
if (targetDeclarationResult.node is! ClassOrMixinDeclaration &&
if (targetDeclarationResult.node is! ClassDeclaration &&
targetDeclarationResult.node is! MixinDeclaration &&
targetDeclarationResult.node is! ExtensionDeclaration) {
return;
}

View file

@ -53,16 +53,21 @@ class EncapsulateField extends CorrectionProducer {
}
// Should be in a class or mixin.
if (fieldDeclaration.parent is! ClassOrMixinDeclaration) {
List<ClassMember> classMembers;
final parent = fieldDeclaration.parent;
if (parent is ClassDeclaration) {
classMembers = parent.members;
} else if (parent is MixinDeclaration) {
classMembers = parent.members;
} else {
return;
}
var classDeclaration = fieldDeclaration.parent as ClassOrMixinDeclaration;
await builder.addDartFileEdit(file, (builder) {
// rename field
builder.addSimpleReplacement(range.token(nameToken), '_$name');
// update references in constructors
for (var member in classDeclaration.members) {
for (var member in classMembers) {
if (member is ConstructorDeclaration) {
for (var parameter in member.parameters.parameters) {
var identifier = parameter.name;

View file

@ -355,10 +355,12 @@ class ImportLibrary extends MultiCorrectionProducer {
// `this`.
DartType? enclosingThisType(AstNode node) {
var parent = node.parent;
if (parent is ClassOrMixinDeclaration) {
if (parent is ClassDeclaration) {
return parent.declaredElement?.thisType;
} else if (parent is ExtensionDeclaration) {
return parent.extendedType.type;
} else if (parent is MixinDeclaration) {
return parent.declaredElement?.thisType;
} else {
return null;
}

View file

@ -31,33 +31,39 @@ class MakeFieldPublic extends CorrectionProducer {
if (parent is MethodDeclaration &&
parent.name2 == token &&
parent.isGetter) {
NodeList<ClassMember> members;
var container = parent.parent;
if (container is ClassOrMixinDeclaration) {
var members = container.members;
MethodDeclaration? setter;
VariableDeclaration? field;
for (var member in members) {
if (member is MethodDeclaration &&
member.name2.lexeme == getterName &&
member.isSetter) {
setter = member;
} else if (member is FieldDeclaration) {
for (var variable in member.fields.variables) {
if (variable.name2.lexeme == _fieldName) {
field = variable;
}
if (container is ClassDeclaration) {
members = container.members;
} else if (container is MixinDeclaration) {
members = container.members;
} else {
return;
}
MethodDeclaration? setter;
VariableDeclaration? field;
for (var member in members) {
if (member is MethodDeclaration &&
member.name2.lexeme == getterName &&
member.isSetter) {
setter = member;
} else if (member is FieldDeclaration) {
for (var variable in member.fields.variables) {
if (variable.name2.lexeme == _fieldName) {
field = variable;
}
}
}
if (setter == null || field == null) {
return;
}
await builder.addDartFileEdit(file, (builder) {
builder.addSimpleReplacement(range.token(field!.name2), getterName);
builder.removeMember(members, parent);
builder.removeMember(members, setter!);
});
}
if (setter == null || field == null) {
return;
}
await builder.addDartFileEdit(file, (builder) {
builder.addSimpleReplacement(range.token(field!.name2), getterName);
builder.removeMember(members, parent);
builder.removeMember(members, setter!);
});
}
}
}

View file

@ -90,15 +90,17 @@ class MemberSorter {
}
}
/// Sorts all members of all [ClassOrMixinDeclaration]s.
/// Sorts all class members.
void _sortClassesMembers() {
for (var unitMember in unit.declarations) {
if (unitMember is ClassOrMixinDeclaration) {
if (unitMember is ClassDeclaration) {
_sortClassMembers(unitMember.members);
} else if (unitMember is EnumDeclaration) {
_sortClassMembers(unitMember.members);
} else if (unitMember is ExtensionDeclaration) {
_sortClassMembers(unitMember.members);
} else if (unitMember is MixinDeclaration) {
_sortClassMembers(unitMember.members);
}
}
}
@ -165,7 +167,7 @@ class MemberSorter {
for (var member in unit.declarations) {
_MemberKind kind;
String name;
if (member is ClassOrMixinDeclaration) {
if (member is ClassDeclaration) {
kind = _MemberKind.UNIT_CLASS;
name = member.name2.lexeme;
} else if (member is ClassTypeAlias) {
@ -198,6 +200,9 @@ class MemberSorter {
} else if (member is GenericTypeAlias) {
kind = _MemberKind.UNIT_GENERIC_TYPE_ALIAS;
name = member.name2.lexeme;
} else if (member is MixinDeclaration) {
kind = _MemberKind.UNIT_CLASS;
name = member.name2.lexeme;
} else if (member is TopLevelVariableDeclaration) {
var variableDeclaration = member;
List<VariableDeclaration> variables =

View file

@ -233,11 +233,6 @@ String getElementQualifiedName(Element element) {
}
}
/// If the given [node] is in a class, enum or mixin declaration, return the
/// declared [ClassElement]. Otherwise return `null`.
ClassElement? getEnclosingClassElement(AstNode node) =>
node.thisOrAncestorOfType<ClassOrMixinDeclaration>()?.declaredElement;
/// Returns a class or an unit member enclosing the given [input].
AstNode? getEnclosingClassOrUnitMember(AstNode input) {
var member = input;
@ -288,11 +283,6 @@ AstNode? getEnclosingExecutableNode(AstNode input) {
return null;
}
/// If the given [node] is in an extension, return the declared
/// [ExtensionElement]. Otherwise return `null`.
ExtensionElement? getEnclosingExtensionElement(AstNode node) =>
node.thisOrAncestorOfType<ExtensionDeclaration>()?.declaredElement;
/// Returns [getExpressionPrecedence] for the parent of [node], or
/// ASSIGNMENT_PRECEDENCE if the parent node is a [ParenthesizedExpression].
///
@ -1225,28 +1215,34 @@ class CorrectionUtils {
}
Token? _getLeftBracket(CompilationUnitMember declaration) {
if (declaration is ClassOrMixinDeclaration) {
if (declaration is ClassDeclaration) {
return declaration.leftBracket;
} else if (declaration is ExtensionDeclaration) {
return declaration.leftBracket;
} else if (declaration is MixinDeclaration) {
return declaration.leftBracket;
}
return null;
}
List<ClassMember>? _getMembers(CompilationUnitMember declaration) {
if (declaration is ClassOrMixinDeclaration) {
if (declaration is ClassDeclaration) {
return declaration.members;
} else if (declaration is ExtensionDeclaration) {
return declaration.members;
} else if (declaration is MixinDeclaration) {
return declaration.members;
}
return null;
}
Token? _getRightBracket(CompilationUnitMember declaration) {
if (declaration is ClassOrMixinDeclaration) {
if (declaration is ClassDeclaration) {
return declaration.rightBracket;
} else if (declaration is ExtensionDeclaration) {
return declaration.rightBracket;
} else if (declaration is MixinDeclaration) {
return declaration.rightBracket;
}
return null;
}

View file

@ -10,6 +10,7 @@ import 'package:analysis_server/src/services/refactoring/legacy/refactoring_inte
import 'package:analysis_server/src/services/refactoring/legacy/visible_ranges_computer.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analysis_server/src/utilities/strings.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
@ -159,7 +160,7 @@ Set<String> _getNamesConflictingAt(AstNode node) {
}
// fields
{
var enclosingClassElement = getEnclosingClassElement(node);
var enclosingClassElement = node.enclosingInterfaceElement;
if (enclosingClassElement != null) {
var elements = [
...enclosingClassElement.allSupertypes.map((e) => e.element2),

View file

@ -84,7 +84,9 @@ class DartSnippetRequest {
return SnippetContext.inBlock;
}
if (node is ClassOrMixinDeclaration || node is ExtensionDeclaration) {
if (node is ClassDeclaration ||
node is ExtensionDeclaration ||
node is MixinDeclaration) {
return SnippetContext.inClass;
}

View file

@ -20,6 +20,16 @@ extension AnnotatedNodeExtensions on AnnotatedNode {
}
extension AstNodeExtensions on AstNode {
/// Returns [ExtensionElement] declared by an enclosing node.
ExtensionElement? get enclosingExtensionElement {
for (final node in withParents) {
if (node is ExtensionDeclaration) {
return node.declaredElement;
}
}
return null;
}
/// Return the [IfStatement] associated with `this`.
IfStatement? get enclosingIfStatement {
for (var node in withParents) {
@ -32,6 +42,18 @@ extension AstNodeExtensions on AstNode {
return null;
}
/// Returns [InterfaceElement] declared by an enclosing node.
InterfaceElement? get enclosingInterfaceElement {
for (final node in withParents) {
if (node is ClassDeclaration) {
return node.declaredElement;
} else if (node is MixinDeclaration) {
return node.declaredElement;
}
}
return null;
}
/// Return `true` if this node has an `override` annotation.
bool get hasOverride {
var node = this;

View file

@ -1,5 +1,6 @@
## 4.4.1-dev
## 4.5.0-dev
* Update deprecation message for `FormalParameter.identifier`.
* Deprecated `ClassOrMixinDeclaration`, use `ClassDeclaration` and `MixinDeclaration` directly.
## 4.4.0
* Deprecated `ClassDeclaration.isAbstract`, use `abstractKeyword` instead.

View file

@ -878,15 +878,43 @@ abstract class ClassAugmentationDeclaration
// TODO(scheglov) Add `ClassOrAugmentationElement get declaredElement`,
// when [ClassOrMixinDeclaration] is gone.
abstract class ClassDeclaration
implements ClassOrAugmentationDeclaration, ClassOrMixinDeclaration {
implements
ClassOrAugmentationDeclaration,
// ignore: deprecated_member_use_from_same_package
ClassOrMixinDeclaration {
@override
ClassElement? get declaredElement;
/// Returns the implements clause for the class/mixin, or `null` if the
/// class/mixin does not implement any interfaces.
@override
ImplementsClause? get implementsClause;
/// Return `true` if this class is declared to be an abstract class.
@Deprecated('Use abstractKeyword instead')
bool get isAbstract;
/// Returns the left curly bracket.
@override
Token get leftBracket;
/// Returns the members defined by the class/mixin.
@override
NodeList<ClassMember> get members;
/// Return the native clause for this class, or `null` if the class does not
/// have a native clause.
NativeClause? get nativeClause;
/// Returns the right curly bracket.
@override
Token get rightBracket;
/// Returns the type parameters for the class/mixin, or `null` if the
/// class/mixin does not have any type parameters.
@override
TypeParameterList? get typeParameters;
/// Return the constructor declared in the class with the given [name], or
/// `null` if there is no such constructor.
///
@ -950,26 +978,32 @@ abstract class ClassOrAugmentationDeclaration
/// The declaration of a class or mixin.
///
/// Clients may not extend, implement or mix-in this class.
// TODO(scheglov) Deprecate and remove.
@Deprecated('Use ClassDeclaration or MixinDeclaration directly')
abstract class ClassOrMixinDeclaration implements NamedCompilationUnitMember {
@Deprecated('Use ClassDeclaration or MixinDeclaration directly')
@override
ClassElement? get declaredElement;
/// Returns the implements clause for the class/mixin, or `null` if the
/// class/mixin does not implement any interfaces.
@Deprecated('Use ClassDeclaration or MixinDeclaration directly')
ImplementsClause? get implementsClause;
/// Returns the left curly bracket.
@Deprecated('Use ClassDeclaration or MixinDeclaration directly')
Token get leftBracket;
/// Returns the members defined by the class/mixin.
@Deprecated('Use ClassDeclaration or MixinDeclaration directly')
NodeList<ClassMember> get members;
/// Returns the right curly bracket.
@Deprecated('Use ClassDeclaration or MixinDeclaration directly')
Token get rightBracket;
/// Returns the type parameters for the class/mixin, or `null` if the
/// class/mixin does not have any type parameters.
@Deprecated('Use ClassDeclaration or MixinDeclaration directly')
TypeParameterList? get typeParameters;
/// Returns the field declared in the class/mixin with the given [name], or
@ -3529,10 +3563,38 @@ abstract class MixinAugmentationDeclaration
///
/// Clients may not extend, implement or mix-in this class.
abstract class MixinDeclaration
implements MixinOrAugmentationDeclaration, ClassOrMixinDeclaration {
implements
MixinOrAugmentationDeclaration,
// ignore: deprecated_member_use_from_same_package
ClassOrMixinDeclaration {
// TODO(scheglov) Uncomment when removed [ClassOrMixinDeclaration].
// @override
// MixinElement get declaredElement;
@override
ClassElement? get declaredElement;
/// Returns the implements clause for the class/mixin, or `null` if the
/// class/mixin does not implement any interfaces.
@override
ImplementsClause? get implementsClause;
/// Returns the left curly bracket.
@override
Token get leftBracket;
/// Returns the members defined by the class/mixin.
@override
NodeList<ClassMember> get members;
/// Returns the right curly bracket.
@override
Token get rightBracket;
/// Returns the type parameters for the class/mixin, or `null` if the
/// class/mixin does not have any type parameters.
@override
TypeParameterList? get typeParameters;
}
/// Shared interface between [MixinDeclaration] and

View file

@ -343,7 +343,7 @@ class _DeclarationByElementLocator extends UnifyingAstVisitor<void> {
}
if (element is ClassElement) {
if (node is ClassOrMixinDeclaration) {
if (node is ClassDeclaration) {
if (_hasOffset2(node.name2)) {
result = node;
}
@ -355,6 +355,10 @@ class _DeclarationByElementLocator extends UnifyingAstVisitor<void> {
if (_hasOffset2(node.name2)) {
result = node;
}
} else if (node is MixinDeclaration) {
if (_hasOffset2(node.name2)) {
result = node;
}
}
} else if (element is ConstructorElement) {
if (node is ConstructorDeclaration) {

View file

@ -39,8 +39,8 @@ class _UnitApiSignatureComputer {
signature.addInt(unit.declarations.length);
for (var declaration in unit.declarations) {
if (declaration is ClassOrMixinDeclaration) {
_addClassOrMixin(declaration);
if (declaration is ClassDeclaration) {
_addClass(declaration);
} else if (declaration is EnumDeclaration) {
_addEnum(declaration);
} else if (declaration is ExtensionDeclaration) {
@ -52,6 +52,8 @@ class _UnitApiSignatureComputer {
functionExpression.parameters?.endToken ?? declaration.name2,
);
_addFunctionBodyModifiers(functionExpression.body);
} else if (declaration is MixinDeclaration) {
_addMixin(declaration);
} else if (declaration is TopLevelVariableDeclaration) {
_topLevelVariableDeclaration(declaration);
} else {
@ -60,6 +62,15 @@ class _UnitApiSignatureComputer {
}
}
void _addClass(ClassDeclaration node) {
_addTokens(node.beginToken, node.leftBracket);
bool hasConstConstructor = node.members
.any((m) => m is ConstructorDeclaration && m.constKeyword != null);
_addClassMembers(node.members, hasConstConstructor);
}
void _addClassMembers(List<ClassMember> members, bool hasConstConstructor) {
signature.addInt(members.length);
for (var member in members) {
@ -75,15 +86,6 @@ class _UnitApiSignatureComputer {
}
}
void _addClassOrMixin(ClassOrMixinDeclaration node) {
_addTokens(node.beginToken, node.leftBracket);
bool hasConstConstructor = node.members
.any((m) => m is ConstructorDeclaration && m.constKeyword != null);
_addClassMembers(node.members, hasConstConstructor);
}
void _addConstructorDeclaration(ConstructorDeclaration node) {
signature.addInt(_kindConstructorDeclaration);
_addTokens(node.beginToken, node.parameters.endToken);
@ -145,6 +147,11 @@ class _UnitApiSignatureComputer {
signature.addBool(node.invokesSuperSelf);
}
void _addMixin(MixinDeclaration node) {
_addTokens(node.beginToken, node.leftBracket);
_addClassMembers(node.members, false);
}
void _addNode(AstNode? node) {
if (node != null) {
signature.addInt(_notNullNode);

View file

@ -1684,6 +1684,7 @@ class ChildEntity {
/// ([ExtendsClause] [WithClause]?)?
/// [ImplementsClause]?
/// '{' [ClassMember]* '}'
// ignore: deprecated_member_use_from_same_package
class ClassDeclarationImpl extends ClassOrMixinDeclarationImpl
implements ClassDeclaration {
/// The 'abstract' keyword, or `null` if the keyword was absent.
@ -1838,6 +1839,7 @@ abstract class ClassMemberImpl extends DeclarationImpl implements ClassMember {
});
}
@Deprecated('Use ClassDeclaration or MixinDeclaration directly')
abstract class ClassOrMixinDeclarationImpl
extends NamedCompilationUnitMemberImpl implements ClassOrMixinDeclaration {
/// The type parameters for the class or mixin,
@ -8247,6 +8249,7 @@ class MethodInvocationImpl extends InvocationExpressionImpl
/// mixinDeclaration ::=
/// metadata? 'mixin' [SimpleIdentifier] [TypeParameterList]?
/// [RequiresClause]? [ImplementsClause]? '{' [ClassMember]* '}'
// ignore: deprecated_member_use_from_same_package
class MixinDeclarationImpl extends ClassOrMixinDeclarationImpl
implements MixinDeclaration {
/// Return the 'augment' keyword, or `null` if the keyword was absent.

View file

@ -79,12 +79,14 @@ DartType? _writeType(AstNode node) {
extension AstNodeNullableExtension on AstNode? {
List<ClassMember> get classMembers {
final self = this;
if (self is ClassOrMixinDeclaration) {
if (self is ClassDeclaration) {
return self.members;
} else if (self is EnumDeclaration) {
return self.members;
} else if (self is ExtensionDeclaration) {
return self.members;
} else if (self is MixinDeclaration) {
return self.members;
} else {
throw UnimplementedError('(${self.runtimeType}) $self');
}

View file

@ -1089,7 +1089,7 @@ extension on Expression {
if (declarationListParent is FieldDeclaration &&
!declarationListParent.isStatic) {
var container = declarationListParent.parent;
if (container is ClassOrMixinDeclaration) {
if (container is ClassDeclaration) {
var enclosingClass = container.declaredElement;
if (enclosingClass != null) {
// A field initializer of a class with at least one generative

View file

@ -148,7 +148,9 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
.reportErrorForNode(HintCode.INVALID_FACTORY_ANNOTATION, node, []);
}
} else if (element.isImmutable) {
if (parent is! ClassOrMixinDeclaration && parent is! ClassTypeAlias) {
if (parent is! ClassDeclaration &&
parent is! ClassTypeAlias &&
parent is! MixinDeclaration) {
_errorReporter.reportErrorForNode(
HintCode.INVALID_IMMUTABLE_ANNOTATION, node, []);
}

View file

@ -1790,7 +1790,7 @@ class _File {
for (CompilationUnitMember declaration in unit.declarations) {
var comment = declaration.documentationComment;
info.extractTemplate(getCommentNodeRawText(comment));
if (declaration is ClassOrMixinDeclaration) {
if (declaration is ClassDeclaration) {
for (ClassMember member in declaration.members) {
var comment = member.documentationComment;
info.extractTemplate(getCommentNodeRawText(comment));
@ -1800,6 +1800,11 @@ class _File {
var comment = constant.documentationComment;
info.extractTemplate(getCommentNodeRawText(comment));
}
} else if (declaration is MixinDeclaration) {
for (ClassMember member in declaration.members) {
var comment = member.documentationComment;
info.extractTemplate(getCommentNodeRawText(comment));
}
}
}
Map<String, String> templateMap = info.templateMap;

View file

@ -116,7 +116,7 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
node.extendsClause?.accept(this);
node.withClause?.accept(this);
node.implementsClause?.accept(this);
_buildClassOrMixin(node);
_buildClass(node);
}
@override
@ -876,7 +876,7 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
node.onClause?.accept(this);
node.implementsClause?.accept(this);
_buildClassOrMixin(node);
_buildMixin(node);
}
@override
@ -1091,7 +1091,7 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
return _buildAnnotationsWithUnit(_unitElement, nodeList);
}
void _buildClassOrMixin(ClassOrMixinDeclaration node) {
void _buildClass(ClassDeclaration node) {
var element = node.declaredElement as ClassElementImpl;
var hasConstConstructor = node.members.any((e) {
return e is ConstructorDeclaration && e.constKeyword != null;
@ -1103,7 +1103,7 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
_visitPropertyFirst<FieldDeclaration>(node.members);
});
if (node is ClassDeclaration && holder.constructors.isEmpty) {
if (holder.constructors.isEmpty) {
holder.addConstructor(
ConstructorElementImpl('', -1)..isSynthetic = true,
);
@ -1136,6 +1136,26 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
});
}
void _buildMixin(MixinDeclaration node) {
var element = node.declaredElement as MixinElementImpl;
var hasConstConstructor = node.members.any((e) {
return e is ConstructorDeclaration && e.constKeyword != null;
});
// TODO(scheglov) don't create a duplicate
var holder = _EnclosingContext(element.reference!, element,
hasConstConstructor: hasConstConstructor);
_withEnclosing(holder, () {
_visitPropertyFirst<FieldDeclaration>(node.members);
});
element.accessors = holder.propertyAccessors;
element.constructors = holder.constructors;
element.fields = holder.properties.whereType<FieldElement>().toList();
element.methods = holder.methods;
_resolveConstructorFieldFormals(element);
}
void _buildSyntheticVariable({
required String name,
required PropertyAccessorElementImpl accessorElement,

View file

@ -39,7 +39,7 @@ void computeSimplyBounded(Linker linker) {
for (var node in nodes) {
walker.walk(node);
var node2 = node._node;
if (node2 is ClassOrMixinDeclaration) {
if (node2 is ClassDeclaration) {
var element = node2.declaredElement as ClassElementImpl;
element.isSimplyBounded = node.isSimplyBounded;
} else if (node2 is ClassTypeAlias) {
@ -54,6 +54,9 @@ void computeSimplyBounded(Linker linker) {
} else if (node2 is FunctionTypeAlias) {
var element = node2.declaredElement as TypeAliasElementImpl;
element.isSimplyBounded = node.isSimplyBounded;
} else if (node2 is MixinDeclaration) {
var element = node2.declaredElement as MixinElementImpl;
element.isSimplyBounded = node.isSimplyBounded;
} else {
throw UnimplementedError('${node2.runtimeType}');
}

View file

@ -585,9 +585,12 @@ class _MixinsInference {
/// hierarchies for all classes being linked, indiscriminately.
void _resetHierarchies(List<AstNode> declarations) {
for (var declaration in declarations) {
if (declaration is ClassOrMixinDeclaration) {
if (declaration is ClassDeclaration) {
var element = declaration.declaredElement as ClassElementImpl;
element.library.session.classHierarchy.remove(element);
} else if (declaration is MixinDeclaration) {
var element = declaration.declaredElement as MixinElementImpl;
element.library.session.classHierarchy.remove(element);
}
}
}

View file

@ -1,5 +1,5 @@
name: analyzer
version: 4.4.1-dev
version: 4.5.0-dev
description: This package provides a library that performs static analysis of Dart code.
repository: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer

View file

@ -43,8 +43,6 @@ const isClassDeclaration = TypeMatcher<ClassDeclaration>();
const isClassMember = TypeMatcher<ClassMember>();
const isClassOrMixinDeclaration = TypeMatcher<ClassOrMixinDeclaration>();
const isClassTypeAlias = TypeMatcher<ClassTypeAlias>();
const isCombinator = TypeMatcher<Combinator>();

View file

@ -118,10 +118,18 @@ class CompletionTarget {
/// otherwise this is `null`.
ParameterElement? _parameterElement;
/// The enclosing [ClassElement], or `null` if not in a class.
late final ClassElement? enclosingClassElement = containingNode
.thisOrAncestorOfType<ClassOrMixinDeclaration>()
?.declaredElement;
/// The enclosing [InterfaceElement], or `null` if not in a class.
late final InterfaceElement? enclosingInterfaceElement = () {
final unitMember =
containingNode.thisOrAncestorOfType<CompilationUnitMember>();
if (unitMember is ClassDeclaration) {
return unitMember.declaredElement;
} else if (unitMember is MixinDeclaration) {
return unitMember.declaredElement;
} else {
return null;
}
}();
/// The enclosing [ExtensionElement], or `null` if not in an extension.
late final ExtensionElement? enclosingExtensionElement = containingNode

View file

@ -665,12 +665,20 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
DecoratedType? visitClassOrMixinOrExtensionDeclaration(
CompilationUnitMember node) {
assert(node is ClassOrMixinDeclaration || node is ExtensionDeclaration);
assert(node is ClassDeclaration ||
node is ExtensionDeclaration ||
node is MixinDeclaration);
try {
_currentClassOrExtension = node.declaredElement;
var members = node is ClassOrMixinDeclaration
? node.members
: (node as ExtensionDeclaration).members;
List<ClassMember> members;
if (node is ClassDeclaration) {
members = node.members;
} else if (node is ExtensionDeclaration) {
members = node.members;
} else {
members = (node as MixinDeclaration).members;
}
_fieldsNotInitializedAtDeclaration = {
for (var member in members)
@ -2354,7 +2362,7 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
}
}
void _dispatchList(NodeList? nodeList) {
void _dispatchList(List<AstNode>? nodeList) {
if (nodeList == null) return;
for (var node in nodeList) {
_dispatch(node);