| // Copyright (c) 2021, 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 'package:analyzer/dart/ast/ast.dart'; | |
| import 'package:analyzer/src/dart/element/element.dart'; | |
| import 'package:analyzer/src/summary2/link.dart'; | |
| /// Resolves the explicit or implicit super-constructors invoked by | |
| /// non-redirecting generative constructors. | |
| class SuperConstructorResolver { | |
| final Linker _linker; | |
| SuperConstructorResolver(this._linker); | |
| void perform() { | |
| for (var builder in _linker.builders.values) { | |
| for (var interfaceElement in <InterfaceElementImpl>[ | |
| ...builder.element.classes, | |
| ...builder.element.enums, | |
| ]) { | |
| for (var constructorElement in interfaceElement.constructors) { | |
| _constructor(interfaceElement, constructorElement); | |
| } | |
| } | |
| } | |
| } | |
| void _constructor( | |
| InterfaceElementImpl interfaceElement, | |
| ConstructorElementImpl element, | |
| ) { | |
| // Constructors of mixin applications are already configured. | |
| if (interfaceElement is ClassElementImpl && | |
| interfaceElement.isMixinApplication) { | |
| return; | |
| } | |
| // We handle only generative constructors here. | |
| if (element.isFactory) { | |
| return; | |
| } | |
| var invokesDefaultSuperConstructor = true; | |
| void handleInitializers(List<ConstructorInitializer> initializers) { | |
| for (var initializer in initializers) { | |
| if (initializer is RedirectingConstructorInvocation) { | |
| invokesDefaultSuperConstructor = false; | |
| } else if (initializer is SuperConstructorInvocation) { | |
| invokesDefaultSuperConstructor = false; | |
| var name = initializer.constructorSelector?.name2.lexeme ?? 'new'; | |
| element.superConstructor = interfaceElement.supertype | |
| ?.getNamedConstructor(name); | |
| } | |
| } | |
| } | |
| for (var fragment in element.fragments) { | |
| var node = _linker.getLinkingNode(fragment); | |
| if (node is ConstructorDeclaration) { | |
| handleInitializers(node.initializers); | |
| } else if (node is PrimaryConstructorDeclaration) { | |
| if (node.body case var body?) { | |
| handleInitializers(body.initializers); | |
| } | |
| } | |
| } | |
| if (invokesDefaultSuperConstructor) { | |
| element.superConstructor = interfaceElement.supertype | |
| ?.getNamedConstructor('new'); | |
| } | |
| } | |
| } |