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

Unified Diff: pkg/analyzer/lib/src/generated/static_type_analyzer.dart

Issue 1323513005: Strong mode foreach inference. Infer the type of declared identifiers (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Cycle detection based on class elements Created 5 years, 4 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 | « pkg/analyzer/lib/src/generated/resolver.dart ('k') | pkg/analyzer/test/generated/resolver_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/static_type_analyzer.dart
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 720f8bbd4f0e314e7688cc267ac2ef22bfab6c7f..bffeaadc6ec92b39364d1d1b2ca2a507b2efb889 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -303,6 +303,14 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
return null;
}
+ @override
+ Object visitDeclaredIdentifier(DeclaredIdentifier node) {
+ super.visitDeclaredIdentifier(node);
+ if (_resolver.definingLibrary.context.analysisOptions.strongMode) {
+ _inferForEachLoopVariableType(node);
+ }
+ }
+
/**
* The Dart Language Specification, 12.3: <blockquote>The static type of a literal double is
* double.</blockquote>
@@ -1181,19 +1189,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
return null;
}
- void _inferLocalVariableType(
- VariableDeclaration node, Expression initializer) {
- if (initializer != null &&
- (node.parent as VariableDeclarationList).type == null &&
- (node.element is LocalVariableElementImpl) &&
- (initializer.staticType != null) &&
- (!initializer.staticType.isBottom)) {
- LocalVariableElementImpl element = node.element;
- element.type = initializer.staticType;
- node.name.staticType = initializer.staticType;
- }
- }
-
@override
Object visitVariableDeclaration(VariableDeclaration node) {
Expression initializer = node.initializer;
@@ -1400,6 +1395,43 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
}
}
+ // TODO(vsm): Use leafp's matchType here?
+ DartType _findIteratedType(InterfaceType type, DartType targetType) {
+ // Set by _find if match is found
+ DartType result = null;
+ // Elements we've already visited on a given inheritance path.
+ HashSet<ClassElement> visitedClasses = null;
+
+ bool _find(InterfaceType type) {
+ ClassElement element = type.element;
+ if (type == _typeProvider.objectType || element == null) {
+ return false;
+ }
+ if (element == targetType.element) {
+ List<DartType> typeArguments = type.typeArguments;
+ assert(typeArguments.length == 1);
+ result = typeArguments[0];
+ return true;
+ }
+ if (visitedClasses == null) {
+ visitedClasses = new HashSet<ClassElement>();
+ }
+ // Already visited this class along this path
+ if (!visitedClasses.add(element)) {
+ return false;
+ }
+ try {
+ return _find(type.superclass) ||
+ type.interfaces.any(_find) ||
+ type.mixins.any(_find);
+ } finally {
+ visitedClasses.remove(element);
+ }
+ }
+ _find(type);
+ return result;
+ }
+
/**
* Return the best type of the given [expression].
*/
@@ -1621,6 +1653,42 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
return returnType;
}
+ void _inferForEachLoopVariableType(DeclaredIdentifier loopVariable) {
+ if (loopVariable != null &&
+ loopVariable.type == null &&
+ loopVariable.parent is ForEachStatement) {
+ ForEachStatement loop = loopVariable.parent;
+ if (loop.iterable != null) {
+ Expression expr = loop.iterable;
+ LocalVariableElementImpl element = loopVariable.element;
+ DartType exprType = expr.staticType;
+ if (exprType is InterfaceType) {
+ DartType targetType = (loop.awaitKeyword == null)
+ ? _typeProvider.iterableType
+ : _typeProvider.streamType;
+ DartType iteratedType = _findIteratedType(exprType, targetType);
+ if (element != null && iteratedType != null) {
+ element.type = iteratedType;
+ loopVariable.identifier.staticType = iteratedType;
+ }
+ }
+ }
+ }
+ }
+
+ void _inferLocalVariableType(
+ VariableDeclaration node, Expression initializer) {
+ if (initializer != null &&
+ (node.parent as VariableDeclarationList).type == null &&
+ (node.element is LocalVariableElementImpl) &&
+ (initializer.staticType != null) &&
+ (!initializer.staticType.isBottom)) {
+ LocalVariableElementImpl element = node.element;
+ element.type = initializer.staticType;
+ node.name.staticType = initializer.staticType;
+ }
+ }
+
/**
* Return `true` if the given [Type] is the `Future` form the 'dart:async'
* library.
« no previous file with comments | « pkg/analyzer/lib/src/generated/resolver.dart ('k') | pkg/analyzer/test/generated/resolver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698