Chromium Code Reviews| Index: pkg/analyzer/lib/src/dart/element/element.dart |
| diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart |
| index 7c1e056917cbf7af237cbf95e6229ffb651e92c1..a0c0c4ccd46b510bf509cff6af3b9f2a214a17c0 100644 |
| --- a/pkg/analyzer/lib/src/dart/element/element.dart |
| +++ b/pkg/analyzer/lib/src/dart/element/element.dart |
| @@ -527,11 +527,26 @@ class ClassElementImpl extends AbstractClassElementImpl |
| @override |
| List<ConstructorElement> get constructors { |
| - if (!isMixinApplication) { |
| - assert(_constructors != null); |
| - return _constructors ?? ConstructorElement.EMPTY_LIST; |
| + if (isMixinApplication) { |
| + return _computeMixinAppConstructors(); |
| } |
| - return _computeMixinAppConstructors(); |
| + if (_unlinkedClass != null && _constructors == null) { |
| + _constructors = _unlinkedClass.executables |
| + .where((e) => e.kind == UnlinkedExecutableKind.constructor) |
| + .map((e) => new ConstructorElementImpl.forSerialized(e, this)) |
| + .toList(growable: false); |
| + // Ensure at least implicit default constructor. |
| + if (_constructors.isEmpty) { |
| + ConstructorElementImpl constructor = new ConstructorElementImpl('', -1); |
| + constructor.enclosingElement = this; |
| + constructor.synthetic = true; |
| + constructor.type = new FunctionTypeImpl.elementWithNameAndArgs( |
| + constructor, null, type.typeArguments, false); |
| + _constructors = <ConstructorElement>[constructor]; |
| + } |
| + } |
| + assert(_constructors != null); |
| + return _constructors ?? const <ConstructorElement>[]; |
|
Brian Wilkerson
2016/06/03 16:06:34
This doesn't make sense. If _constructors is not n
scheglov
2016/06/03 16:10:38
I agree, but this change just keeps the previous s
Brian Wilkerson
2016/06/03 16:18:15
Ok, I see. Are we doing the same everywhere that w
Paul Berry
2016/06/03 16:21:50
Yes, that was my intention when I wrote this code,
|
| } |
| /** |
| @@ -540,6 +555,7 @@ class ClassElementImpl extends AbstractClassElementImpl |
| * Should only be used for class elements that are not mixin applications. |
| */ |
| void set constructors(List<ConstructorElement> constructors) { |
| + assert(_unlinkedClass == null); |
| assert(!isMixinApplication); |
| for (ConstructorElement constructor in constructors) { |
| (constructor as ConstructorElementImpl).enclosingElement = this; |
| @@ -1678,11 +1694,6 @@ class ConstLocalVariableElementImpl extends LocalVariableElementImpl |
| class ConstructorElementImpl extends ExecutableElementImpl |
| implements ConstructorElement { |
| /** |
| - * Set of slots corresponding to const constructors that are part of cycles. |
| - */ |
| - final Set<int> _constCycles; |
| - |
| - /** |
| * The constructor to which this constructor is redirecting. |
| */ |
| ConstructorElement _redirectedConstructor; |
| @@ -1714,22 +1725,18 @@ class ConstructorElementImpl extends ExecutableElementImpl |
| * Initialize a newly created constructor element to have the given [name] and |
| * [offset]. |
| */ |
| - ConstructorElementImpl(String name, int offset) |
| - : _constCycles = null, |
| - super(name, offset); |
| + ConstructorElementImpl(String name, int offset) : super(name, offset); |
| /** |
| * Initialize a newly created constructor element to have the given [name]. |
| */ |
| - ConstructorElementImpl.forNode(Identifier name) |
| - : _constCycles = null, |
| - super.forNode(name); |
| + ConstructorElementImpl.forNode(Identifier name) : super.forNode(name); |
| /** |
| * Initialize using the given serialized information. |
| */ |
| - ConstructorElementImpl.forSerialized(UnlinkedExecutable serializedExecutable, |
| - this._constCycles, ClassElementImpl enclosingClass) |
| + ConstructorElementImpl.forSerialized( |
| + UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass) |
| : super.forSerialized(serializedExecutable, enclosingClass); |
| /** |
| @@ -1782,7 +1789,8 @@ class ConstructorElementImpl extends ExecutableElementImpl |
| bool get isCycleFree { |
| if (serializedExecutable != null) { |
| return serializedExecutable.isConst && |
| - !_constCycles.contains(serializedExecutable.constCycleSlot); |
| + !enclosingUnit.resynthesizerContext |
| + .isInConstCycle(serializedExecutable.constCycleSlot); |
| } |
| return _isCycleFree; |
| } |
| @@ -7394,6 +7402,11 @@ abstract class ResynthesizerContext { |
| UnitExplicitTopLevelVariables buildTopLevelVariables(); |
| /** |
| + * Return `true` if the given const constructor [slot] is a part of cycle. |
| + */ |
| + bool isInConstCycle(int slot); |
| + |
| + /** |
| * Resolve an [EntityRef] into a constructor. If the reference is |
| * unresolved, return `null`. |
| */ |