Chromium Code Reviews| Index: pkg/analyzer/lib/src/summary/link.dart |
| diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart |
| index 57dccf1191c88f3731f2a2cb3bb331b329eeebcb..63195a2414e5405c1dd266db15f1269bd44f9fb9 100644 |
| --- a/pkg/analyzer/lib/src/summary/link.dart |
| +++ b/pkg/analyzer/lib/src/summary/link.dart |
| @@ -1241,6 +1241,9 @@ class CompilationUnitElementInBuildUnit extends CompilationUnitElementForLink { |
| for (TopLevelVariableElementForLink variable in topLevelVariables) { |
| variable.link(this); |
| } |
| + for (TopLevelFunctionElementForLink function in functions) { |
| + function.link(this); |
| + } |
| } |
| for (ClassElementForLink classElement in types) { |
| classElement.link(this); |
| @@ -2976,6 +2979,116 @@ class FunctionElementForLink_Initializer extends Object |
| } |
| /** |
| + * Element representing the initializer expression of a parameter. |
| + */ |
| +class FunctionElementForLink_ParameterInitializer extends Object |
|
Jennifer Messerly
2016/06/25 00:37:46
this is almost entirely a copy+paste of FunctionEl
|
| + with ReferenceableElementForLink, TypeParameterizedElementMixin |
| + implements FunctionElementForLink_Local { |
| + /** |
| + * The variable for which this element is the initializer. |
| + */ |
| + final ParameterElementForLink _param; |
| + |
| + /** |
| + * The type inference node for this function, or `null` if it hasn't been |
| + * computed yet. |
| + */ |
| + TypeInferenceNode _typeInferenceNode; |
| + |
| + List<FunctionElementForLink_Local_NonSynthetic> _functions; |
| + DartType _inferredReturnType; |
| + |
| + FunctionElementForLink_ParameterInitializer(this._param); |
| + |
| + @override |
| + TypeInferenceNode get asTypeInferenceNode => |
| + _typeInferenceNode ??= new TypeInferenceNode(this); |
| + |
| + @override |
| + CompilationUnitElementForLink get compilationUnit => |
| + _param.compilationUnit; |
| + |
| + @override |
| + ParameterElementForLink get enclosingElement => _param; |
| + |
| + TypeParameterizedElementMixin get enclosingTypeParameterContext => |
| + _param.getAncestor((e) => e is ClassElementForLink); |
|
Jennifer Messerly
2016/06/25 00:37:47
I think this was the only actual change
|
| + |
| + @override |
| + CompilationUnitElementForLink get enclosingUnit => _param.compilationUnit; |
| + |
| + @override |
| + List<FunctionElementForLink_Local_NonSynthetic> get functions => |
| + _functions ??= _param._unlinkedParam.initializer.localFunctions |
| + .map((UnlinkedExecutable ex) => |
| + new FunctionElementForLink_Local_NonSynthetic( |
| + _param.compilationUnit, this, ex)) |
| + .toList(); |
| + |
| + @override |
| + DartType get returnType { |
| + // If this is a variable whose type needs inferring, infer it. |
| + if (_param.hasImplicitType) { |
| + return _param.inferredType; |
| + } else { |
| + // There's no reason linking should need to access the type of |
| + // this FunctionElement, since the variable doesn't need its |
| + // type inferred. |
| + assert(false); |
| + // But for robustness, return the dynamic type. |
| + return DynamicTypeImpl.instance; |
| + } |
| + } |
| + |
| + @override |
| + void set returnType(DartType newType) { |
| + // InstanceMemberInferrer stores the new type both here and on the variable |
| + // element. We don't need to record both values, so we ignore it here. |
| + } |
| + |
| + @override |
| + TypeParameterizedElementMixin get typeParameterContext => this; |
| + |
| + @override |
| + List<UnlinkedTypeParam> get unlinkedTypeParams => const []; |
| + |
| + @override |
| + bool get _hasTypeBeenInferred => _inferredReturnType != null; |
| + |
| + @override |
| + UnlinkedExecutable get _unlinkedExecutable => |
| + _param._unlinkedParam.initializer; |
| + |
| + @override |
| + FunctionElementForLink_Local getLocalFunction(int index) { |
| + List<FunctionElementForLink_Local_NonSynthetic> functions = this.functions; |
| + return index < functions.length ? functions[index] : null; |
| + } |
| + |
| + /** |
| + * Store the results of type inference for this initializer in |
| + * [compilationUnit]. |
| + */ |
| + void link(CompilationUnitElementInBuildUnit compilationUnit) { |
| + compilationUnit._storeLinkedType(_unlinkedExecutable.inferredReturnTypeSlot, |
| + _inferredReturnType, typeParameterContext); |
| + for (FunctionElementForLink_Local_NonSynthetic function in functions) { |
| + function.link(compilationUnit); |
| + } |
| + } |
| + |
| + @override |
| + noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
| + |
| + @override |
| + void _setInferredType(DartType type) { |
| + assert(!_hasTypeBeenInferred); |
| + _inferredReturnType = type; |
| + _param._inferredType = _dynamicIfNull(type); |
| + } |
| +} |
| + |
| +/** |
| * Element representing a local function (possibly a closure). |
| */ |
| abstract class FunctionElementForLink_Local |
| @@ -3888,6 +4001,15 @@ class ParameterElementForLink implements ParameterElementImpl { |
| @override |
| final ParameterParentElementForLink enclosingElement; |
| + /** |
| + * If this variable has an initializer and an implicit type, and the enclosing |
| + * library is part of the build unit being linked, the variable's node in the |
| + * type inference dependency graph. Otherwise `null`. |
| + */ |
| + TypeInferenceNode _typeInferenceNode; |
| + |
| + FunctionElementForLink_ParameterInitializer _initializer; |
| + |
| DartType _inferredType; |
| DartType _declaredType; |
| @@ -3895,6 +4017,19 @@ class ParameterElementForLink implements ParameterElementImpl { |
| this._typeParameterContext, this.compilationUnit, this._parameterIndex) { |
| if (_unlinkedParam.initializer?.bodyExpr != null) { |
| _constNode = new ConstParameterNode(this); |
| + if (hasImplicitType) { |
| + _typeInferenceNode = initializer.asTypeInferenceNode; |
| + } |
| + } |
| + } |
| + |
| + @override |
| + FunctionElementForLink_ParameterInitializer get initializer { |
| + if (_unlinkedParam.initializer == null) { |
| + return null; |
| + } else { |
| + return _initializer ??= |
| + new FunctionElementForLink_ParameterInitializer(this); |
| } |
| } |
| @@ -3921,32 +4056,58 @@ class ParameterElementForLink implements ParameterElementImpl { |
| return null; |
| } |
| - @override |
| - DartType get type { |
| - if (_inferredType != null) { |
| - return _inferredType; |
| - } else if (_declaredType == null) { |
| - if (_unlinkedParam.isFunctionTyped) { |
| - _declaredType = new FunctionTypeImpl( |
| - new FunctionElementForLink_FunctionTypedParam( |
| - this, _typeParameterContext, _unlinkedParam.parameters)); |
| - } else if (_unlinkedParam.type == null) { |
| - if (!compilationUnit.isInBuildUnit) { |
| - _inferredType = compilationUnit.getLinkedType( |
| - _unlinkedParam.inferredTypeSlot, _typeParameterContext); |
| - return _inferredType; |
| - } else { |
| - _declaredType = DynamicTypeImpl.instance; |
| + /** |
| + * If the variable has an explicitly declared return type, return it. |
| + * Otherwise return `null`. |
| + */ |
| + DartType get declaredType { |
|
Jennifer Messerly
2016/06/25 00:37:47
this pattern more or less copy+paste from Variable
|
| + if (hasImplicitType) { |
| + return null; |
| + } else if (_declaredType != null) { |
| + return _declaredType; |
| + } else if (_unlinkedParam.isFunctionTyped) { |
| + return _declaredType = new FunctionTypeImpl( |
| + new FunctionElementForLink_FunctionTypedParam( |
| + this, _typeParameterContext, _unlinkedParam.parameters)); |
| + } else { |
| + return _declaredType = compilationUnit.resolveTypeRef( |
| + _unlinkedParam.type, _typeParameterContext); |
| + } |
| + } |
| + |
| + /** |
| + * Return the inferred type of the parameter element. |
| + * |
| + * Should only be called if no type was explicitly declared. |
| + */ |
| + DartType get inferredType { |
| + // We should only try to infer a type when none is explicitly declared. |
| + assert(_unlinkedParam.type == null); |
| + if (_inferredType == null) { |
| + if (_typeInferenceNode != null) { |
| + assert(Linker._initializerTypeInferenceCycle == null); |
| + Linker._initializerTypeInferenceCycle = |
| + compilationUnit.library.libraryCycleForLink; |
| + try { |
| + new TypeInferenceDependencyWalker().walk(_typeInferenceNode); |
|
Jennifer Messerly
2016/06/25 00:37:46
Aside -- I'm reusing logic from the static/top-lev
|
| + assert(_inferredType != null); |
| + } finally { |
| + Linker._initializerTypeInferenceCycle = null; |
| } |
| + } else if (compilationUnit.isInBuildUnit) { |
| + _inferredType = DynamicTypeImpl.instance; |
| } else { |
| - _declaredType = compilationUnit.resolveTypeRef( |
| - _unlinkedParam.type, _typeParameterContext); |
| + _inferredType = compilationUnit.getLinkedType( |
| + _unlinkedParam.inferredTypeSlot, _typeParameterContext); |
| } |
| } |
| - return _declaredType; |
| + return _inferredType; |
| } |
| @override |
| + DartType get type => declaredType ?? inferredType; |
| + |
| + @override |
| void set type(DartType inferredType) { |
| assert(_inferredType == null); |
| _inferredType = inferredType; |
| @@ -3957,8 +4118,11 @@ class ParameterElementForLink implements ParameterElementImpl { |
| * [compilationUnit]. |
| */ |
| void link(CompilationUnitElementInBuildUnit compilationUnit) { |
|
Jennifer Messerly
2016/06/25 00:37:46
"link" method seems like the thing that actually f
|
| - compilationUnit._storeLinkedType( |
| - _unlinkedParam.inferredTypeSlot, _inferredType, _typeParameterContext); |
| + if (hasImplicitType) { |
| + compilationUnit._storeLinkedType( |
| + _unlinkedParam.inferredTypeSlot, inferredType, _typeParameterContext); |
| + initializer?.link(compilationUnit); |
| + } |
| } |
| @override |