| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be | 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
| 6 // refactored to fit into analyzer. | 6 // refactored to fit into analyzer. |
| 7 library analyzer.src.task.strong.checker; | 7 library analyzer.src.task.strong.checker; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 // Malformed type - fallback on analyzer error. | 793 // Malformed type - fallback on analyzer error. |
| 794 return null; | 794 return null; |
| 795 } | 795 } |
| 796 } | 796 } |
| 797 | 797 |
| 798 DartType _getStaticType(Expression expr) { | 798 DartType _getStaticType(Expression expr) { |
| 799 DartType t = expr.staticType ?? DynamicTypeImpl.instance; | 799 DartType t = expr.staticType ?? DynamicTypeImpl.instance; |
| 800 | 800 |
| 801 // Remove fuzzy arrow if possible. | 801 // Remove fuzzy arrow if possible. |
| 802 if (t is FunctionType && StaticInfo.isKnownFunction(expr)) { | 802 if (t is FunctionType && StaticInfo.isKnownFunction(expr)) { |
| 803 t = _removeFuzz(t); | 803 t = rules.functionTypeToConcreteType(typeProvider, t); |
| 804 } | 804 } |
| 805 | 805 |
| 806 return t; | 806 return t; |
| 807 } | 807 } |
| 808 | 808 |
| 809 /// Given an expression, return its type assuming it is | 809 /// Given an expression, return its type assuming it is |
| 810 /// in the caller position of a call (that is, accounting | 810 /// in the caller position of a call (that is, accounting |
| 811 /// for the possibility of a call method). Returns null | 811 /// for the possibility of a call method). Returns null |
| 812 /// if expression is not statically callable. | 812 /// if expression is not statically callable. |
| 813 FunctionType _getTypeAsCaller(Expression node) { | 813 FunctionType _getTypeAsCaller(Expression node) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 if (info is CoercionInfo) { | 901 if (info is CoercionInfo) { |
| 902 // TODO(jmesserly): if we're run again on the same AST, we'll produce the | 902 // TODO(jmesserly): if we're run again on the same AST, we'll produce the |
| 903 // same annotations. This should be harmless. This might go away once | 903 // same annotations. This should be harmless. This might go away once |
| 904 // CodeChecker is integrated better with analyzer, as it will know that | 904 // CodeChecker is integrated better with analyzer, as it will know that |
| 905 // checking has already been performed. | 905 // checking has already been performed. |
| 906 // assert(CoercionInfo.get(info.node) == null); | 906 // assert(CoercionInfo.get(info.node) == null); |
| 907 CoercionInfo.set(info.node, info); | 907 CoercionInfo.set(info.node, info); |
| 908 } | 908 } |
| 909 } | 909 } |
| 910 | 910 |
| 911 /// Remove "fuzzy arrow" in this function type. | |
| 912 /// | |
| 913 /// Normally we treat dynamically typed parameters as bottom for function | |
| 914 /// types. This allows type tests such as `if (f is SingleArgFunction)`. | |
| 915 /// It also requires a dynamic check on the parameter type to call these | |
| 916 /// functions. | |
| 917 /// | |
| 918 /// When we convert to a strict arrow, dynamically typed parameters become | |
| 919 /// top. This is safe to do for known functions, like top-level or local | |
| 920 /// functions and static methods. Those functions must already be essentially | |
| 921 /// treating dynamic as top. | |
| 922 /// | |
| 923 /// Only the outer-most arrow can be strict. Any others must be fuzzy, because | |
| 924 /// we don't know what function value will be passed there. | |
| 925 // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function | |
| 926 // type? That would allow us to implement this in the subtype relation. | |
| 927 // TODO(jmesserly): we'll need to factor this differently if we want to | |
| 928 // move CodeChecker's functionality into existing analyzer. Likely we can | |
| 929 // let the Expression have a strict arrow, then in places were we do | |
| 930 // inference, convert back to a fuzzy arrow. | |
| 931 FunctionType _removeFuzz(FunctionType t) { | |
| 932 bool foundFuzz = false; | |
| 933 List<ParameterElement> parameters = <ParameterElement>[]; | |
| 934 for (ParameterElement p in t.parameters) { | |
| 935 ParameterElement newP = _removeParameterFuzz(p); | |
| 936 parameters.add(newP); | |
| 937 if (p != newP) foundFuzz = true; | |
| 938 } | |
| 939 if (!foundFuzz) { | |
| 940 return t; | |
| 941 } | |
| 942 | |
| 943 FunctionElementImpl function = new FunctionElementImpl("", -1); | |
| 944 function.synthetic = true; | |
| 945 function.returnType = t.returnType; | |
| 946 function.shareTypeParameters(t.typeFormals); | |
| 947 function.shareParameters(parameters); | |
| 948 return function.type = new FunctionTypeImpl(function); | |
| 949 } | |
| 950 | |
| 951 /// Removes fuzzy arrow, see [_removeFuzz]. | |
| 952 ParameterElement _removeParameterFuzz(ParameterElement p) { | |
| 953 if (p.type.isDynamic) { | |
| 954 return new ParameterElementImpl.synthetic( | |
| 955 p.name, typeProvider.objectType, p.parameterKind); | |
| 956 } | |
| 957 return p; | |
| 958 } | |
| 959 | |
| 960 DartType _specializedBinaryReturnType( | 911 DartType _specializedBinaryReturnType( |
| 961 TokenType op, DartType t1, DartType t2, DartType normalReturnType) { | 912 TokenType op, DartType t1, DartType t2, DartType normalReturnType) { |
| 962 // This special cases binary return types as per 16.26 and 16.27 of the | 913 // This special cases binary return types as per 16.26 and 16.27 of the |
| 963 // Dart language spec. | 914 // Dart language spec. |
| 964 switch (op) { | 915 switch (op) { |
| 965 case TokenType.PLUS: | 916 case TokenType.PLUS: |
| 966 case TokenType.MINUS: | 917 case TokenType.MINUS: |
| 967 case TokenType.STAR: | 918 case TokenType.STAR: |
| 968 case TokenType.TILDE_SLASH: | 919 case TokenType.TILDE_SLASH: |
| 969 case TokenType.PERCENT: | 920 case TokenType.PERCENT: |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 } while (!current.isObject && !visited.contains(current)); | 1253 } while (!current.isObject && !visited.contains(current)); |
| 1303 } | 1254 } |
| 1304 | 1255 |
| 1305 void _recordMessage(StaticInfo info) { | 1256 void _recordMessage(StaticInfo info) { |
| 1306 if (info == null) return; | 1257 if (info == null) return; |
| 1307 var error = info.toAnalysisError(); | 1258 var error = info.toAnalysisError(); |
| 1308 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; | 1259 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; |
| 1309 _reporter.onError(error); | 1260 _reporter.onError(error); |
| 1310 } | 1261 } |
| 1311 } | 1262 } |
| OLD | NEW |