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..690bd04a59fbe08c3cbfcbc966b3c83e193dae87 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>[]; |
} |
/** |
@@ -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 a cycle. |
+ */ |
+ bool isInConstCycle(int slot); |
+ |
+ /** |
* Resolve an [EntityRef] into a constructor. If the reference is |
* unresolved, return `null`. |
*/ |