| 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:math" as math; | 7 import "dart:math" as math; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:analyzer/src/generated/utilities_collection.dart'; | 10 import 'package:analyzer/src/generated/utilities_collection.dart'; |
| (...skipping 11141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11152 _propagateTrueState(condition); | 11152 _propagateTrueState(condition); |
| 11153 _overrideManager.applyOverrides(thenOverrides); | 11153 _overrideManager.applyOverrides(thenOverrides); |
| 11154 } else if (thenIsAbrupt && !elseIsAbrupt) { | 11154 } else if (thenIsAbrupt && !elseIsAbrupt) { |
| 11155 _propagateFalseState(condition); | 11155 _propagateFalseState(condition); |
| 11156 _overrideManager.applyOverrides(elseOverrides); | 11156 _overrideManager.applyOverrides(elseOverrides); |
| 11157 } else if (!thenIsAbrupt && !elseIsAbrupt) { | 11157 } else if (!thenIsAbrupt && !elseIsAbrupt) { |
| 11158 List<Map<VariableElement, DartType>> perBranchOverrides = | 11158 List<Map<VariableElement, DartType>> perBranchOverrides = |
| 11159 new List<Map<VariableElement, DartType>>(); | 11159 new List<Map<VariableElement, DartType>>(); |
| 11160 perBranchOverrides.add(thenOverrides); | 11160 perBranchOverrides.add(thenOverrides); |
| 11161 perBranchOverrides.add(elseOverrides); | 11161 perBranchOverrides.add(elseOverrides); |
| 11162 if (AnalysisEngine.instance.enableUnionTypes) { | 11162 _overrideManager.mergeOverrides(perBranchOverrides); |
| 11163 _overrideManager.joinOverrides(perBranchOverrides); | |
| 11164 } else { | |
| 11165 _overrideManager.mergeOverrides(perBranchOverrides); | |
| 11166 } | |
| 11167 } | 11163 } |
| 11168 return null; | 11164 return null; |
| 11169 } | 11165 } |
| 11170 | 11166 |
| 11171 @override | 11167 @override |
| 11172 Object visitLabel(Label node) => null; | 11168 Object visitLabel(Label node) => null; |
| 11173 | 11169 |
| 11174 @override | 11170 @override |
| 11175 Object visitLibraryIdentifier(LibraryIdentifier node) => null; | 11171 Object visitLibraryIdentifier(LibraryIdentifier node) => null; |
| 11176 | 11172 |
| (...skipping 1717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12894 * @return the overridden type of the given element | 12890 * @return the overridden type of the given element |
| 12895 */ | 12891 */ |
| 12896 DartType getType(Element element) { | 12892 DartType getType(Element element) { |
| 12897 if (_currentScope == null) { | 12893 if (_currentScope == null) { |
| 12898 return null; | 12894 return null; |
| 12899 } | 12895 } |
| 12900 return _currentScope.getType(element); | 12896 return _currentScope.getType(element); |
| 12901 } | 12897 } |
| 12902 | 12898 |
| 12903 /** | 12899 /** |
| 12904 * Update overrides assuming `perBranchOverrides` is the collection of per-bra
nch overrides | |
| 12905 * for *all* branches flowing into a join point. If a variable is updated in e
ach per-branch | |
| 12906 * override, then its type before the branching is ignored. Otherwise, its typ
e before the | |
| 12907 * branching is merged with all updates in the branches. | |
| 12908 * | |
| 12909 * Although this method would do the right thing for a single set of overrides
, we require there | |
| 12910 * to be at least two override sets. Instead use `applyOverrides` for to apply
a single set. | |
| 12911 * | |
| 12912 * For example, for the code | |
| 12913 * | |
| 12914 * <pre> | |
| 12915 * if (c) { | |
| 12916 * ... | |
| 12917 * } else { | |
| 12918 * ... | |
| 12919 * } | |
| 12920 * </pre> | |
| 12921 * the `perBranchOverrides` would include overrides for the then and else bran
ches, and for | |
| 12922 * the code | |
| 12923 * | |
| 12924 * <pre> | |
| 12925 * ... | |
| 12926 * while(c) { | |
| 12927 * ... | |
| 12928 * } | |
| 12929 * </pre> | |
| 12930 * the `perBranchOverrides` would include overrides for before the loop and fo
r the loop | |
| 12931 * body. | |
| 12932 * | |
| 12933 * @param perBranchOverrides one set of overrides for each (at least two) bran
ch flowing into the | |
| 12934 * join point | |
| 12935 */ | |
| 12936 void joinOverrides(List<Map<VariableElement, DartType>> perBranchOverrides) { | |
| 12937 if (perBranchOverrides.length < 2) { | |
| 12938 throw new IllegalArgumentException( | |
| 12939 "There is no point in joining zero or one override sets."); | |
| 12940 } | |
| 12941 Set<VariableElement> allElements = new HashSet<VariableElement>(); | |
| 12942 Set<VariableElement> commonElements = | |
| 12943 new HashSet<VariableElement>.from(perBranchOverrides[0].keys.toSet()); | |
| 12944 for (Map<VariableElement, DartType> os in perBranchOverrides) { | |
| 12945 // Union: elements updated in some branch. | |
| 12946 allElements.addAll(os.keys.toSet()); | |
| 12947 // Intersection: elements updated in all branches. | |
| 12948 commonElements.retainAll(os.keys.toSet()); | |
| 12949 } | |
| 12950 Set<VariableElement> uncommonElements = allElements; | |
| 12951 // Difference: elements updated in some but not all branches. | |
| 12952 uncommonElements.removeAll(commonElements); | |
| 12953 Map<VariableElement, DartType> joinOverrides = | |
| 12954 new HashMap<VariableElement, DartType>(); | |
| 12955 // The common elements were updated in all branches, so their type | |
| 12956 // before branching can be ignored. | |
| 12957 for (VariableElement e in commonElements) { | |
| 12958 joinOverrides[e] = perBranchOverrides[0][e]; | |
| 12959 for (Map<VariableElement, DartType> os in perBranchOverrides) { | |
| 12960 joinOverrides[e] = UnionTypeImpl.union([joinOverrides[e], os[e]]); | |
| 12961 } | |
| 12962 } | |
| 12963 // The uncommon elements were updated in some but not all branches, | |
| 12964 // so they may still have the type they had before branching. | |
| 12965 for (VariableElement e in uncommonElements) { | |
| 12966 joinOverrides[e] = getBestType(e); | |
| 12967 for (Map<VariableElement, DartType> os in perBranchOverrides) { | |
| 12968 if (os.containsKey(e)) { | |
| 12969 joinOverrides[e] = UnionTypeImpl.union([joinOverrides[e], os[e]]); | |
| 12970 } | |
| 12971 } | |
| 12972 } | |
| 12973 applyOverrides(joinOverrides); | |
| 12974 } | |
| 12975 | |
| 12976 /** | |
| 12977 * Update overrides assuming [perBranchOverrides] is the collection of | 12900 * Update overrides assuming [perBranchOverrides] is the collection of |
| 12978 * per-branch overrides for *all* branches flowing into a join point. | 12901 * per-branch overrides for *all* branches flowing into a join point. |
| 12979 * | 12902 * |
| 12980 * If a variable type in any of branches is not the same as its type before | 12903 * If a variable type in any of branches is not the same as its type before |
| 12981 * the branching, then its propagated type is reset to `null`. | 12904 * the branching, then its propagated type is reset to `null`. |
| 12982 */ | 12905 */ |
| 12983 void mergeOverrides(List<Map<VariableElement, DartType>> perBranchOverrides) { | 12906 void mergeOverrides(List<Map<VariableElement, DartType>> perBranchOverrides) { |
| 12984 for (Map<VariableElement, DartType> branch in perBranchOverrides) { | 12907 for (Map<VariableElement, DartType> branch in perBranchOverrides) { |
| 12985 branch.forEach((VariableElement variable, DartType branchType) { | 12908 branch.forEach((VariableElement variable, DartType branchType) { |
| 12986 DartType currentType = _currentScope.getType(variable); | 12909 DartType currentType = _currentScope.getType(variable); |
| (...skipping 2495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15482 nonFields.add(node); | 15405 nonFields.add(node); |
| 15483 return null; | 15406 return null; |
| 15484 } | 15407 } |
| 15485 | 15408 |
| 15486 @override | 15409 @override |
| 15487 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 15410 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 15488 | 15411 |
| 15489 @override | 15412 @override |
| 15490 Object visitWithClause(WithClause node) => null; | 15413 Object visitWithClause(WithClause node) => null; |
| 15491 } | 15414 } |
| OLD | NEW |