OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |