Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Unified Diff: pkg/analyzer/lib/src/summary/link.dart

Issue 2092333002: fix #25794, infer parameter type from default value, in AST summaries (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix comment Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/summary/summarize_ast.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/summary/summarize_ast.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698