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

Side by Side Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 1462133005: Downwards inference. This adds support to the resolver for downwards (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Minor fixes Created 5 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library engine.resolver; 5 library engine.resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import '../task/strong/info.dart' show InferredType, StaticInfo;
10 import '../task/strong/rules.dart' show TypeRules;
9 import 'ast.dart'; 11 import 'ast.dart';
10 import 'constant.dart'; 12 import 'constant.dart';
11 import 'element.dart'; 13 import 'element.dart';
12 import 'element_resolver.dart'; 14 import 'element_resolver.dart';
13 import 'engine.dart'; 15 import 'engine.dart';
14 import 'error.dart'; 16 import 'error.dart';
15 import 'error_verifier.dart'; 17 import 'error_verifier.dart';
16 import 'html.dart' as ht; 18 import 'html.dart' as ht;
17 import 'java_core.dart'; 19 import 'java_core.dart';
18 import 'java_engine.dart'; 20 import 'java_engine.dart';
(...skipping 5728 matching lines...) Expand 10 before | Expand all | Expand 10 after
5747 LibraryElement libraryElement, ImportDirective importDirective) { 5749 LibraryElement libraryElement, ImportDirective importDirective) {
5748 List<ImportDirective> importList = _libraryMap[libraryElement]; 5750 List<ImportDirective> importList = _libraryMap[libraryElement];
5749 if (importList == null) { 5751 if (importList == null) {
5750 importList = new List<ImportDirective>(); 5752 importList = new List<ImportDirective>();
5751 _libraryMap[libraryElement] = importList; 5753 _libraryMap[libraryElement] = importList;
5752 } 5754 }
5753 importList.add(importDirective); 5755 importList.add(importDirective);
5754 } 5756 }
5755 } 5757 }
5756 5758
5759 /** Maintains and manages contextual type information used for
Brian Wilkerson 2015/11/21 16:12:22 Not asking for a change, but I'm not a fan of the
Jennifer Messerly 2015/11/23 22:11:57 Yeah same here. I've been trying to follow: /**
Leaf 2015/12/01 21:49:11 Done.
Brian Wilkerson 2015/12/01 22:31:09 Personally, I find the "///" style hard to read, s
Bob Nystrom 2015/12/01 23:33:27 I'll point out two things: 1. The style guide req
Leaf 2015/12/01 23:39:24 Per point 2: that's my fault (caught in the review
5760 * inferring types.
5761 */
5762 class InferenceContext {
Jennifer Messerly 2015/11/23 22:11:57 "Context" as a class suffix often just means "here
Leaf 2015/12/01 21:49:11 Acknowledged.
5763 /** The key by which we hang information off of ast nodes.
5764 */
5765 static const String _propertyName =
Jennifer Messerly 2015/11/23 22:11:57 might be worth giving this a more descriptive name
Leaf 2015/12/01 21:49:11 Done.
5766 'analyzer.src.generated.InferenceContext.contextType';
5767
5768 /** The error listener on which to record inference information.
5769 */
5770 final AnalysisErrorListener _errorListener;
5771
5772 /** Type provider, needed for type matching.
5773 */
5774 final TypeProvider _typeProvider;
5775
5776 /** The type system in use.
5777 */
5778 final TypeSystem _typeSystem;
5779
5780 /** The DDC type rules, used to create the inference info nodes.
5781 */
5782 final TypeRules _rules;
Jennifer Messerly 2015/11/23 22:11:57 Question: are we still on track to remove this obj
Leaf 2015/11/24 19:32:12 Yes. It's here only to produce the info nodes tha
5783
5784 /** A stack of return types for all of the enclosing
5785 * functions and methods.
5786 */
5787 List<DartType> _returnStack = <DartType>[];
5788
5789 InferenceContext(
Jennifer Messerly 2015/11/23 22:11:58 BTW, if either the type or constructor can be made
Leaf 2015/11/24 19:32:11 The type has to be public since it's accessed by t
Jennifer Messerly 2015/11/24 20:10:57 InferenceContext._(...)
Leaf 2015/12/01 21:49:11 Done.
5790 this._errorListener, TypeProvider typeProvider, this._typeSystem)
5791 : this._typeProvider = typeProvider,
Jennifer Messerly 2015/11/23 22:11:57 nit: "this." is not necessary here
Leaf 2015/12/01 21:49:10 Done.
5792 this._rules = new TypeRules(typeProvider);
5793
5794 /** Get the return type of the current enclusing function, if any.
Brian Wilkerson 2015/11/21 16:12:22 "enclusing" --> "enclosing"
Leaf 2015/12/01 21:49:11 Done.
5795 */
5796 DartType get returnContext =>
5797 (_returnStack.isNotEmpty) ? _returnStack.last : null;
5798
5799 /** If t1 = I<dynamic, ..., dynamic>, then look for a supertype
Jennifer Messerly 2015/11/23 22:11:57 BTW: you probably want to put backticks around gen
Leaf 2015/12/01 21:49:11 Done.
5800 * of t1 of the form K<S0, ..., Sm> where t2 = K<S0', ..., Sm'>
Brian Wilkerson 2015/11/21 16:12:22 What is 't2'?
Jennifer Messerly 2015/11/23 22:11:57 looks like it's the second argument to matchTypes
Leaf 2015/12/01 21:49:11 Added a line to the comments to make this clearer.
5801 * If the supertype exists, use the constraints S0 <: S0', ... Sm <: Sm'
5802 * to derive a concrete instantation for I of the form <T0, ..., Tn>,
5803 * such that I<T0, .., Tn> <: t2
5804 */
5805 List<DartType> matchTypes(DartType t1, DartType t2) =>
5806 (t1 is InterfaceType && t2 is InterfaceType) ? _matchTypes(t1, t2) : null;
5807
5808 /** Pop a return type off of the return stack.
5809 */
5810 void popReturnContext() {
5811 if (_returnStack.isNotEmpty) {
Brian Wilkerson 2015/11/21 16:12:22 Add "assert(_returnStack.isNotEmpty);" before the
Leaf 2015/12/01 21:49:11 Done.
5812 _returnStack.removeLast();
5813 }
5814 }
5815
5816 /** Push a [returnType] onto the return stack.
5817 */
5818 void pushReturnContext(DartType returnType) {
5819 _returnStack.add(returnType);
5820 }
5821
5822 /** Place an info node into the error stream indicating that a
5823 * [type] has been inferred as the type of [node].
5824 */
5825 void recordInference(Expression node, DartType type) {
5826 StaticInfo info = InferredType.create(_rules, node, type);
5827 if (info == null) return;
Brian Wilkerson 2015/11/21 16:12:22 Stylistic nit (for here and elsewhere): we always
Leaf 2015/11/24 19:32:12 Sorry - pulled over from DDC code and I missed the
Leaf 2015/12/01 21:49:11 Done.
5828 var error = info.toAnalysisError();
5829 _errorListener.onError(error);
5830 }
5831
5832 List<DartType> _matchTypes(InterfaceType t1, InterfaceType t2) {
5833 if (t1 == t2) {
5834 return t2.typeArguments;
5835 }
5836 List<DartType> tArgs1 = t1.typeArguments;
5837 List<DartType> tArgs2 = t2.typeArguments;
5838 // If t1 isn't a raw type, bail out
5839 if (tArgs1 != null && tArgs1.any((t) => !t.isDynamic)) {
5840 return null;
5841 }
5842
5843 // This is our inferred type argument list. We start at all dynamic,
5844 // and fill in with inferred types when we reach a match.
5845 List<DartType> actuals =
5846 new List<DartType>.filled(tArgs1.length, _typeProvider.dynamicType);
5847
5848 // When we find the supertype of t1 with the same
5849 // classname as t2 (see below), we have the following:
5850 // If t1 is an instantiation of a class T1<X0, ..., Xn>
5851 // and t2 is an instantiation of a class T2<Y0, ...., Ym>
5852 // of the form t2 = T2<S0, ..., Sm>
5853 // then we want to choose instantiations for the Xi
5854 // T0, ..., Tn such that T1<T0, ..., Tn> <: t2 .
5855 // To find this, we simply instantate T1 with
5856 // X0, ..., Xn, and then find its superclass
5857 // T2<T0', ..., Tn'>. We then solve the constraint
5858 // set T0' <: S0, ..., Tn' <: Sn for the Xi.
5859 // Currently, we only handle constraints where
5860 // the Ti' is one of the Xi'. If there are multiple
5861 // constraints on some Xi, we choose the lower of the
5862 // two (if it exists).
5863 bool permute(List<DartType> permutedArgs) {
5864 if (permutedArgs == null) {
5865 return false;
5866 }
5867 List<TypeParameterElement> ps = t1.typeParameters;
5868 List<DartType> ts = ps.map((p) => p.type).toList();
5869 for (int i = 0; i < permutedArgs.length; i++) {
5870 DartType tVar = permutedArgs[i];
5871 DartType tActual = tArgs2[i];
5872 int index = ts.indexOf(tVar);
5873 if (index >= 0 && _typeSystem.isSubtypeOf(tActual, actuals[index])) {
5874 actuals[index] = tActual;
5875 }
5876 }
5877 return actuals.any((x) => !x.isDynamic);
5878 }
5879
5880 // Look for the first supertype of t1 with the same class name as t2.
5881 bool match(InterfaceType t1) {
Brian Wilkerson 2015/11/21 16:12:22 This method will result in an infinite loop if the
Leaf 2015/12/01 21:49:11 Done.
5882 if (t1.element == t2.element) {
5883 return permute(t1.typeArguments);
5884 }
5885
5886 if (t1 == _typeProvider.objectType) {
5887 return false;
5888 }
5889
5890 if (match(t1.superclass)) {
5891 return true;
5892 }
5893
5894 for (final parent in t1.interfaces) {
5895 if (match(parent)) {
5896 return true;
5897 }
5898 }
5899
5900 for (final parent in t1.mixins) {
Brian Wilkerson 2015/11/21 16:12:22 Interesting that we do mixins after interfaces. I
Jennifer Messerly 2015/11/23 22:11:58 Yeah. I would normally think of mixins as coming b
Leaf 2015/11/24 19:32:11 I need to sit down and work through the details of
5901 if (match(parent)) {
5902 return true;
5903 }
5904 }
5905 return false;
5906 }
5907
5908 // We have that t1 = T1<dynamic, ..., dynamic>.
5909 // To match t1 against t2, we use the uninstantiated version
5910 // of t1, essentially treating it as an instantiation with
5911 // fresh variables, and solve for the variables.
5912 // t1.element.type will be of the form T1<X0, ..., Xn>
5913 if (!match(t1.element.type)) return null;
5914 DartType newT1 = t1.element.type.substitute4(actuals);
5915 // If we found a solution, return it.
5916 if (_typeSystem.isSubtypeOf(newT1, t2)) return actuals;
5917 return null;
5918 }
5919
5920 /** Attach contextual type information [type] to [node] for use during
5921 * inference.
5922 */
5923 static void annotateNode(AstNode node, DartType type) {
Jennifer Messerly 2015/11/23 22:11:58 (note: the following may be obsolete in light of m
Leaf 2015/12/01 21:49:10 Done.
5924 node?.setProperty(_propertyName, type);
Jennifer Messerly 2015/11/23 22:11:57 hmmmm. Thinking on this more (having seen the use
Leaf 2015/11/24 19:32:12 Yeah, I think this would be fine. I initially did
Brian Wilkerson 2015/11/24 21:17:57 I don't have a problem with either approach. The
Leaf 2015/12/01 21:49:11 I'm leaving it as it is for now, but added a todo
5925 return;
Jennifer Messerly 2015/11/23 22:11:57 nit: return not needed here
Leaf 2015/12/01 21:49:10 The visitor methods seem to always explicitly retu
5926 }
5927
5928 /** Clear the type information assocated with [node].
5929 */
5930 static void clear(AstNode node) {
5931 node?.setProperty(_propertyName, null);
5932 return;
5933 }
5934
5935 // If t1 = I<dynamic, ..., dynamic>, then look for a supertype
Jennifer Messerly 2015/11/23 22:11:57 Is this supposed to be here? Consider folding it i
Leaf 2015/12/01 21:49:10 Done.
5936 // of t1 of the form K<S0, ..., Sm> where t2 = K<S0', ..., Sm'>
5937 // If the supertype exists, use the constraints S0 <: S0', ... Sm <: Sm'
5938 // to derive a concrete instantation for I of the form <T0, ..., Tn>,
5939 // such that I<T0, .., Tn> <: t2
5940 /** Look for contextual type information attached to [node]. Returns
5941 * the type if found, otherwise null.
5942 */
5943 static DartType get(AstNode node) => node?.getProperty(_propertyName);
5944 }
5945
5757 /** 5946 /**
5758 * Instances of the class `InheritanceManager` manage the knowledge of where cla ss members 5947 * Instances of the class `InheritanceManager` manage the knowledge of where cla ss members
5759 * (methods, getters & setters) are inherited from. 5948 * (methods, getters & setters) are inherited from.
5760 */ 5949 */
5761 class InheritanceManager { 5950 class InheritanceManager {
5762 /** 5951 /**
5763 * The [LibraryElement] that is managed by this manager. 5952 * The [LibraryElement] that is managed by this manager.
5764 */ 5953 */
5765 LibraryElement _library; 5954 LibraryElement _library;
5766 5955
(...skipping 4598 matching lines...) Expand 10 before | Expand all | Expand 10 after
10365 * The object used to resolve the element associated with the current node. 10554 * The object used to resolve the element associated with the current node.
10366 */ 10555 */
10367 ElementResolver elementResolver; 10556 ElementResolver elementResolver;
10368 10557
10369 /** 10558 /**
10370 * The object used to compute the type associated with the current node. 10559 * The object used to compute the type associated with the current node.
10371 */ 10560 */
10372 StaticTypeAnalyzer typeAnalyzer; 10561 StaticTypeAnalyzer typeAnalyzer;
10373 10562
10374 /* 10563 /*
10375 * The type system in use during resolution. 10564 * The type system in use during resolution.
10376 */ 10565 */
10377 TypeSystem typeSystem; 10566 TypeSystem typeSystem;
10378 10567
10379 /** 10568 /**
10380 * The class element representing the class containing the current node, 10569 * The class element representing the class containing the current node,
10381 * or `null` if the current node is not contained in a class. 10570 * or `null` if the current node is not contained in a class.
10382 */ 10571 */
10383 ClassElement enclosingClass = null; 10572 ClassElement enclosingClass = null;
10384 10573
10385 /** 10574 /**
10386 * The class declaration representing the class containing the current node, o r `null` if 10575 * The class declaration representing the class containing the current node, o r `null` if
(...skipping 12 matching lines...) Expand all
10399 * current node is not contained in a function. 10588 * current node is not contained in a function.
10400 */ 10589 */
10401 ExecutableElement _enclosingFunction = null; 10590 ExecutableElement _enclosingFunction = null;
10402 10591
10403 /** 10592 /**
10404 * The [Comment] before a [FunctionDeclaration] or a [MethodDeclaration] that 10593 * The [Comment] before a [FunctionDeclaration] or a [MethodDeclaration] that
10405 * cannot be resolved where we visited it, because it should be resolved in th e scope of the body. 10594 * cannot be resolved where we visited it, because it should be resolved in th e scope of the body.
10406 */ 10595 */
10407 Comment _commentBeforeFunction = null; 10596 Comment _commentBeforeFunction = null;
10408 10597
10598 InferenceContext inferenceContext = null;
Jennifer Messerly 2015/11/23 22:11:58 hmmm, I guess this is for consistency, but `= null
Leaf 2015/12/01 21:49:11 Acknowledged.
10599
10409 /** 10600 /**
10410 * The object keeping track of which elements have had their types overridden. 10601 * The object keeping track of which elements have had their types overridden.
10411 */ 10602 */
10412 TypeOverrideManager _overrideManager = new TypeOverrideManager(); 10603 TypeOverrideManager _overrideManager = new TypeOverrideManager();
10413 10604
10414 /** 10605 /**
10415 * The object keeping track of which elements have had their types promoted. 10606 * The object keeping track of which elements have had their types promoted.
10416 */ 10607 */
10417 TypePromotionManager _promoteManager = new TypePromotionManager(); 10608 TypePromotionManager _promoteManager = new TypePromotionManager();
10418 10609
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
10450 StaticTypeAnalyzerFactory typeAnalyzerFactory}) 10641 StaticTypeAnalyzerFactory typeAnalyzerFactory})
10451 : super(definingLibrary, source, typeProvider, errorListener, 10642 : super(definingLibrary, source, typeProvider, errorListener,
10452 nameScope: nameScope) { 10643 nameScope: nameScope) {
10453 if (inheritanceManager == null) { 10644 if (inheritanceManager == null) {
10454 this._inheritanceManager = new InheritanceManager(definingLibrary); 10645 this._inheritanceManager = new InheritanceManager(definingLibrary);
10455 } else { 10646 } else {
10456 this._inheritanceManager = inheritanceManager; 10647 this._inheritanceManager = inheritanceManager;
10457 } 10648 }
10458 this.elementResolver = new ElementResolver(this); 10649 this.elementResolver = new ElementResolver(this);
10459 this.typeSystem = definingLibrary.context.typeSystem; 10650 this.typeSystem = definingLibrary.context.typeSystem;
10651 this.inferenceContext =
10652 new InferenceContext(errorListener, typeProvider, typeSystem);
10460 if (typeAnalyzerFactory == null) { 10653 if (typeAnalyzerFactory == null) {
10461 this.typeAnalyzer = new StaticTypeAnalyzer(this); 10654 this.typeAnalyzer = new StaticTypeAnalyzer(this);
10462 } else { 10655 } else {
10463 this.typeAnalyzer = typeAnalyzerFactory(this); 10656 this.typeAnalyzer = typeAnalyzerFactory(this);
10464 } 10657 }
10465 } 10658 }
10466 10659
10467 /** 10660 /**
10468 * Initialize a newly created visitor to resolve the nodes in a compilation un it. 10661 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
10469 * 10662 *
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
10722 expression.propagatedType = type; 10915 expression.propagatedType = type;
10723 } 10916 }
10724 10917
10725 @override 10918 @override
10726 Object visitAnnotation(Annotation node) { 10919 Object visitAnnotation(Annotation node) {
10727 AstNode parent = node.parent; 10920 AstNode parent = node.parent;
10728 if (identical(parent, _enclosingClassDeclaration) || 10921 if (identical(parent, _enclosingClassDeclaration) ||
10729 identical(parent, _enclosingFunctionTypeAlias)) { 10922 identical(parent, _enclosingFunctionTypeAlias)) {
10730 return null; 10923 return null;
10731 } 10924 }
10732 return super.visitAnnotation(node); 10925 safelyVisit(node.name);
10926 safelyVisit(node.constructorName);
10927 Element element = node.element;
10928 if (element is ExecutableElement) {
10929 InferenceContext.annotateNode(node.arguments, element.type);
10930 }
10931 safelyVisit(node.arguments);
10932 node.accept(elementResolver);
10933 node.accept(typeAnalyzer);
10934 return null;
10935 }
10936
10937 @override
10938 Object visitArgumentList(ArgumentList node) {
10939 DartType callerType = InferenceContext.get(node);
10940 if (callerType is FunctionType) {
10941 Map<String, DartType> namedParameterTypes =
10942 callerType.namedParameterTypes;
10943 List<DartType> normalParameterTypes = callerType.normalParameterTypes;
10944 List<DartType> optionalParameterTypes = callerType.optionalParameterTypes;
10945 int normalCount = normalParameterTypes.length;
10946 int optionalCount = optionalParameterTypes.length;
10947 int namedCount = namedParameterTypes.length;
10948
10949 NodeList<Expression> arguments = node.arguments;
10950 Iterable<Expression> positional =
10951 arguments.takeWhile((l) => l is! NamedExpression);
10952 Iterable<Expression> required = positional.take(normalCount);
10953 Iterable<Expression> optional =
10954 positional.skip(normalCount).take(optionalCount);
10955 Iterable<Expression> named =
10956 arguments.skipWhile((l) => l is! NamedExpression);
10957
10958 int index = 0;
Jennifer Messerly 2015/11/23 22:11:57 trivial: I'd probably just write this as a C-style
Leaf 2015/11/24 19:32:12 The for loop version above will throw an out of bo
Jennifer Messerly 2015/11/24 20:10:58 Ah, in that case, probably best to leave it as is!
10959 for (Expression argument in required) {
10960 InferenceContext.annotateNode(argument, normalParameterTypes[index++]);
Jennifer Messerly 2015/11/23 22:11:58 you might be able to avoid some of the above logic
Leaf 2015/12/01 21:49:11 Maybe? I'd have to think through the various impl
10961 }
10962 index = 0;
10963 for (Expression argument in optional) {
10964 InferenceContext.annotateNode(
10965 argument, optionalParameterTypes[index++]);
10966 }
10967
10968 for (Expression argument in named) {
10969 if (argument is NamedExpression &&
10970 namedParameterTypes.containsKey(argument.name.label.name)) {
Jennifer Messerly 2015/11/23 22:11:57 not that it matters, but I'd be tempted to rewrite
Leaf 2015/12/01 21:49:11 Done.
10971 InferenceContext.annotateNode(
10972 argument, namedParameterTypes[argument.name.label.name]);
10973 }
10974 }
10975 }
10976 super.visitArgumentList(node);
Brian Wilkerson 2015/11/21 16:12:22 Missing return
Leaf 2015/12/01 21:49:10 Done.
10733 } 10977 }
10734 10978
10735 @override 10979 @override
10736 Object visitAsExpression(AsExpression node) { 10980 Object visitAsExpression(AsExpression node) {
10981 InferenceContext.annotateNode(node.expression, node.type.type);
10737 super.visitAsExpression(node); 10982 super.visitAsExpression(node);
10738 // Since an as-statement doesn't actually change the type, we don't 10983 // Since an as-statement doesn't actually change the type, we don't
10739 // let it affect the propagated type when it would result in a loss 10984 // let it affect the propagated type when it would result in a loss
10740 // of precision. 10985 // of precision.
10741 overrideExpression(node.expression, node.type.type, false, false); 10986 overrideExpression(node.expression, node.type.type, false, false);
10742 return null; 10987 return null;
10743 } 10988 }
10744 10989
10745 @override 10990 @override
10746 Object visitAssertStatement(AssertStatement node) { 10991 Object visitAssertStatement(AssertStatement node) {
10747 super.visitAssertStatement(node); 10992 super.visitAssertStatement(node);
10748 _propagateTrueState(node.condition); 10993 _propagateTrueState(node.condition);
10749 return null; 10994 return null;
10750 } 10995 }
10751 10996
10752 @override 10997 @override
10998 Object visitAssignmentExpression(AssignmentExpression node) {
10999 safelyVisit(node.leftHandSide);
11000 sc.TokenType operator = node.operator.type;
11001 if (operator == sc.TokenType.EQ ||
11002 operator == sc.TokenType.QUESTION_QUESTION_EQ) {
11003 InferenceContext.annotateNode(
11004 node.rightHandSide, node.leftHandSide.staticType);
11005 }
11006 safelyVisit(node.rightHandSide);
11007 node.accept(elementResolver);
11008 node.accept(typeAnalyzer);
11009 return null;
11010 }
11011
11012 @override
11013 Object visitAwaitExpression(AwaitExpression node) {
11014 //TODO(leafp): Handle the implicit union type here
11015 DartType contextType = InferenceContext.get(node);
11016 if (contextType != null) {
11017 InterfaceType futureT =
11018 typeProvider.futureType.substitute4([contextType]);
11019 InferenceContext.annotateNode(node.expression, futureT);
11020 }
11021 super.visitAwaitExpression(node);
11022 return null;
Brian Wilkerson 2015/11/21 16:12:22 Or "return super.visitAwaitExpression(node);"
Leaf 2015/12/01 21:49:10 Done.
11023 }
11024
11025 @override
10753 Object visitBinaryExpression(BinaryExpression node) { 11026 Object visitBinaryExpression(BinaryExpression node) {
10754 sc.TokenType operatorType = node.operator.type; 11027 sc.TokenType operatorType = node.operator.type;
10755 Expression leftOperand = node.leftOperand; 11028 Expression leftOperand = node.leftOperand;
10756 Expression rightOperand = node.rightOperand; 11029 Expression rightOperand = node.rightOperand;
10757 if (operatorType == sc.TokenType.AMPERSAND_AMPERSAND) { 11030 if (operatorType == sc.TokenType.AMPERSAND_AMPERSAND) {
10758 safelyVisit(leftOperand); 11031 safelyVisit(leftOperand);
10759 if (rightOperand != null) { 11032 if (rightOperand != null) {
10760 _overrideManager.enterScope(); 11033 _overrideManager.enterScope();
10761 try { 11034 try {
10762 _promoteManager.enterScope(); 11035 _promoteManager.enterScope();
(...skipping 19 matching lines...) Expand all
10782 if (rightOperand != null) { 11055 if (rightOperand != null) {
10783 _overrideManager.enterScope(); 11056 _overrideManager.enterScope();
10784 try { 11057 try {
10785 _propagateFalseState(leftOperand); 11058 _propagateFalseState(leftOperand);
10786 rightOperand.accept(this); 11059 rightOperand.accept(this);
10787 } finally { 11060 } finally {
10788 _overrideManager.exitScope(); 11061 _overrideManager.exitScope();
10789 } 11062 }
10790 } 11063 }
10791 } else { 11064 } else {
11065 // TODO(leafp): Handle this case
Brian Wilkerson 2015/11/21 16:12:22 I won't remember what this means outside the conte
Leaf 2015/12/01 21:49:11 Done.
10792 safelyVisit(leftOperand); 11066 safelyVisit(leftOperand);
10793 safelyVisit(rightOperand); 11067 safelyVisit(rightOperand);
10794 } 11068 }
10795 node.accept(elementResolver); 11069 node.accept(elementResolver);
10796 node.accept(typeAnalyzer); 11070 node.accept(typeAnalyzer);
10797 return null; 11071 return null;
10798 } 11072 }
10799 11073
10800 @override 11074 @override
10801 Object visitBlockFunctionBody(BlockFunctionBody node) { 11075 Object visitBlockFunctionBody(BlockFunctionBody node) {
10802 safelyVisit(_commentBeforeFunction); 11076 safelyVisit(_commentBeforeFunction);
10803 _overrideManager.enterScope(); 11077 _overrideManager.enterScope();
10804 try { 11078 try {
11079 inferenceContext.pushReturnContext(InferenceContext.get(node));
10805 super.visitBlockFunctionBody(node); 11080 super.visitBlockFunctionBody(node);
10806 } finally { 11081 } finally {
10807 _overrideManager.exitScope(); 11082 _overrideManager.exitScope();
11083 inferenceContext.popReturnContext();
10808 } 11084 }
10809 return null; 11085 return null;
10810 } 11086 }
10811 11087
10812 @override 11088 @override
10813 Object visitBreakStatement(BreakStatement node) { 11089 Object visitBreakStatement(BreakStatement node) {
10814 // 11090 //
10815 // We do not visit the label because it needs to be visited in the context 11091 // We do not visit the label because it needs to be visited in the context
10816 // of the statement. 11092 // of the statement.
10817 // 11093 //
10818 node.accept(elementResolver); 11094 node.accept(elementResolver);
10819 node.accept(typeAnalyzer); 11095 node.accept(typeAnalyzer);
10820 return null; 11096 return null;
10821 } 11097 }
10822 11098
10823 @override 11099 @override
11100 Object visitCascadeExpression(CascadeExpression node) {
11101 InferenceContext.annotateNode(node.target, InferenceContext.get(node));
11102 super.visitCascadeExpression(node);
11103 }
11104
11105 @override
10824 Object visitClassDeclaration(ClassDeclaration node) { 11106 Object visitClassDeclaration(ClassDeclaration node) {
10825 // 11107 //
10826 // Resolve the metadata in the library scope. 11108 // Resolve the metadata in the library scope.
10827 // 11109 //
10828 if (node.metadata != null) { 11110 if (node.metadata != null) {
10829 node.metadata.accept(this); 11111 node.metadata.accept(this);
10830 } 11112 }
10831 _enclosingClassDeclaration = node; 11113 _enclosingClassDeclaration = node;
10832 // 11114 //
10833 // Continue the class resolution. 11115 // Continue the class resolution.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
10946 try { 11228 try {
10947 _promoteManager.enterScope(); 11229 _promoteManager.enterScope();
10948 try { 11230 try {
10949 _propagateTrueState(condition); 11231 _propagateTrueState(condition);
10950 // Type promotion. 11232 // Type promotion.
10951 _promoteTypes(condition); 11233 _promoteTypes(condition);
10952 _clearTypePromotionsIfPotentiallyMutatedIn(thenExpression); 11234 _clearTypePromotionsIfPotentiallyMutatedIn(thenExpression);
10953 _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated( 11235 _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
10954 thenExpression); 11236 thenExpression);
10955 // Visit "then" expression. 11237 // Visit "then" expression.
11238 InferenceContext.annotateNode(
Jennifer Messerly 2015/11/23 22:11:57 might be worth a helper for this? InferenceCo
Leaf 2015/12/01 21:49:11 Done.
11239 thenExpression, InferenceContext.get(node));
10956 thenExpression.accept(this); 11240 thenExpression.accept(this);
10957 } finally { 11241 } finally {
10958 _promoteManager.exitScope(); 11242 _promoteManager.exitScope();
10959 } 11243 }
10960 } finally { 11244 } finally {
10961 _overrideManager.exitScope(); 11245 _overrideManager.exitScope();
10962 } 11246 }
10963 } 11247 }
10964 Expression elseExpression = node.elseExpression; 11248 Expression elseExpression = node.elseExpression;
10965 if (elseExpression != null) { 11249 if (elseExpression != null) {
10966 _overrideManager.enterScope(); 11250 _overrideManager.enterScope();
10967 try { 11251 try {
10968 _propagateFalseState(condition); 11252 _propagateFalseState(condition);
11253 InferenceContext.annotateNode(
11254 elseExpression, InferenceContext.get(node));
10969 elseExpression.accept(this); 11255 elseExpression.accept(this);
10970 } finally { 11256 } finally {
10971 _overrideManager.exitScope(); 11257 _overrideManager.exitScope();
10972 } 11258 }
10973 } 11259 }
10974 node.accept(elementResolver); 11260 node.accept(elementResolver);
10975 node.accept(typeAnalyzer); 11261 node.accept(typeAnalyzer);
10976 bool thenIsAbrupt = _isAbruptTerminationExpression(thenExpression); 11262 bool thenIsAbrupt = _isAbruptTerminationExpression(thenExpression);
10977 bool elseIsAbrupt = _isAbruptTerminationExpression(elseExpression); 11263 bool elseIsAbrupt = _isAbruptTerminationExpression(elseExpression);
10978 if (elseIsAbrupt && !thenIsAbrupt) { 11264 if (elseIsAbrupt && !thenIsAbrupt) {
10979 _propagateTrueState(condition); 11265 _propagateTrueState(condition);
10980 _propagateState(thenExpression); 11266 _propagateState(thenExpression);
10981 } else if (thenIsAbrupt && !elseIsAbrupt) { 11267 } else if (thenIsAbrupt && !elseIsAbrupt) {
10982 _propagateFalseState(condition); 11268 _propagateFalseState(condition);
10983 _propagateState(elseExpression); 11269 _propagateState(elseExpression);
10984 } 11270 }
10985 return null; 11271 return null;
10986 } 11272 }
10987 11273
10988 @override 11274 @override
10989 Object visitConstructorDeclaration(ConstructorDeclaration node) { 11275 Object visitConstructorDeclaration(ConstructorDeclaration node) {
10990 ExecutableElement outerFunction = _enclosingFunction; 11276 ExecutableElement outerFunction = _enclosingFunction;
10991 try { 11277 try {
10992 _enclosingFunction = node.element; 11278 _enclosingFunction = node.element;
11279 DartType type = _enclosingFunction.type;
11280 if (type is FunctionType) {
Jennifer Messerly 2015/11/23 22:11:58 I think this would always be the case for a constr
Leaf 2015/12/01 21:49:11 Done.
11281 _inferFormalParameterList(node.parameters, type);
Jennifer Messerly 2015/11/23 22:11:57 was just chatting about this--I'm not sure this co
Leaf 2015/12/01 21:49:11 Done.
11282 InferenceContext.annotateNode(node.body, type.returnType);
11283 }
10993 super.visitConstructorDeclaration(node); 11284 super.visitConstructorDeclaration(node);
10994 } finally { 11285 } finally {
10995 _enclosingFunction = outerFunction; 11286 _enclosingFunction = outerFunction;
10996 } 11287 }
10997 ConstructorElementImpl constructor = node.element; 11288 ConstructorElementImpl constructor = node.element;
10998 constructor.constantInitializers = 11289 constructor.constantInitializers =
10999 new ConstantAstCloner().cloneNodeList(node.initializers); 11290 new ConstantAstCloner().cloneNodeList(node.initializers);
11000 return null; 11291 return null;
11001 } 11292 }
11002 11293
11003 @override 11294 @override
11004 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { 11295 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
11005 // 11296 //
11006 // We visit the expression, but do not visit the field name because it needs 11297 // We visit the expression, but do not visit the field name because it needs
11007 // to be visited in the context of the constructor field initializer node. 11298 // to be visited in the context of the constructor field initializer node.
11008 // 11299 //
11300 FieldElement fieldElement = enclosingClass.getField(node.fieldName.name);
Jennifer Messerly 2015/11/23 22:11:57 Does `fieldName.staticElement` give you the field
Leaf 2015/11/24 19:32:12 Not set until the elementResolver runs below. I co
Jennifer Messerly 2015/11/24 20:10:57 ah, interesting. In this case I think re-ordering
Leaf 2015/12/01 21:49:11 Yes, it's fine here and now, but I feel like every
11301 InferenceContext.annotateNode(node.expression, fieldElement?.type);
11009 safelyVisit(node.expression); 11302 safelyVisit(node.expression);
11010 node.accept(elementResolver); 11303 node.accept(elementResolver);
11011 node.accept(typeAnalyzer); 11304 node.accept(typeAnalyzer);
11012 return null; 11305 return null;
11013 } 11306 }
11014 11307
11015 @override 11308 @override
11016 Object visitConstructorName(ConstructorName node) { 11309 Object visitConstructorName(ConstructorName node) {
11017 // 11310 //
11018 // We do not visit either the type name, because it won't be visited anyway, 11311 // We do not visit either the type name, because it won't be visited anyway,
(...skipping 11 matching lines...) Expand all
11030 // We do not visit the label because it needs to be visited in the context 11323 // We do not visit the label because it needs to be visited in the context
11031 // of the statement. 11324 // of the statement.
11032 // 11325 //
11033 node.accept(elementResolver); 11326 node.accept(elementResolver);
11034 node.accept(typeAnalyzer); 11327 node.accept(typeAnalyzer);
11035 return null; 11328 return null;
11036 } 11329 }
11037 11330
11038 @override 11331 @override
11039 Object visitDefaultFormalParameter(DefaultFormalParameter node) { 11332 Object visitDefaultFormalParameter(DefaultFormalParameter node) {
11333 InferenceContext.annotateNode(
11334 node.defaultValue, node.parameter.element?.type);
11040 super.visitDefaultFormalParameter(node); 11335 super.visitDefaultFormalParameter(node);
11041 ParameterElement element = node.element; 11336 ParameterElement element = node.element;
11042 if (element.initializer != null && node.defaultValue != null) { 11337 if (element.initializer != null && node.defaultValue != null) {
11043 (element.initializer as FunctionElementImpl).returnType = 11338 (element.initializer as FunctionElementImpl).returnType =
11044 node.defaultValue.staticType; 11339 node.defaultValue.staticType;
11045 } 11340 }
11046 FormalParameterList parent = node.parent; 11341 FormalParameterList parent = node.parent;
11047 AstNode grandparent = parent.parent; 11342 AstNode grandparent = parent.parent;
11048 if (grandparent is ConstructorDeclaration && 11343 if (grandparent is ConstructorDeclaration &&
11049 grandparent.constKeyword != null) { 11344 grandparent.constKeyword != null) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
11108 } 11403 }
11109 11404
11110 @override 11405 @override
11111 Object visitExpressionFunctionBody(ExpressionFunctionBody node) { 11406 Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
11112 safelyVisit(_commentBeforeFunction); 11407 safelyVisit(_commentBeforeFunction);
11113 if (resolveOnlyCommentInFunctionBody) { 11408 if (resolveOnlyCommentInFunctionBody) {
11114 return null; 11409 return null;
11115 } 11410 }
11116 _overrideManager.enterScope(); 11411 _overrideManager.enterScope();
11117 try { 11412 try {
11413 InferenceContext.annotateNode(
11414 node.expression, InferenceContext.get(node));
11118 super.visitExpressionFunctionBody(node); 11415 super.visitExpressionFunctionBody(node);
11119 } finally { 11416 } finally {
11120 _overrideManager.exitScope(); 11417 _overrideManager.exitScope();
11121 } 11418 }
11122 return null; 11419 return null;
11123 } 11420 }
11124 11421
11125 @override 11422 @override
11126 Object visitFieldDeclaration(FieldDeclaration node) { 11423 Object visitFieldDeclaration(FieldDeclaration node) {
11127 _overrideManager.enterScope(); 11424 _overrideManager.enterScope();
(...skipping 19 matching lines...) Expand all
11147 return null; 11444 return null;
11148 } 11445 }
11149 11446
11150 @override 11447 @override
11151 void visitForEachStatementInScope(ForEachStatement node) { 11448 void visitForEachStatementInScope(ForEachStatement node) {
11152 // 11449 //
11153 // We visit the iterator before the loop variable because the loop variable 11450 // We visit the iterator before the loop variable because the loop variable
11154 // cannot be in scope while visiting the iterator. 11451 // cannot be in scope while visiting the iterator.
11155 // 11452 //
11156 Expression iterable = node.iterable; 11453 Expression iterable = node.iterable;
11157 safelyVisit(iterable);
11158 DeclaredIdentifier loopVariable = node.loopVariable; 11454 DeclaredIdentifier loopVariable = node.loopVariable;
11159 SimpleIdentifier identifier = node.identifier; 11455 SimpleIdentifier identifier = node.identifier;
11456 if (loopVariable?.type?.type != null) {
11457 InterfaceType targetType = (node.awaitKeyword == null)
11458 ? typeProvider.iterableType
11459 : typeProvider.streamType;
11460 InferenceContext.annotateNode(
11461 iterable, targetType.substitute4([loopVariable.type.type]));
11462 }
11463 safelyVisit(iterable);
11160 safelyVisit(loopVariable); 11464 safelyVisit(loopVariable);
11161 safelyVisit(identifier); 11465 safelyVisit(identifier);
11162 Statement body = node.body; 11466 Statement body = node.body;
11163 if (body != null) { 11467 if (body != null) {
11164 _overrideManager.enterScope(); 11468 _overrideManager.enterScope();
11165 try { 11469 try {
11166 if (loopVariable != null && iterable != null) { 11470 if (loopVariable != null && iterable != null) {
11167 LocalVariableElement loopElement = loopVariable.element; 11471 LocalVariableElement loopElement = loopVariable.element;
11168 if (loopElement != null) { 11472 if (loopElement != null) {
11169 DartType propagatedType = null; 11473 DartType propagatedType = null;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
11222 // TODO(brianwilkerson) If the loop can only be exited because the condition 11526 // TODO(brianwilkerson) If the loop can only be exited because the condition
11223 // is false, then propagateFalseState(condition); 11527 // is false, then propagateFalseState(condition);
11224 } 11528 }
11225 11529
11226 @override 11530 @override
11227 Object visitFunctionDeclaration(FunctionDeclaration node) { 11531 Object visitFunctionDeclaration(FunctionDeclaration node) {
11228 ExecutableElement outerFunction = _enclosingFunction; 11532 ExecutableElement outerFunction = _enclosingFunction;
11229 try { 11533 try {
11230 SimpleIdentifier functionName = node.name; 11534 SimpleIdentifier functionName = node.name;
11231 _enclosingFunction = functionName.staticElement as ExecutableElement; 11535 _enclosingFunction = functionName.staticElement as ExecutableElement;
11536 InferenceContext.annotateNode(
11537 node.functionExpression, _enclosingFunction.type);
11232 super.visitFunctionDeclaration(node); 11538 super.visitFunctionDeclaration(node);
11233 } finally { 11539 } finally {
11234 _enclosingFunction = outerFunction; 11540 _enclosingFunction = outerFunction;
11235 } 11541 }
11236 return null; 11542 return null;
11237 } 11543 }
11238 11544
11239 @override 11545 @override
11240 Object visitFunctionExpression(FunctionExpression node) { 11546 Object visitFunctionExpression(FunctionExpression node) {
11241 ExecutableElement outerFunction = _enclosingFunction; 11547 ExecutableElement outerFunction = _enclosingFunction;
11242 try { 11548 try {
11243 _enclosingFunction = node.element; 11549 _enclosingFunction = node.element;
11244 _overrideManager.enterScope(); 11550 _overrideManager.enterScope();
11245 try { 11551 try {
11552 DartType functionType = InferenceContext.get(node);
11553 if (functionType is FunctionType) {
11554 _inferFormalParameterList(node.parameters, functionType);
11555 InferenceContext.annotateNode(node.body, functionType.returnType);
11556 }
11246 super.visitFunctionExpression(node); 11557 super.visitFunctionExpression(node);
11247 } finally { 11558 } finally {
11248 _overrideManager.exitScope(); 11559 _overrideManager.exitScope();
11249 } 11560 }
11250 } finally { 11561 } finally {
11251 _enclosingFunction = outerFunction; 11562 _enclosingFunction = outerFunction;
11252 } 11563 }
11253 return null; 11564 return null;
11254 } 11565 }
11255 11566
11256 @override 11567 @override
11257 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 11568 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
11258 safelyVisit(node.function); 11569 safelyVisit(node.function);
11259 node.accept(elementResolver); 11570 node.accept(elementResolver);
11260 _inferFunctionExpressionsParametersTypes(node.argumentList); 11571 _inferFunctionExpressionsParametersTypes(node.argumentList);
11572 InferenceContext.annotateNode(node.argumentList, node.function.staticType);
11261 safelyVisit(node.argumentList); 11573 safelyVisit(node.argumentList);
11262 node.accept(typeAnalyzer); 11574 node.accept(typeAnalyzer);
11263 return null; 11575 return null;
11264 } 11576 }
11265 11577
11266 @override 11578 @override
11267 Object visitFunctionTypeAlias(FunctionTypeAlias node) { 11579 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
11268 // Resolve the metadata in the library scope. 11580 // Resolve the metadata in the library scope.
11269 if (node.metadata != null) { 11581 if (node.metadata != null) {
11270 node.metadata.accept(this); 11582 node.metadata.accept(this);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
11338 List<Map<VariableElement, DartType>> perBranchOverrides = 11650 List<Map<VariableElement, DartType>> perBranchOverrides =
11339 new List<Map<VariableElement, DartType>>(); 11651 new List<Map<VariableElement, DartType>>();
11340 perBranchOverrides.add(thenOverrides); 11652 perBranchOverrides.add(thenOverrides);
11341 perBranchOverrides.add(elseOverrides); 11653 perBranchOverrides.add(elseOverrides);
11342 _overrideManager.mergeOverrides(perBranchOverrides); 11654 _overrideManager.mergeOverrides(perBranchOverrides);
11343 } 11655 }
11344 return null; 11656 return null;
11345 } 11657 }
11346 11658
11347 @override 11659 @override
11660 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
11661 DartType contextType = InferenceContext.get(node);
11662 if (contextType is InterfaceType &&
11663 contextType.typeArguments != null &&
11664 contextType.typeArguments.length > 0) {
11665 TypeName classTypeName = node.constructorName.type;
11666 if (classTypeName.typeArguments == null) {
11667 List<DartType> targs =
11668 inferenceContext.matchTypes(classTypeName.type, contextType);
11669 if (targs != null && targs.any((t) => !t.isDynamic)) {
11670 ClassElement classElement = classTypeName.type.element;
11671 InterfaceType rawType = classElement.type;
11672 InterfaceType fullType =
11673 rawType.substitute2(targs, rawType.typeArguments);
11674 // The element resolver uses the type on the constructor name, so
11675 // infer it first
11676 typeAnalyzer.inferConstructorName(node.constructorName, fullType);
11677 safelyVisit(node.constructorName);
11678 ConstructorElement invokedConstructor =
11679 node.constructorName.staticElement;
11680 FunctionType rawConstructorType = invokedConstructor.type;
11681 FunctionType constructorType = rawConstructorType.substitute2(
11682 targs, rawConstructorType.typeArguments);
11683 InferenceContext.annotateNode(node.argumentList, constructorType);
11684 safelyVisit(node.argumentList);
11685 InferenceContext.annotateNode(node, fullType);
11686 node.accept(elementResolver);
11687 node.accept(typeAnalyzer);
11688 return null;
11689 }
11690 } else {
11691 InferenceContext.clear(node);
11692 }
11693 }
11694 super.visitInstanceCreationExpression(node);
11695 return null;
11696 }
11697
11698 @override
11348 Object visitLabel(Label node) => null; 11699 Object visitLabel(Label node) => null;
11349 11700
11350 @override 11701 @override
11351 Object visitLibraryIdentifier(LibraryIdentifier node) => null; 11702 Object visitLibraryIdentifier(LibraryIdentifier node) => null;
11352 11703
11353 @override 11704 @override
11705 Object visitListLiteral(ListLiteral node) {
11706 DartType contextType = InferenceContext.get(node);
11707 if (node.typeArguments == null && contextType is InterfaceType) {
11708 InterfaceType listD =
11709 typeProvider.listType.substitute4([typeProvider.dynamicType]);
11710 List<DartType> targs = inferenceContext.matchTypes(listD, contextType);
11711 if (targs != null &&
11712 targs.length == 1 &&
11713 targs.any((t) => !t.isDynamic)) {
11714 DartType eType = targs[0];
11715 InterfaceType listT = typeProvider.listType.substitute4([eType]);
11716 for (Expression child in node.elements) {
11717 InferenceContext.annotateNode(child, eType);
11718 }
11719 InferenceContext.annotateNode(node, listT);
11720 } else {
11721 InferenceContext.clear(node);
11722 }
11723 }
11724 super.visitListLiteral(node);
11725 return null;
11726 }
11727
11728 @override
11729 Object visitMapLiteral(MapLiteral node) {
11730 DartType contextType = InferenceContext.get(node);
11731 if (node.typeArguments == null && contextType is InterfaceType) {
11732 InterfaceType mapD = typeProvider.mapType
11733 .substitute4([typeProvider.dynamicType, typeProvider.dynamicType]);
11734 List<DartType> targs = inferenceContext.matchTypes(mapD, contextType);
11735 if (targs != null &&
11736 targs.length == 2 &&
11737 targs.any((t) => !t.isDynamic)) {
11738 DartType kType = targs[0];
11739 DartType vType = targs[1];
11740 InterfaceType mapT = typeProvider.mapType.substitute4([kType, vType]);
11741 for (MapLiteralEntry entry in node.entries) {
11742 InferenceContext.annotateNode(entry.key, kType);
11743 InferenceContext.annotateNode(entry.value, vType);
11744 }
11745 InferenceContext.annotateNode(node, mapT);
11746 } else {
11747 InferenceContext.clear(node);
11748 }
11749 }
11750 super.visitMapLiteral(node);
11751 return null;
11752 }
11753
11754 @override
11354 Object visitMethodDeclaration(MethodDeclaration node) { 11755 Object visitMethodDeclaration(MethodDeclaration node) {
11355 ExecutableElement outerFunction = _enclosingFunction; 11756 ExecutableElement outerFunction = _enclosingFunction;
11356 try { 11757 try {
11357 _enclosingFunction = node.element; 11758 _enclosingFunction = node.element;
11759 _inferFormalParameterList(node.parameters, node.element.type);
11760 InferenceContext.annotateNode(node.body, node.element.type?.returnType);
11358 super.visitMethodDeclaration(node); 11761 super.visitMethodDeclaration(node);
11359 } finally { 11762 } finally {
11360 _enclosingFunction = outerFunction; 11763 _enclosingFunction = outerFunction;
11361 } 11764 }
11362 return null; 11765 return null;
11363 } 11766 }
11364 11767
11365 @override 11768 @override
11366 Object visitMethodInvocation(MethodInvocation node) { 11769 Object visitMethodInvocation(MethodInvocation node) {
11367 // 11770 //
11368 // We visit the target and argument list, but do not visit the method name 11771 // We visit the target and argument list, but do not visit the method name
11369 // because it needs to be visited in the context of the invocation. 11772 // because it needs to be visited in the context of the invocation.
11370 // 11773 //
11371 safelyVisit(node.target); 11774 safelyVisit(node.target);
11372 node.accept(elementResolver); 11775 node.accept(elementResolver);
11373 _inferFunctionExpressionsParametersTypes(node.argumentList); 11776 _inferFunctionExpressionsParametersTypes(node.argumentList);
11777 if (node.methodName.staticElement is ExecutableElement) {
Jennifer Messerly 2015/11/23 22:11:57 suggestion, if you save this into a variable you c
Leaf 2015/12/01 21:49:10 Done.
11778 DartType type = (node.methodName.staticElement as ExecutableElement).type;
11779 InferenceContext.annotateNode(node.argumentList, type);
11780 }
11374 safelyVisit(node.argumentList); 11781 safelyVisit(node.argumentList);
11375 node.accept(typeAnalyzer); 11782 node.accept(typeAnalyzer);
11376 return null; 11783 return null;
11377 } 11784 }
11378 11785
11379 @override 11786 @override
11787 Object visitNamedExpression(NamedExpression node) {
11788 InferenceContext.annotateNode(node.expression, InferenceContext.get(node));
11789 super.visitNamedExpression(node);
Jennifer Messerly 2015/11/23 22:11:57 not sure if Brian got tired of pointing it out ...
Leaf 2015/12/01 21:49:10 Done.
11790 }
11791
11792 @override
11380 Object visitNode(AstNode node) { 11793 Object visitNode(AstNode node) {
11381 node.visitChildren(this); 11794 node.visitChildren(this);
11382 node.accept(elementResolver); 11795 node.accept(elementResolver);
11383 node.accept(typeAnalyzer); 11796 node.accept(typeAnalyzer);
11384 return null; 11797 return null;
11385 } 11798 }
11386 11799
11387 @override 11800 @override
11801 Object visitParenthesizedExpression(ParenthesizedExpression node) {
11802 InferenceContext.annotateNode(node.expression, InferenceContext.get(node));
11803 super.visitParenthesizedExpression(node);
11804 }
11805
11806 @override
11388 Object visitPrefixedIdentifier(PrefixedIdentifier node) { 11807 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
11389 // 11808 //
11390 // We visit the prefix, but do not visit the identifier because it needs to 11809 // We visit the prefix, but do not visit the identifier because it needs to
11391 // be visited in the context of the prefix. 11810 // be visited in the context of the prefix.
11392 // 11811 //
11393 safelyVisit(node.prefix); 11812 safelyVisit(node.prefix);
11394 node.accept(elementResolver); 11813 node.accept(elementResolver);
11395 node.accept(typeAnalyzer); 11814 node.accept(typeAnalyzer);
11396 return null; 11815 return null;
11397 } 11816 }
(...skipping 11 matching lines...) Expand all
11409 } 11828 }
11410 11829
11411 @override 11830 @override
11412 Object visitRedirectingConstructorInvocation( 11831 Object visitRedirectingConstructorInvocation(
11413 RedirectingConstructorInvocation node) { 11832 RedirectingConstructorInvocation node) {
11414 // 11833 //
11415 // We visit the argument list, but do not visit the optional identifier 11834 // We visit the argument list, but do not visit the optional identifier
11416 // because it needs to be visited in the context of the constructor 11835 // because it needs to be visited in the context of the constructor
11417 // invocation. 11836 // invocation.
11418 // 11837 //
11838 InferenceContext.annotateNode(node.argumentList, node.staticElement?.type);
11419 safelyVisit(node.argumentList); 11839 safelyVisit(node.argumentList);
11420 node.accept(elementResolver); 11840 node.accept(elementResolver);
11421 node.accept(typeAnalyzer); 11841 node.accept(typeAnalyzer);
11422 return null; 11842 return null;
11423 } 11843 }
11424 11844
11425 @override 11845 @override
11846 Object visitReturnStatement(ReturnStatement node) {
11847 InferenceContext.annotateNode(
11848 node.expression, inferenceContext.returnContext);
11849 super.visitReturnStatement(node);
11850 }
11851
11852 @override
11426 Object visitShowCombinator(ShowCombinator node) => null; 11853 Object visitShowCombinator(ShowCombinator node) => null;
11427 11854
11428 @override 11855 @override
11429 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { 11856 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
11430 // 11857 //
11431 // We visit the argument list, but do not visit the optional identifier 11858 // We visit the argument list, but do not visit the optional identifier
11432 // because it needs to be visited in the context of the constructor 11859 // because it needs to be visited in the context of the constructor
11433 // invocation. 11860 // invocation.
11434 // 11861 //
11862 InferenceContext.annotateNode(node.argumentList, node.staticElement?.type);
11435 safelyVisit(node.argumentList); 11863 safelyVisit(node.argumentList);
11436 node.accept(elementResolver); 11864 node.accept(elementResolver);
11437 node.accept(typeAnalyzer); 11865 node.accept(typeAnalyzer);
11438 return null; 11866 return null;
11439 } 11867 }
11440 11868
11441 @override 11869 @override
11442 Object visitSwitchCase(SwitchCase node) { 11870 Object visitSwitchCase(SwitchCase node) {
11443 _overrideManager.enterScope(); 11871 _overrideManager.enterScope();
11444 try { 11872 try {
(...skipping 27 matching lines...) Expand all
11472 _overrideManager.applyOverrides(overrides); 11900 _overrideManager.applyOverrides(overrides);
11473 } 11901 }
11474 return null; 11902 return null;
11475 } 11903 }
11476 11904
11477 @override 11905 @override
11478 Object visitTypeName(TypeName node) => null; 11906 Object visitTypeName(TypeName node) => null;
11479 11907
11480 @override 11908 @override
11481 Object visitVariableDeclaration(VariableDeclaration node) { 11909 Object visitVariableDeclaration(VariableDeclaration node) {
11910 InferenceContext.annotateNode(node.initializer, InferenceContext.get(node));
11482 super.visitVariableDeclaration(node); 11911 super.visitVariableDeclaration(node);
11483 VariableElement element = node.element; 11912 VariableElement element = node.element;
11484 if (element.initializer != null && node.initializer != null) { 11913 if (element.initializer != null && node.initializer != null) {
11485 (element.initializer as FunctionElementImpl).returnType = 11914 (element.initializer as FunctionElementImpl).returnType =
11486 node.initializer.staticType; 11915 node.initializer.staticType;
11487 } 11916 }
11488 // Note: in addition to cloning the initializers for const variables, we 11917 // Note: in addition to cloning the initializers for const variables, we
11489 // have to clone the initializers for non-static final fields (because if 11918 // have to clone the initializers for non-static final fields (because if
11490 // they occur in a class with a const constructor, they will be needed to 11919 // they occur in a class with a const constructor, they will be needed to
11491 // evaluate the const constructor). 11920 // evaluate the const constructor).
11492 if ((element.isConst || 11921 if ((element.isConst ||
11493 (element is FieldElement && 11922 (element is FieldElement &&
11494 element.isFinal && 11923 element.isFinal &&
11495 !element.isStatic)) && 11924 !element.isStatic)) &&
11496 node.initializer != null) { 11925 node.initializer != null) {
11497 (element as ConstVariableElement).constantInitializer = 11926 (element as ConstVariableElement).constantInitializer =
11498 new ConstantAstCloner().cloneNode(node.initializer); 11927 new ConstantAstCloner().cloneNode(node.initializer);
11499 } 11928 }
11500 return null; 11929 return null;
11501 } 11930 }
11502 11931
11932 @override visitVariableDeclarationList(VariableDeclarationList node) {
11933 for (VariableDeclaration decl in node.variables) {
11934 InferenceContext.annotateNode(decl, node.type?.type);
11935 }
11936 super.visitVariableDeclarationList(node);
11937 }
11938
11503 @override 11939 @override
11504 Object visitWhileStatement(WhileStatement node) { 11940 Object visitWhileStatement(WhileStatement node) {
11505 // Note: since we don't call the base class, we have to maintain 11941 // Note: since we don't call the base class, we have to maintain
11506 // _implicitLabelScope ourselves. 11942 // _implicitLabelScope ourselves.
11507 ImplicitLabelScope outerImplicitScope = _implicitLabelScope; 11943 ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
11508 try { 11944 try {
11509 _implicitLabelScope = _implicitLabelScope.nest(node); 11945 _implicitLabelScope = _implicitLabelScope.nest(node);
11510 Expression condition = node.condition; 11946 Expression condition = node.condition;
11511 safelyVisit(condition); 11947 safelyVisit(condition);
11512 Statement body = node.body; 11948 Statement body = node.body;
11513 if (body != null) { 11949 if (body != null) {
11514 _overrideManager.enterScope(); 11950 _overrideManager.enterScope();
11515 try { 11951 try {
11516 _propagateTrueState(condition); 11952 _propagateTrueState(condition);
11517 visitStatementInScope(body); 11953 visitStatementInScope(body);
11518 } finally { 11954 } finally {
11519 _overrideManager.exitScope(); 11955 _overrideManager.exitScope();
11520 } 11956 }
11521 } 11957 }
11522 } finally { 11958 } finally {
11523 _implicitLabelScope = outerImplicitScope; 11959 _implicitLabelScope = outerImplicitScope;
11524 } 11960 }
11525 // TODO(brianwilkerson) If the loop can only be exited because the condition 11961 // TODO(brianwilkerson) If the loop can only be exited because the condition
11526 // is false, then propagateFalseState(condition); 11962 // is false, then propagateFalseState(condition);
11527 node.accept(elementResolver); 11963 node.accept(elementResolver);
11528 node.accept(typeAnalyzer); 11964 node.accept(typeAnalyzer);
11529 return null; 11965 return null;
11530 } 11966 }
11531 11967
11968 @override
11969 Object visitYieldStatement(YieldStatement node) {
11970 DartType returnType = inferenceContext.returnContext;
11971 if (returnType != null && _enclosingFunction != null) {
11972 // If we're not in a generator ([a]sync*, then we shouldn't have a yield.
11973 // so don't infer
11974 if (_enclosingFunction.isGenerator) {
11975 // If this is a yield*, then we just propagate the return type downwards
11976 DartType type = returnType;
11977 // If this just a yield, then we need to get the element type
11978 if (node.star == null) {
11979 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
11980 InterfaceType wrapperD = (_enclosingFunction.isSynchronous)
Jennifer Messerly 2015/11/23 22:11:57 nit: parens not needed
Leaf 2015/12/01 21:49:11 Done.
11981 ? typeProvider.iterableDynamicType
11982 : typeProvider.streamDynamicType;
11983 // Match the types to instantiate the type arguments if possible
11984 List<DartType> targs =
11985 inferenceContext.matchTypes(wrapperD, returnType);
11986 type = (targs?.length == 1) ? targs[0] : null;
11987 }
11988 InferenceContext.annotateNode(node.expression, type);
11989 }
11990 }
11991 super.visitYieldStatement(node);
Brian Wilkerson 2015/11/21 16:12:22 Missing return
Leaf 2015/11/24 19:32:12 Just a meta-comment: this is one of those analyzer
Brian Wilkerson 2015/11/24 21:17:57 That depends on the IDE. I don't know of any way t
Leaf 2015/12/01 21:49:10 Done.
11992 }
11993
11532 /** 11994 /**
11533 * Checks each promoted variable in the current scope for compliance with the following 11995 * Checks each promoted variable in the current scope for compliance with the following
11534 * specification statement: 11996 * specification statement:
11535 * 11997 *
11536 * If the variable <i>v</i> is accessed by a closure in <i>s<sub>1</sub></i> t hen the variable 11998 * If the variable <i>v</i> is accessed by a closure in <i>s<sub>1</sub></i> t hen the variable
11537 * <i>v</i> is not potentially mutated anywhere in the scope of <i>v</i>. 11999 * <i>v</i> is not potentially mutated anywhere in the scope of <i>v</i>.
11538 */ 12000 */
11539 void _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated( 12001 void _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
11540 AstNode target) { 12002 AstNode target) {
11541 for (Element element in _promoteManager.promotedElements) { 12003 for (Element element in _promoteManager.promotedElements) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
11616 List<ParameterElement> onDataParameters = onDataType.parameters; 12078 List<ParameterElement> onDataParameters = onDataType.parameters;
11617 if (onDataParameters == null || onDataParameters.isEmpty) { 12079 if (onDataParameters == null || onDataParameters.isEmpty) {
11618 return null; 12080 return null;
11619 } 12081 }
11620 return onDataParameters[0].type; 12082 return onDataParameters[0].type;
11621 } 12083 }
11622 } 12084 }
11623 return null; 12085 return null;
11624 } 12086 }
11625 12087
12088 void _inferFormalParameterList(FormalParameterList node, DartType type) {
12089 if (typeAnalyzer.inferFormalParameterList(node, type)) {
12090 // TODO(leafp): This gets dropped on the floor if we're in the field
12091 // inference task. We should probably keep these infos.
12092 inferenceContext.recordInference(node.parent, type);
12093 }
12094 }
12095
11626 /** 12096 /**
11627 * If given "mayBeClosure" is [FunctionExpression] without explicit parameters types and its 12097 * If given "mayBeClosure" is [FunctionExpression] without explicit parameters types and its
11628 * required type is [FunctionType], then infer parameters types from [Function Type]. 12098 * required type is [FunctionType], then infer parameters types from [Function Type].
11629 */ 12099 */
11630 void _inferFunctionExpressionParametersTypes( 12100 void _inferFunctionExpressionParametersTypes(
11631 Expression mayBeClosure, DartType mayByFunctionType) { 12101 Expression mayBeClosure, DartType mayByFunctionType) {
11632 // prepare closure 12102 // prepare closure
11633 if (mayBeClosure is! FunctionExpression) { 12103 if (mayBeClosure is! FunctionExpression) {
11634 return; 12104 return;
11635 } 12105 }
(...skipping 3913 matching lines...) Expand 10 before | Expand all | Expand 10 after
15549 nonFields.add(node); 16019 nonFields.add(node);
15550 return null; 16020 return null;
15551 } 16021 }
15552 16022
15553 @override 16023 @override
15554 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); 16024 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this);
15555 16025
15556 @override 16026 @override
15557 Object visitWithClause(WithClause node) => null; 16027 Object visitWithClause(WithClause node) => null;
15558 } 16028 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698