| 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 import "dart:math" as math; | 8 import "dart:math" as math; |
| 9 | 9 |
| 10 import 'java_core.dart'; | 10 import 'java_core.dart'; |
| (...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 _checkForInvalidAssignment(node.name, node.initializer); | 827 _checkForInvalidAssignment(node.name, node.initializer); |
| 828 return super.visitVariableDeclaration(node); | 828 return super.visitVariableDeclaration(node); |
| 829 } | 829 } |
| 830 | 830 |
| 831 /** | 831 /** |
| 832 * Check for the passed is expression for the unnecessary type check hint code
s as well as null | 832 * Check for the passed is expression for the unnecessary type check hint code
s as well as null |
| 833 * checks expressed using an is expression. | 833 * checks expressed using an is expression. |
| 834 * | 834 * |
| 835 * @param node the is expression to check | 835 * @param node the is expression to check |
| 836 * @return `true` if and only if a hint code is generated on the passed node | 836 * @return `true` if and only if a hint code is generated on the passed node |
| 837 * @see HintCode#TYPE_CHECK_IS_NOT_NULL | 837 * See [HintCode.TYPE_CHECK_IS_NOT_NULL], [HintCode.TYPE_CHECK_IS_NULL], |
| 838 * @see HintCode#TYPE_CHECK_IS_NULL | 838 * [HintCode.UNNECESSARY_TYPE_CHECK_TRUE], and |
| 839 * @see HintCode#UNNECESSARY_TYPE_CHECK_TRUE | 839 * [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]. |
| 840 * @see HintCode#UNNECESSARY_TYPE_CHECK_FALSE | |
| 841 */ | 840 */ |
| 842 bool _checkAllTypeChecks(IsExpression node) { | 841 bool _checkAllTypeChecks(IsExpression node) { |
| 843 Expression expression = node.expression; | 842 Expression expression = node.expression; |
| 844 TypeName typeName = node.type; | 843 TypeName typeName = node.type; |
| 845 DartType lhsType = expression.staticType; | 844 DartType lhsType = expression.staticType; |
| 846 DartType rhsType = typeName.type; | 845 DartType rhsType = typeName.type; |
| 847 if (lhsType == null || rhsType == null) { | 846 if (lhsType == null || rhsType == null) { |
| 848 return false; | 847 return false; |
| 849 } | 848 } |
| 850 String rhsNameStr = typeName.name.name; | 849 String rhsNameStr = typeName.name.name; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 894 * TODO (jwren) In the ErrorVerifier there are other warnings that we could ha
ve a corresponding | 893 * TODO (jwren) In the ErrorVerifier there are other warnings that we could ha
ve a corresponding |
| 895 * hint for: see other callers of ErrorVerifier.checkForArgumentTypeNotAssigna
ble(..). | 894 * hint for: see other callers of ErrorVerifier.checkForArgumentTypeNotAssigna
ble(..). |
| 896 * | 895 * |
| 897 * @param expression the expression to evaluate | 896 * @param expression the expression to evaluate |
| 898 * @param expectedStaticType the expected static type of the parameter | 897 * @param expectedStaticType the expected static type of the parameter |
| 899 * @param actualStaticType the actual static type of the argument | 898 * @param actualStaticType the actual static type of the argument |
| 900 * @param expectedPropagatedType the expected propagated type of the parameter
, may be | 899 * @param expectedPropagatedType the expected propagated type of the parameter
, may be |
| 901 * `null` | 900 * `null` |
| 902 * @param actualPropagatedType the expected propagated type of the parameter,
may be `null` | 901 * @param actualPropagatedType the expected propagated type of the parameter,
may be `null` |
| 903 * @return `true` if and only if an hint code is generated on the passed node | 902 * @return `true` if and only if an hint code is generated on the passed node |
| 904 * @see HintCode#ARGUMENT_TYPE_NOT_ASSIGNABLE | 903 * See [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. |
| 905 */ | 904 */ |
| 906 bool _checkForArgumentTypeNotAssignable(Expression expression, DartType expect
edStaticType, DartType actualStaticType, DartType expectedPropagatedType, DartTy
pe actualPropagatedType, ErrorCode hintCode) { | 905 bool _checkForArgumentTypeNotAssignable(Expression expression, DartType expect
edStaticType, DartType actualStaticType, DartType expectedPropagatedType, DartTy
pe actualPropagatedType, ErrorCode hintCode) { |
| 907 // | 906 // |
| 908 // Warning case: test static type information | 907 // Warning case: test static type information |
| 909 // | 908 // |
| 910 if (actualStaticType != null && expectedStaticType != null) { | 909 if (actualStaticType != null && expectedStaticType != null) { |
| 911 if (!actualStaticType.isAssignableTo(expectedStaticType)) { | 910 if (!actualStaticType.isAssignableTo(expectedStaticType)) { |
| 912 // A warning was created in the ErrorVerifier, return false, don't creat
e a hint when a | 911 // A warning was created in the ErrorVerifier, return false, don't creat
e a hint when a |
| 913 // warning has already been created. | 912 // warning has already been created. |
| 914 return false; | 913 return false; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 929 return false; | 928 return false; |
| 930 } | 929 } |
| 931 | 930 |
| 932 /** | 931 /** |
| 933 * This verifies that the passed argument can be assigned to its corresponding
parameter. | 932 * This verifies that the passed argument can be assigned to its corresponding
parameter. |
| 934 * | 933 * |
| 935 * This method corresponds to ErrorCode.checkForArgumentTypeNotAssignableForAr
gument. | 934 * This method corresponds to ErrorCode.checkForArgumentTypeNotAssignableForAr
gument. |
| 936 * | 935 * |
| 937 * @param argument the argument to evaluate | 936 * @param argument the argument to evaluate |
| 938 * @return `true` if and only if an hint code is generated on the passed node | 937 * @return `true` if and only if an hint code is generated on the passed node |
| 939 * @see HintCode#ARGUMENT_TYPE_NOT_ASSIGNABLE | 938 * See [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. |
| 940 */ | 939 */ |
| 941 bool _checkForArgumentTypeNotAssignableForArgument(Expression argument) { | 940 bool _checkForArgumentTypeNotAssignableForArgument(Expression argument) { |
| 942 if (argument == null) { | 941 if (argument == null) { |
| 943 return false; | 942 return false; |
| 944 } | 943 } |
| 945 ParameterElement staticParameterElement = argument.staticParameterElement; | 944 ParameterElement staticParameterElement = argument.staticParameterElement; |
| 946 DartType staticParameterType = staticParameterElement == null ? null : stati
cParameterElement.type; | 945 DartType staticParameterType = staticParameterElement == null ? null : stati
cParameterElement.type; |
| 947 ParameterElement propagatedParameterElement = argument.propagatedParameterEl
ement; | 946 ParameterElement propagatedParameterElement = argument.propagatedParameterEl
ement; |
| 948 DartType propagatedParameterType = propagatedParameterElement == null ? null
: propagatedParameterElement.type; | 947 DartType propagatedParameterType = propagatedParameterElement == null ? null
: propagatedParameterElement.type; |
| 949 return _checkForArgumentTypeNotAssignableWithExpectedTypes(argument, staticP
arameterType, propagatedParameterType, HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE); | 948 return _checkForArgumentTypeNotAssignableWithExpectedTypes(argument, staticP
arameterType, propagatedParameterType, HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE); |
| 950 } | 949 } |
| 951 | 950 |
| 952 /** | 951 /** |
| 953 * This verifies that the passed expression can be assigned to its correspondi
ng parameters. | 952 * This verifies that the passed expression can be assigned to its correspondi
ng parameters. |
| 954 * | 953 * |
| 955 * This method corresponds to ErrorCode.checkForArgumentTypeNotAssignableWithE
xpectedTypes. | 954 * This method corresponds to ErrorCode.checkForArgumentTypeNotAssignableWithE
xpectedTypes. |
| 956 * | 955 * |
| 957 * @param expression the expression to evaluate | 956 * @param expression the expression to evaluate |
| 958 * @param expectedStaticType the expected static type | 957 * @param expectedStaticType the expected static type |
| 959 * @param expectedPropagatedType the expected propagated type, may be `null` | 958 * @param expectedPropagatedType the expected propagated type, may be `null` |
| 960 * @return `true` if and only if an hint code is generated on the passed node | 959 * @return `true` if and only if an hint code is generated on the passed node |
| 961 * @see HintCode#ARGUMENT_TYPE_NOT_ASSIGNABLE | 960 * See [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. |
| 962 */ | 961 */ |
| 963 bool _checkForArgumentTypeNotAssignableWithExpectedTypes(Expression expression
, DartType expectedStaticType, DartType expectedPropagatedType, ErrorCode errorC
ode) => _checkForArgumentTypeNotAssignable(expression, expectedStaticType, expre
ssion.staticType, expectedPropagatedType, expression.propagatedType, errorCode); | 962 bool _checkForArgumentTypeNotAssignableWithExpectedTypes(Expression expression
, DartType expectedStaticType, DartType expectedPropagatedType, ErrorCode errorC
ode) => _checkForArgumentTypeNotAssignable(expression, expectedStaticType, expre
ssion.staticType, expectedPropagatedType, expression.propagatedType, errorCode); |
| 964 | 963 |
| 965 /** | 964 /** |
| 966 * This verifies that the passed arguments can be assigned to their correspond
ing parameters. | 965 * This verifies that the passed arguments can be assigned to their correspond
ing parameters. |
| 967 * | 966 * |
| 968 * This method corresponds to ErrorCode.checkForArgumentTypesNotAssignableInLi
st. | 967 * This method corresponds to ErrorCode.checkForArgumentTypesNotAssignableInLi
st. |
| 969 * | 968 * |
| 970 * @param node the arguments to evaluate | 969 * @param node the arguments to evaluate |
| 971 * @return `true` if and only if an hint code is generated on the passed node | 970 * @return `true` if and only if an hint code is generated on the passed node |
| 972 * @see HintCode#ARGUMENT_TYPE_NOT_ASSIGNABLE | 971 * See [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. |
| 973 */ | 972 */ |
| 974 bool _checkForArgumentTypesNotAssignableInList(ArgumentList argumentList) { | 973 bool _checkForArgumentTypesNotAssignableInList(ArgumentList argumentList) { |
| 975 if (argumentList == null) { | 974 if (argumentList == null) { |
| 976 return false; | 975 return false; |
| 977 } | 976 } |
| 978 bool problemReported = false; | 977 bool problemReported = false; |
| 979 for (Expression argument in argumentList.arguments) { | 978 for (Expression argument in argumentList.arguments) { |
| 980 if (_checkForArgumentTypeNotAssignableForArgument(argument)) { | 979 if (_checkForArgumentTypeNotAssignableForArgument(argument)) { |
| 981 problemReported = true; | 980 problemReported = true; |
| 982 } | 981 } |
| 983 } | 982 } |
| 984 return problemReported; | 983 return problemReported; |
| 985 } | 984 } |
| 986 | 985 |
| 987 /** | 986 /** |
| 988 * Given some [Element], look at the associated metadata and report the use of
the member if | 987 * Given some [Element], look at the associated metadata and report the use of
the member if |
| 989 * it is declared as deprecated. | 988 * it is declared as deprecated. |
| 990 * | 989 * |
| 991 * @param element some element to check for deprecated use of | 990 * @param element some element to check for deprecated use of |
| 992 * @param node the node use for the location of the error | 991 * @param node the node use for the location of the error |
| 993 * @return `true` if and only if a hint code is generated on the passed node | 992 * @return `true` if and only if a hint code is generated on the passed node |
| 994 * @see HintCode#DEPRECATED_MEMBER_USE | 993 * See [HintCode.DEPRECATED_MEMBER_USE]. |
| 995 */ | 994 */ |
| 996 bool _checkForDeprecatedMemberUse(Element element, AstNode node) { | 995 bool _checkForDeprecatedMemberUse(Element element, AstNode node) { |
| 997 if (element != null && element.isDeprecated) { | 996 if (element != null && element.isDeprecated) { |
| 998 String displayName = element.displayName; | 997 String displayName = element.displayName; |
| 999 if (element is ConstructorElement) { | 998 if (element is ConstructorElement) { |
| 1000 // TODO(jwren) We should modify ConstructorElement.getDisplayName(), or
have the logic | 999 // TODO(jwren) We should modify ConstructorElement.getDisplayName(), or
have the logic |
| 1001 // centralized elsewhere, instead of doing this logic here. | 1000 // centralized elsewhere, instead of doing this logic here. |
| 1002 ConstructorElement constructorElement = element; | 1001 ConstructorElement constructorElement = element; |
| 1003 displayName = constructorElement.enclosingElement.displayName; | 1002 displayName = constructorElement.enclosingElement.displayName; |
| 1004 if (!constructorElement.displayName.isEmpty) { | 1003 if (!constructorElement.displayName.isEmpty) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1016 * if the node is not in a declaration context. | 1015 * if the node is not in a declaration context. |
| 1017 * | 1016 * |
| 1018 * Also, if the identifier is a constructor name in a constructor invocation,
then calls to the | 1017 * Also, if the identifier is a constructor name in a constructor invocation,
then calls to the |
| 1019 * deprecated constructor will be caught by | 1018 * deprecated constructor will be caught by |
| 1020 * [visitInstanceCreationExpression] and | 1019 * [visitInstanceCreationExpression] and |
| 1021 * [visitSuperConstructorInvocation], and can be ignored by | 1020 * [visitSuperConstructorInvocation], and can be ignored by |
| 1022 * this visit method. | 1021 * this visit method. |
| 1023 * | 1022 * |
| 1024 * @param identifier some simple identifier to check for deprecated use of | 1023 * @param identifier some simple identifier to check for deprecated use of |
| 1025 * @return `true` if and only if a hint code is generated on the passed node | 1024 * @return `true` if and only if a hint code is generated on the passed node |
| 1026 * @see HintCode#DEPRECATED_MEMBER_USE | 1025 * See [HintCode.DEPRECATED_MEMBER_USE]. |
| 1027 */ | 1026 */ |
| 1028 bool _checkForDeprecatedMemberUseAtIdentifier(SimpleIdentifier identifier) { | 1027 bool _checkForDeprecatedMemberUseAtIdentifier(SimpleIdentifier identifier) { |
| 1029 if (identifier.inDeclarationContext()) { | 1028 if (identifier.inDeclarationContext()) { |
| 1030 return false; | 1029 return false; |
| 1031 } | 1030 } |
| 1032 AstNode parent = identifier.parent; | 1031 AstNode parent = identifier.parent; |
| 1033 if ((parent is ConstructorName && identical(identifier, parent.name)) || (pa
rent is SuperConstructorInvocation && identical(identifier, parent.constructorNa
me)) || parent is HideCombinator) { | 1032 if ((parent is ConstructorName && identical(identifier, parent.name)) || (pa
rent is SuperConstructorInvocation && identical(identifier, parent.constructorNa
me)) || parent is HideCombinator) { |
| 1034 return false; | 1033 return false; |
| 1035 } | 1034 } |
| 1036 return _checkForDeprecatedMemberUse(identifier.bestElement, identifier); | 1035 return _checkForDeprecatedMemberUse(identifier.bestElement, identifier); |
| 1037 } | 1036 } |
| 1038 | 1037 |
| 1039 /** | 1038 /** |
| 1040 * Check for the passed binary expression for the [HintCode#DIVISION_OPTIMIZAT
ION]. | 1039 * Check for the passed binary expression for the [HintCode.DIVISION_OPTIMIZAT
ION]. |
| 1041 * | 1040 * |
| 1042 * @param node the binary expression to check | 1041 * @param node the binary expression to check |
| 1043 * @return `true` if and only if a hint code is generated on the passed node | 1042 * @return `true` if and only if a hint code is generated on the passed node |
| 1044 * @see HintCode#DIVISION_OPTIMIZATION | 1043 * See [HintCode.DIVISION_OPTIMIZATION]. |
| 1045 */ | 1044 */ |
| 1046 bool _checkForDivisionOptimizationHint(BinaryExpression node) { | 1045 bool _checkForDivisionOptimizationHint(BinaryExpression node) { |
| 1047 // Return if the operator is not '/' | 1046 // Return if the operator is not '/' |
| 1048 if (node.operator.type != sc.TokenType.SLASH) { | 1047 if (node.operator.type != sc.TokenType.SLASH) { |
| 1049 return false; | 1048 return false; |
| 1050 } | 1049 } |
| 1051 // Return if the '/' operator is not defined in core, or if we don't know it
s static or propagated type | 1050 // Return if the '/' operator is not defined in core, or if we don't know it
s static or propagated type |
| 1052 MethodElement methodElement = node.bestElement; | 1051 MethodElement methodElement = node.bestElement; |
| 1053 if (methodElement == null) { | 1052 if (methodElement == null) { |
| 1054 return false; | 1053 return false; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1072 } | 1071 } |
| 1073 | 1072 |
| 1074 /** | 1073 /** |
| 1075 * This verifies that the passed left hand side and right hand side represent
a valid assignment. | 1074 * This verifies that the passed left hand side and right hand side represent
a valid assignment. |
| 1076 * | 1075 * |
| 1077 * This method corresponds to ErrorVerifier.checkForInvalidAssignment. | 1076 * This method corresponds to ErrorVerifier.checkForInvalidAssignment. |
| 1078 * | 1077 * |
| 1079 * @param lhs the left hand side expression | 1078 * @param lhs the left hand side expression |
| 1080 * @param rhs the right hand side expression | 1079 * @param rhs the right hand side expression |
| 1081 * @return `true` if and only if an error code is generated on the passed node | 1080 * @return `true` if and only if an error code is generated on the passed node |
| 1082 * @see HintCode#INVALID_ASSIGNMENT | 1081 * See [HintCode.INVALID_ASSIGNMENT]. |
| 1083 */ | 1082 */ |
| 1084 bool _checkForInvalidAssignment(Expression lhs, Expression rhs) { | 1083 bool _checkForInvalidAssignment(Expression lhs, Expression rhs) { |
| 1085 if (lhs == null || rhs == null) { | 1084 if (lhs == null || rhs == null) { |
| 1086 return false; | 1085 return false; |
| 1087 } | 1086 } |
| 1088 VariableElement leftVariableElement = ErrorVerifier.getVariableElement(lhs); | 1087 VariableElement leftVariableElement = ErrorVerifier.getVariableElement(lhs); |
| 1089 DartType leftType = (leftVariableElement == null) ? ErrorVerifier.getStaticT
ype(lhs) : leftVariableElement.type; | 1088 DartType leftType = (leftVariableElement == null) ? ErrorVerifier.getStaticT
ype(lhs) : leftVariableElement.type; |
| 1090 DartType staticRightType = ErrorVerifier.getStaticType(rhs); | 1089 DartType staticRightType = ErrorVerifier.getStaticType(rhs); |
| 1091 if (!staticRightType.isAssignableTo(leftType)) { | 1090 if (!staticRightType.isAssignableTo(leftType)) { |
| 1092 // The warning was generated on this rhs | 1091 // The warning was generated on this rhs |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1103 return false; | 1102 return false; |
| 1104 } | 1103 } |
| 1105 | 1104 |
| 1106 /** | 1105 /** |
| 1107 * Check that the imported library does not define a loadLibrary function. The
import has already | 1106 * Check that the imported library does not define a loadLibrary function. The
import has already |
| 1108 * been determined to be deferred when this is called. | 1107 * been determined to be deferred when this is called. |
| 1109 * | 1108 * |
| 1110 * @param node the import directive to evaluate | 1109 * @param node the import directive to evaluate |
| 1111 * @param importElement the [ImportElement] retrieved from the node | 1110 * @param importElement the [ImportElement] retrieved from the node |
| 1112 * @return `true` if and only if an error code is generated on the passed node | 1111 * @return `true` if and only if an error code is generated on the passed node |
| 1113 * @see CompileTimeErrorCode#IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION | 1112 * See [CompileTimeErrorCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION]. |
| 1114 */ | 1113 */ |
| 1115 bool _checkForLoadLibraryFunction(ImportDirective node, ImportElement importEl
ement) { | 1114 bool _checkForLoadLibraryFunction(ImportDirective node, ImportElement importEl
ement) { |
| 1116 LibraryElement importedLibrary = importElement.importedLibrary; | 1115 LibraryElement importedLibrary = importElement.importedLibrary; |
| 1117 if (importedLibrary == null) { | 1116 if (importedLibrary == null) { |
| 1118 return false; | 1117 return false; |
| 1119 } | 1118 } |
| 1120 if (importedLibrary.hasLoadLibraryFunction) { | 1119 if (importedLibrary.hasLoadLibraryFunction) { |
| 1121 _errorReporter.reportErrorForNode(HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LO
AD_FUNCTION, node, [importedLibrary.name]); | 1120 _errorReporter.reportErrorForNode(HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LO
AD_FUNCTION, node, [importedLibrary.name]); |
| 1122 return true; | 1121 return true; |
| 1123 } | 1122 } |
| 1124 return false; | 1123 return false; |
| 1125 } | 1124 } |
| 1126 | 1125 |
| 1127 /** | 1126 /** |
| 1128 * Generate a hint for functions or methods that have a return type, but do no
t have a return | 1127 * Generate a hint for functions or methods that have a return type, but do no
t have a return |
| 1129 * statement on all branches. At the end of blocks with no return, Dart implic
itly returns | 1128 * statement on all branches. At the end of blocks with no return, Dart implic
itly returns |
| 1130 * `null`, avoiding these implicit returns is considered a best practice. | 1129 * `null`, avoiding these implicit returns is considered a best practice. |
| 1131 * | 1130 * |
| 1132 * @param node the binary expression to check | 1131 * @param node the binary expression to check |
| 1133 * @param body the function body | 1132 * @param body the function body |
| 1134 * @return `true` if and only if a hint code is generated on the passed node | 1133 * @return `true` if and only if a hint code is generated on the passed node |
| 1135 * @see HintCode#MISSING_RETURN | 1134 * See [HintCode.MISSING_RETURN]. |
| 1136 */ | 1135 */ |
| 1137 bool _checkForMissingReturn(TypeName returnType, FunctionBody body) { | 1136 bool _checkForMissingReturn(TypeName returnType, FunctionBody body) { |
| 1138 // Check that the method or function has a return type, and a function body | 1137 // Check that the method or function has a return type, and a function body |
| 1139 if (returnType == null || body == null) { | 1138 if (returnType == null || body == null) { |
| 1140 return false; | 1139 return false; |
| 1141 } | 1140 } |
| 1142 // Check that the body is a BlockFunctionBody | 1141 // Check that the body is a BlockFunctionBody |
| 1143 if (body is! BlockFunctionBody) { | 1142 if (body is! BlockFunctionBody) { |
| 1144 return false; | 1143 return false; |
| 1145 } | 1144 } |
| 1146 // Check that the type is resolvable, and is not "void" | 1145 // Check that the type is resolvable, and is not "void" |
| 1147 DartType returnTypeType = returnType.type; | 1146 DartType returnTypeType = returnType.type; |
| 1148 if (returnTypeType == null || returnTypeType.isVoid) { | 1147 if (returnTypeType == null || returnTypeType.isVoid) { |
| 1149 return false; | 1148 return false; |
| 1150 } | 1149 } |
| 1151 // Check the block for a return statement, if not, create the hint | 1150 // Check the block for a return statement, if not, create the hint |
| 1152 BlockFunctionBody blockFunctionBody = body as BlockFunctionBody; | 1151 BlockFunctionBody blockFunctionBody = body as BlockFunctionBody; |
| 1153 if (!blockFunctionBody.accept(new ExitDetector())) { | 1152 if (!blockFunctionBody.accept(new ExitDetector())) { |
| 1154 _errorReporter.reportErrorForNode(HintCode.MISSING_RETURN, returnType, [re
turnTypeType.displayName]); | 1153 _errorReporter.reportErrorForNode(HintCode.MISSING_RETURN, returnType, [re
turnTypeType.displayName]); |
| 1155 return true; | 1154 return true; |
| 1156 } | 1155 } |
| 1157 return false; | 1156 return false; |
| 1158 } | 1157 } |
| 1159 | 1158 |
| 1160 /** | 1159 /** |
| 1161 * Check for the passed class declaration for the | 1160 * Check for the passed class declaration for the |
| 1162 * [HintCode#OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code. | 1161 * [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code. |
| 1163 * | 1162 * |
| 1164 * @param node the class declaration to check | 1163 * @param node the class declaration to check |
| 1165 * @return `true` if and only if a hint code is generated on the passed node | 1164 * @return `true` if and only if a hint code is generated on the passed node |
| 1166 * @see HintCode#OVERRIDE_EQUALS_BUT_NOT_HASH_CODE | 1165 * See [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]. |
| 1167 */ | 1166 */ |
| 1168 bool _checkForOverrideEqualsButNotHashCode(ClassDeclaration node) { | 1167 bool _checkForOverrideEqualsButNotHashCode(ClassDeclaration node) { |
| 1169 ClassElement classElement = node.element; | 1168 ClassElement classElement = node.element; |
| 1170 if (classElement == null) { | 1169 if (classElement == null) { |
| 1171 return false; | 1170 return false; |
| 1172 } | 1171 } |
| 1173 MethodElement equalsOperatorMethodElement = classElement.getMethod(sc.TokenT
ype.EQ_EQ.lexeme); | 1172 MethodElement equalsOperatorMethodElement = classElement.getMethod(sc.TokenT
ype.EQ_EQ.lexeme); |
| 1174 if (equalsOperatorMethodElement != null) { | 1173 if (equalsOperatorMethodElement != null) { |
| 1175 PropertyAccessorElement hashCodeElement = classElement.getGetter(_HASHCODE
_GETTER_NAME); | 1174 PropertyAccessorElement hashCodeElement = classElement.getGetter(_HASHCODE
_GETTER_NAME); |
| 1176 if (hashCodeElement == null) { | 1175 if (hashCodeElement == null) { |
| 1177 _errorReporter.reportErrorForNode(HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_
CODE, node.name, [classElement.displayName]); | 1176 _errorReporter.reportErrorForNode(HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_
CODE, node.name, [classElement.displayName]); |
| 1178 return true; | 1177 return true; |
| 1179 } | 1178 } |
| 1180 } | 1179 } |
| 1181 return false; | 1180 return false; |
| 1182 } | 1181 } |
| 1183 | 1182 |
| 1184 /** | 1183 /** |
| 1185 * Check for the passed as expression for the [HintCode#UNNECESSARY_CAST] hint
code. | 1184 * Check for the passed as expression for the [HintCode.UNNECESSARY_CAST] hint
code. |
| 1186 * | 1185 * |
| 1187 * @param node the as expression to check | 1186 * @param node the as expression to check |
| 1188 * @return `true` if and only if a hint code is generated on the passed node | 1187 * @return `true` if and only if a hint code is generated on the passed node |
| 1189 * @see HintCode#UNNECESSARY_CAST | 1188 * See [HintCode.UNNECESSARY_CAST]. |
| 1190 */ | 1189 */ |
| 1191 bool _checkForUnnecessaryCast(AsExpression node) { | 1190 bool _checkForUnnecessaryCast(AsExpression node) { |
| 1192 Expression expression = node.expression; | 1191 Expression expression = node.expression; |
| 1193 TypeName typeName = node.type; | 1192 TypeName typeName = node.type; |
| 1194 DartType lhsType = expression.staticType; | 1193 DartType lhsType = expression.staticType; |
| 1195 DartType rhsType = typeName.type; | 1194 DartType rhsType = typeName.type; |
| 1196 // TODO(jwren) After dartbug.com/13732, revisit this, we should be able to r
emove the | 1195 // TODO(jwren) After dartbug.com/13732, revisit this, we should be able to r
emove the |
| 1197 // !(x instanceof TypeParameterType) checks. | 1196 // !(x instanceof TypeParameterType) checks. |
| 1198 if (lhsType != null && rhsType != null && !lhsType.isDynamic && !rhsType.isD
ynamic && lhsType is! TypeParameterType && rhsType is! TypeParameterType && lhsT
ype.isMoreSpecificThan(rhsType)) { | 1197 if (lhsType != null && rhsType != null && !lhsType.isDynamic && !rhsType.isD
ynamic && lhsType is! TypeParameterType && rhsType is! TypeParameterType && lhsT
ype.isMoreSpecificThan(rhsType)) { |
| 1199 _errorReporter.reportErrorForNode(HintCode.UNNECESSARY_CAST, node, []); | 1198 _errorReporter.reportErrorForNode(HintCode.UNNECESSARY_CAST, node, []); |
| 1200 return true; | 1199 return true; |
| 1201 } | 1200 } |
| 1202 return false; | 1201 return false; |
| 1203 } | 1202 } |
| 1204 | 1203 |
| 1205 /** | 1204 /** |
| 1206 * Check for situations where the result of a method or function is used, when
it returns 'void'. | 1205 * Check for situations where the result of a method or function is used, when
it returns 'void'. |
| 1207 * | 1206 * |
| 1208 * TODO(jwren) Many other situations of use could be covered. We currently cov
er the cases var x = | 1207 * TODO(jwren) Many other situations of use could be covered. We currently cov
er the cases var x = |
| 1209 * m() and x = m(), but we could also cover cases such as m().x, m()[k], a + m
(), f(m()), return | 1208 * m() and x = m(), but we could also cover cases such as m().x, m()[k], a + m
(), f(m()), return |
| 1210 * m(). | 1209 * m(). |
| 1211 * | 1210 * |
| 1212 * @param node expression on the RHS of some assignment | 1211 * @param node expression on the RHS of some assignment |
| 1213 * @return `true` if and only if a hint code is generated on the passed node | 1212 * @return `true` if and only if a hint code is generated on the passed node |
| 1214 * @see HintCode#USE_OF_VOID_RESULT | 1213 * See [HintCode.USE_OF_VOID_RESULT]. |
| 1215 */ | 1214 */ |
| 1216 bool _checkForUseOfVoidResult(Expression expression) { | 1215 bool _checkForUseOfVoidResult(Expression expression) { |
| 1217 if (expression == null || expression is! MethodInvocation) { | 1216 if (expression == null || expression is! MethodInvocation) { |
| 1218 return false; | 1217 return false; |
| 1219 } | 1218 } |
| 1220 MethodInvocation methodInvocation = expression as MethodInvocation; | 1219 MethodInvocation methodInvocation = expression as MethodInvocation; |
| 1221 if (identical(methodInvocation.staticType, VoidTypeImpl.instance)) { | 1220 if (identical(methodInvocation.staticType, VoidTypeImpl.instance)) { |
| 1222 SimpleIdentifier methodName = methodInvocation.methodName; | 1221 SimpleIdentifier methodName = methodInvocation.methodName; |
| 1223 _errorReporter.reportErrorForNode(HintCode.USE_OF_VOID_RESULT, methodName,
[methodName.name]); | 1222 _errorReporter.reportErrorForNode(HintCode.USE_OF_VOID_RESULT, methodName,
[methodName.name]); |
| 1224 return true; | 1223 return true; |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 return null; | 1544 return null; |
| 1546 } | 1545 } |
| 1547 | 1546 |
| 1548 /** | 1547 /** |
| 1549 * This verifies that the passed switch statement does not have a case express
ion with the | 1548 * This verifies that the passed switch statement does not have a case express
ion with the |
| 1550 * operator '==' overridden. | 1549 * operator '==' overridden. |
| 1551 * | 1550 * |
| 1552 * @param node the switch statement to evaluate | 1551 * @param node the switch statement to evaluate |
| 1553 * @param type the common type of all 'case' expressions | 1552 * @param type the common type of all 'case' expressions |
| 1554 * @return `true` if and only if an error code is generated on the passed node | 1553 * @return `true` if and only if an error code is generated on the passed node |
| 1555 * @see CompileTimeErrorCode#CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS | 1554 * See [CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]. |
| 1556 */ | 1555 */ |
| 1557 bool _checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, DartTyp
e type) { | 1556 bool _checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, DartTyp
e type) { |
| 1558 if (!_implementsEqualsWhenNotAllowed(type)) { | 1557 if (!_implementsEqualsWhenNotAllowed(type)) { |
| 1559 return false; | 1558 return false; |
| 1560 } | 1559 } |
| 1561 // report error | 1560 // report error |
| 1562 _errorReporter.reportErrorForToken(CompileTimeErrorCode.CASE_EXPRESSION_TYPE
_IMPLEMENTS_EQUALS, node.keyword, [type.displayName]); | 1561 _errorReporter.reportErrorForToken(CompileTimeErrorCode.CASE_EXPRESSION_TYPE
_IMPLEMENTS_EQUALS, node.keyword, [type.displayName]); |
| 1563 return true; | 1562 return true; |
| 1564 } | 1563 } |
| 1565 | 1564 |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1836 } | 1835 } |
| 1837 return new DartObjectImpl(type is InterfaceType ? type : ConstantVerifie
r_this._typeProvider.objectType, GenericState.UNKNOWN_VALUE); | 1836 return new DartObjectImpl(type is InterfaceType ? type : ConstantVerifie
r_this._typeProvider.objectType, GenericState.UNKNOWN_VALUE); |
| 1838 } | 1837 } |
| 1839 } | 1838 } |
| 1840 return super.visitSimpleIdentifier(node); | 1839 return super.visitSimpleIdentifier(node); |
| 1841 } | 1840 } |
| 1842 } | 1841 } |
| 1843 | 1842 |
| 1844 /** | 1843 /** |
| 1845 * Instances of the class `Dart2JSVerifier` traverse an AST structure looking fo
r hints for | 1844 * Instances of the class `Dart2JSVerifier` traverse an AST structure looking fo
r hints for |
| 1846 * code that will be compiled to JS, such as [HintCode#IS_DOUBLE]. | 1845 * code that will be compiled to JS, such as [HintCode.IS_DOUBLE]. |
| 1847 */ | 1846 */ |
| 1848 class Dart2JSVerifier extends RecursiveAstVisitor<Object> { | 1847 class Dart2JSVerifier extends RecursiveAstVisitor<Object> { |
| 1849 /** | 1848 /** |
| 1850 * The error reporter by which errors will be reported. | 1849 * The error reporter by which errors will be reported. |
| 1851 */ | 1850 */ |
| 1852 final ErrorReporter _errorReporter; | 1851 final ErrorReporter _errorReporter; |
| 1853 | 1852 |
| 1854 /** | 1853 /** |
| 1855 * The name of the `double` type. | 1854 * The name of the `double` type. |
| 1856 */ | 1855 */ |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1868 _checkForIsDoubleHints(node); | 1867 _checkForIsDoubleHints(node); |
| 1869 return super.visitIsExpression(node); | 1868 return super.visitIsExpression(node); |
| 1870 } | 1869 } |
| 1871 | 1870 |
| 1872 /** | 1871 /** |
| 1873 * Check for instances of `x is double`, `x is int`, `x is! double` and | 1872 * Check for instances of `x is double`, `x is int`, `x is! double` and |
| 1874 * `x is! int`. | 1873 * `x is! int`. |
| 1875 * | 1874 * |
| 1876 * @param node the is expression to check | 1875 * @param node the is expression to check |
| 1877 * @return `true` if and only if a hint code is generated on the passed node | 1876 * @return `true` if and only if a hint code is generated on the passed node |
| 1878 * @see HintCode#IS_DOUBLE | 1877 * See [HintCode.IS_DOUBLE], |
| 1879 * @see HintCode#IS_INT | 1878 * [HintCode.IS_INT], |
| 1880 * @see HintCode#IS_NOT_DOUBLE | 1879 * [HintCode.IS_NOT_DOUBLE], and |
| 1881 * @see HintCode#IS_NOT_INT | 1880 * [HintCode.IS_NOT_INT]. |
| 1882 */ | 1881 */ |
| 1883 bool _checkForIsDoubleHints(IsExpression node) { | 1882 bool _checkForIsDoubleHints(IsExpression node) { |
| 1884 TypeName typeName = node.type; | 1883 TypeName typeName = node.type; |
| 1885 DartType type = typeName.type; | 1884 DartType type = typeName.type; |
| 1886 if (type != null && type.element != null) { | 1885 if (type != null && type.element != null) { |
| 1887 Element element = type.element; | 1886 Element element = type.element; |
| 1888 String typeNameStr = element.name; | 1887 String typeNameStr = element.name; |
| 1889 LibraryElement libraryElement = element.library; | 1888 LibraryElement libraryElement = element.library; |
| 1890 // if (typeNameStr.equals(INT_TYPE_NAME) && libraryElement != null | 1889 // if (typeNameStr.equals(INT_TYPE_NAME) && libraryElement != null |
| 1891 // && libraryElement.isDartCore()) { | 1890 // && libraryElement.isDartCore()) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1930 _errorReporter.reportErrorForElement( | 1929 _errorReporter.reportErrorForElement( |
| 1931 HintCode.UNUSED_LOCAL_VARIABLE, | 1930 HintCode.UNUSED_LOCAL_VARIABLE, |
| 1932 element, | 1931 element, |
| 1933 [element.displayName]); | 1932 [element.displayName]); |
| 1934 } | 1933 } |
| 1935 } | 1934 } |
| 1936 } | 1935 } |
| 1937 | 1936 |
| 1938 /** | 1937 /** |
| 1939 * Instances of the class `DeadCodeVerifier` traverse an AST structure looking f
or cases of | 1938 * Instances of the class `DeadCodeVerifier` traverse an AST structure looking f
or cases of |
| 1940 * [HintCode#DEAD_CODE]. | 1939 * [HintCode.DEAD_CODE]. |
| 1941 */ | 1940 */ |
| 1942 class DeadCodeVerifier extends RecursiveAstVisitor<Object> { | 1941 class DeadCodeVerifier extends RecursiveAstVisitor<Object> { |
| 1943 /** | 1942 /** |
| 1944 * The error reporter by which errors will be reported. | 1943 * The error reporter by which errors will be reported. |
| 1945 */ | 1944 */ |
| 1946 final ErrorReporter _errorReporter; | 1945 final ErrorReporter _errorReporter; |
| 1947 | 1946 |
| 1948 /** | 1947 /** |
| 1949 * Create a new instance of the [DeadCodeVerifier]. | 1948 * Create a new instance of the [DeadCodeVerifier]. |
| 1950 * | 1949 * |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2169 Statement lastStatement = statements[size - 1]; | 2168 Statement lastStatement = statements[size - 1]; |
| 2170 int offset = nextStatement.offset; | 2169 int offset = nextStatement.offset; |
| 2171 int length = lastStatement.end - offset; | 2170 int length = lastStatement.end - offset; |
| 2172 _errorReporter.reportErrorForOffset(HintCode.DEAD_CODE, offset, length,
[]); | 2171 _errorReporter.reportErrorForOffset(HintCode.DEAD_CODE, offset, length,
[]); |
| 2173 return; | 2172 return; |
| 2174 } | 2173 } |
| 2175 } | 2174 } |
| 2176 } | 2175 } |
| 2177 | 2176 |
| 2178 /** | 2177 /** |
| 2179 * Given some [Expression], this method returns [ValidResult#RESULT_TRUE] if i
t is | 2178 * Given some [Expression], this method returns [ValidResult.RESULT_TRUE] if i
t is |
| 2180 * `true`, [ValidResult#RESULT_FALSE] if it is `false`, or `null` if the | 2179 * `true`, [ValidResult.RESULT_FALSE] if it is `false`, or `null` if the |
| 2181 * expression is not a constant boolean value. | 2180 * expression is not a constant boolean value. |
| 2182 * | 2181 * |
| 2183 * @param expression the expression to evaluate | 2182 * @param expression the expression to evaluate |
| 2184 * @return [ValidResult#RESULT_TRUE] if it is `true`, [ValidResult#RESULT_FALS
E] | 2183 * @return [ValidResult.RESULT_TRUE] if it is `true`, [ValidResult.RESULT_FALS
E] |
| 2185 * if it is `false`, or `null` if the expression is not a constant boo
lean | 2184 * if it is `false`, or `null` if the expression is not a constant boo
lean |
| 2186 * value | 2185 * value |
| 2187 */ | 2186 */ |
| 2188 EvaluationResultImpl _getConstantBooleanValue(Expression expression) { | 2187 EvaluationResultImpl _getConstantBooleanValue(Expression expression) { |
| 2189 if (expression is BooleanLiteral) { | 2188 if (expression is BooleanLiteral) { |
| 2190 if (expression.value) { | 2189 if (expression.value) { |
| 2191 return new EvaluationResultImpl.con1(new DartObjectImpl(null, BoolState.
from(true))); | 2190 return new EvaluationResultImpl.con1(new DartObjectImpl(null, BoolState.
from(true))); |
| 2192 } else { | 2191 } else { |
| 2193 return new EvaluationResultImpl.con1(new DartObjectImpl(null, BoolState.
from(false))); | 2192 return new EvaluationResultImpl.con1(new DartObjectImpl(null, BoolState.
from(false))); |
| 2194 } | 2193 } |
| (...skipping 3170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5365 DeclarationMatcher_this._allElements.add(element); | 5364 DeclarationMatcher_this._allElements.add(element); |
| 5366 DeclarationMatcher_this._unmatchedElements.add(element); | 5365 DeclarationMatcher_this._unmatchedElements.add(element); |
| 5367 return super.visitElement(element); | 5366 return super.visitElement(element); |
| 5368 } | 5367 } |
| 5369 } | 5368 } |
| 5370 | 5369 |
| 5371 /** | 5370 /** |
| 5372 * Instances of the class `HintGenerator` traverse a library's worth of dart cod
e at a time to | 5371 * Instances of the class `HintGenerator` traverse a library's worth of dart cod
e at a time to |
| 5373 * generate hints over the set of sources. | 5372 * generate hints over the set of sources. |
| 5374 * | 5373 * |
| 5375 * @see HintCode | 5374 * See [HintCode]. |
| 5376 */ | 5375 */ |
| 5377 class HintGenerator { | 5376 class HintGenerator { |
| 5378 final List<CompilationUnit> _compilationUnits; | 5377 final List<CompilationUnit> _compilationUnits; |
| 5379 | 5378 |
| 5380 final AnalysisContext _context; | 5379 final AnalysisContext _context; |
| 5381 | 5380 |
| 5382 final AnalysisErrorListener _errorListener; | 5381 final AnalysisErrorListener _errorListener; |
| 5383 | 5382 |
| 5384 ImportsVerifier _importsVerifier; | 5383 ImportsVerifier _importsVerifier; |
| 5385 | 5384 |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5840 types[i] = dynamic; | 5839 types[i] = dynamic; |
| 5841 } | 5840 } |
| 5842 } | 5841 } |
| 5843 return types; | 5842 return types; |
| 5844 } | 5843 } |
| 5845 } | 5844 } |
| 5846 | 5845 |
| 5847 /** | 5846 /** |
| 5848 * Instances of the class `ImportsVerifier` visit all of the referenced librarie
s in the | 5847 * Instances of the class `ImportsVerifier` visit all of the referenced librarie
s in the |
| 5849 * source code verifying that all of the imports are used, otherwise a | 5848 * source code verifying that all of the imports are used, otherwise a |
| 5850 * [HintCode#UNUSED_IMPORT] is generated with | 5849 * [HintCode.UNUSED_IMPORT] is generated with |
| 5851 * [generateUnusedImportHints]. | 5850 * [generateUnusedImportHints]. |
| 5852 * | 5851 * |
| 5853 * While this class does not yet have support for an "Organize Imports" action,
this logic built up | 5852 * While this class does not yet have support for an "Organize Imports" action,
this logic built up |
| 5854 * in this class could be used for such an action in the future. | 5853 * in this class could be used for such an action in the future. |
| 5855 */ | 5854 */ |
| 5856 class ImportsVerifier extends RecursiveAstVisitor<Object> { | 5855 class ImportsVerifier extends RecursiveAstVisitor<Object> { |
| 5857 /** | 5856 /** |
| 5858 * This is set to `true` if the current compilation unit which is being visite
d is the | 5857 * This is set to `true` if the current compilation unit which is being visite
d is the |
| 5859 * defining compilation unit for the library, its value can be set with | 5858 * defining compilation unit for the library, its value can be set with |
| 5860 * [setInDefiningCompilationUnit]. | 5859 * [setInDefiningCompilationUnit]. |
| 5861 */ | 5860 */ |
| 5862 bool _inDefiningCompilationUnit = false; | 5861 bool _inDefiningCompilationUnit = false; |
| 5863 | 5862 |
| 5864 /** | 5863 /** |
| 5865 * The current library. | 5864 * The current library. |
| 5866 */ | 5865 */ |
| 5867 LibraryElement _currentLibrary; | 5866 LibraryElement _currentLibrary; |
| 5868 | 5867 |
| 5869 /** | 5868 /** |
| 5870 * A list of [ImportDirective]s that the current library imports, as identifie
rs are visited | 5869 * A list of [ImportDirective]s that the current library imports, as identifie
rs are visited |
| 5871 * by this visitor and an import has been identified as being used by the libr
ary, the | 5870 * by this visitor and an import has been identified as being used by the libr
ary, the |
| 5872 * [ImportDirective] is removed from this list. After all the sources in the l
ibrary have | 5871 * [ImportDirective] is removed from this list. After all the sources in the l
ibrary have |
| 5873 * been evaluated, this list represents the set of unused imports. | 5872 * been evaluated, this list represents the set of unused imports. |
| 5874 * | 5873 * |
| 5875 * @see ImportsVerifier#generateUnusedImportErrors(ErrorReporter) | 5874 * See [ImportsVerifier.generateUnusedImportErrors]. |
| 5876 */ | 5875 */ |
| 5877 List<ImportDirective> _unusedImports; | 5876 List<ImportDirective> _unusedImports; |
| 5878 | 5877 |
| 5879 /** | 5878 /** |
| 5880 * After the list of [unusedImports] has been computed, this list is a proper
subset of the | 5879 * After the list of [unusedImports] has been computed, this list is a proper
subset of the |
| 5881 * unused imports that are listed more than once. | 5880 * unused imports that are listed more than once. |
| 5882 */ | 5881 */ |
| 5883 List<ImportDirective> _duplicateImports; | 5882 List<ImportDirective> _duplicateImports; |
| 5884 | 5883 |
| 5885 /** | 5884 /** |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5924 this._currentLibrary = library; | 5923 this._currentLibrary = library; |
| 5925 this._unusedImports = new List<ImportDirective>(); | 5924 this._unusedImports = new List<ImportDirective>(); |
| 5926 this._duplicateImports = new List<ImportDirective>(); | 5925 this._duplicateImports = new List<ImportDirective>(); |
| 5927 this._libraryMap = new HashMap<LibraryElement, List<ImportDirective>>(); | 5926 this._libraryMap = new HashMap<LibraryElement, List<ImportDirective>>(); |
| 5928 this._namespaceMap = new HashMap<ImportDirective, Namespace>(); | 5927 this._namespaceMap = new HashMap<ImportDirective, Namespace>(); |
| 5929 this._prefixElementMap = new HashMap<PrefixElement, List<ImportDirective>>()
; | 5928 this._prefixElementMap = new HashMap<PrefixElement, List<ImportDirective>>()
; |
| 5930 } | 5929 } |
| 5931 | 5930 |
| 5932 /** | 5931 /** |
| 5933 * Any time after the defining compilation unit has been visited by this visit
or, this method can | 5932 * Any time after the defining compilation unit has been visited by this visit
or, this method can |
| 5934 * be called to report an [HintCode#DUPLICATE_IMPORT] hint for each of the imp
ort directives | 5933 * be called to report an [HintCode.DUPLICATE_IMPORT] hint for each of the imp
ort directives |
| 5935 * in the [duplicateImports] list. | 5934 * in the [duplicateImports] list. |
| 5936 * | 5935 * |
| 5937 * @param errorReporter the error reporter to report the set of [HintCode#DUPL
ICATE_IMPORT] | 5936 * @param errorReporter the error reporter to report the set of [HintCode.DUPL
ICATE_IMPORT] |
| 5938 * hints to | 5937 * hints to |
| 5939 */ | 5938 */ |
| 5940 void generateDuplicateImportHints(ErrorReporter errorReporter) { | 5939 void generateDuplicateImportHints(ErrorReporter errorReporter) { |
| 5941 for (ImportDirective duplicateImport in _duplicateImports) { | 5940 for (ImportDirective duplicateImport in _duplicateImports) { |
| 5942 errorReporter.reportErrorForNode(HintCode.DUPLICATE_IMPORT, duplicateImpor
t.uri, []); | 5941 errorReporter.reportErrorForNode(HintCode.DUPLICATE_IMPORT, duplicateImpor
t.uri, []); |
| 5943 } | 5942 } |
| 5944 } | 5943 } |
| 5945 | 5944 |
| 5946 /** | 5945 /** |
| 5947 * After all of the compilation units have been visited by this visitor, this
method can be called | 5946 * After all of the compilation units have been visited by this visitor, this
method can be called |
| 5948 * to report an [HintCode#UNUSED_IMPORT] hint for each of the import directive
s in the | 5947 * to report an [HintCode.UNUSED_IMPORT] hint for each of the import directive
s in the |
| 5949 * [unusedImports] list. | 5948 * [unusedImports] list. |
| 5950 * | 5949 * |
| 5951 * @param errorReporter the error reporter to report the set of [HintCode#UNUS
ED_IMPORT] | 5950 * @param errorReporter the error reporter to report the set of [HintCode.UNUS
ED_IMPORT] |
| 5952 * hints to | 5951 * hints to |
| 5953 */ | 5952 */ |
| 5954 void generateUnusedImportHints(ErrorReporter errorReporter) { | 5953 void generateUnusedImportHints(ErrorReporter errorReporter) { |
| 5955 for (ImportDirective unusedImport in _unusedImports) { | 5954 for (ImportDirective unusedImport in _unusedImports) { |
| 5956 // Check that the import isn't dart:core | 5955 // Check that the import isn't dart:core |
| 5957 ImportElement importElement = unusedImport.element; | 5956 ImportElement importElement = unusedImport.element; |
| 5958 if (importElement != null) { | 5957 if (importElement != null) { |
| 5959 LibraryElement libraryElement = importElement.importedLibrary; | 5958 LibraryElement libraryElement = importElement.importedLibrary; |
| 5960 if (libraryElement != null && libraryElement.isDartCore) { | 5959 if (libraryElement != null && libraryElement.isDartCore) { |
| 5961 continue; | 5960 continue; |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6260 throw new AnalysisException("Cannot resolve node: element model changed"); | 6259 throw new AnalysisException("Cannot resolve node: element model changed"); |
| 6261 } | 6260 } |
| 6262 _resolveTypes(node, scope); | 6261 _resolveTypes(node, scope); |
| 6263 _resolveVariables(node, scope); | 6262 _resolveVariables(node, scope); |
| 6264 _resolveReferences(node, scope); | 6263 _resolveReferences(node, scope); |
| 6265 } | 6264 } |
| 6266 | 6265 |
| 6267 /** | 6266 /** |
| 6268 * Return `true` if the given node can be resolved independently of any other
nodes. | 6267 * Return `true` if the given node can be resolved independently of any other
nodes. |
| 6269 * | 6268 * |
| 6270 * <b>Note:</b> This method needs to be kept in sync with [ScopeBuilder#scopeF
orAstNode]. | 6269 * <b>Note:</b> This method needs to be kept in sync with [ScopeBuilder.scopeF
orAstNode]. |
| 6271 * | 6270 * |
| 6272 * @param node the node being tested | 6271 * @param node the node being tested |
| 6273 * @return `true` if the given node can be resolved independently of any other
nodes | 6272 * @return `true` if the given node can be resolved independently of any other
nodes |
| 6274 */ | 6273 */ |
| 6275 bool _canBeResolved(AstNode node) => node is ClassDeclaration || node is Class
TypeAlias || node is CompilationUnit || node is ConstructorDeclaration || node i
s FunctionDeclaration || node is FunctionTypeAlias || node is MethodDeclaration; | 6274 bool _canBeResolved(AstNode node) => node is ClassDeclaration || node is Class
TypeAlias || node is CompilationUnit || node is ConstructorDeclaration || node i
s FunctionDeclaration || node is FunctionTypeAlias || node is MethodDeclaration; |
| 6276 | 6275 |
| 6277 /** | 6276 /** |
| 6278 * Return `true` if the portion of the element model defined by the given node
has changed. | 6277 * Return `true` if the portion of the element model defined by the given node
has changed. |
| 6279 * | 6278 * |
| 6280 * @param node the node defining the portion of the element model being tested | 6279 * @param node the node defining the portion of the element model being tested |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6462 if (parameterElement.parameterKind == parameterKind) { | 6461 if (parameterElement.parameterKind == parameterKind) { |
| 6463 parameterCount++; | 6462 parameterCount++; |
| 6464 } | 6463 } |
| 6465 } | 6464 } |
| 6466 return parameterCount; | 6465 return parameterCount; |
| 6467 } | 6466 } |
| 6468 | 6467 |
| 6469 /** | 6468 /** |
| 6470 * Given some [ExecutableElement] return the number of positional parameters. | 6469 * Given some [ExecutableElement] return the number of positional parameters. |
| 6471 * | 6470 * |
| 6472 * Note: by positional we mean [ParameterKind#REQUIRED] or [ParameterKind#POSI
TIONAL]. | 6471 * Note: by positional we mean [ParameterKind.REQUIRED] or [ParameterKind.POSI
TIONAL]. |
| 6473 */ | 6472 */ |
| 6474 static int _getNumOfPositionalParameters(ExecutableElement executableElement)
=> _getNumOfParameters(executableElement, ParameterKind.REQUIRED) + _getNumOfPar
ameters(executableElement, ParameterKind.POSITIONAL); | 6473 static int _getNumOfPositionalParameters(ExecutableElement executableElement)
=> _getNumOfParameters(executableElement, ParameterKind.REQUIRED) + _getNumOfPar
ameters(executableElement, ParameterKind.POSITIONAL); |
| 6475 | 6474 |
| 6476 /** | 6475 /** |
| 6477 * Given some [ExecutableElement] return the number of required parameters. | 6476 * Given some [ExecutableElement] return the number of required parameters. |
| 6478 */ | 6477 */ |
| 6479 static int _getNumOfRequiredParameters(ExecutableElement executableElement) =>
_getNumOfParameters(executableElement, ParameterKind.REQUIRED); | 6478 static int _getNumOfRequiredParameters(ExecutableElement executableElement) =>
_getNumOfParameters(executableElement, ParameterKind.REQUIRED); |
| 6480 | 6479 |
| 6481 /** | 6480 /** |
| 6482 * Given some [ExecutableElement] returns `true` if it is an abstract member o
f a | 6481 * Given some [ExecutableElement] returns `true` if it is an abstract member o
f a |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7038 List<PropertyAccessorElement> accessors = type.accessors; | 7037 List<PropertyAccessorElement> accessors = type.accessors; |
| 7039 for (PropertyAccessorElement accessor in accessors) { | 7038 for (PropertyAccessorElement accessor in accessors) { |
| 7040 if (accessor.isAccessibleIn(_library) && !accessor.isStatic && (doIncludeA
bstract || !accessor.isAbstract)) { | 7039 if (accessor.isAccessibleIn(_library) && !accessor.isStatic && (doIncludeA
bstract || !accessor.isAbstract)) { |
| 7041 map.put(accessor.name, accessor); | 7040 map.put(accessor.name, accessor); |
| 7042 } | 7041 } |
| 7043 } | 7042 } |
| 7044 } | 7043 } |
| 7045 | 7044 |
| 7046 /** | 7045 /** |
| 7047 * This method is used to report errors on when they are found computing inher
itance information. | 7046 * This method is used to report errors on when they are found computing inher
itance information. |
| 7048 * See [ErrorVerifier#checkForInconsistentMethodInheritance] to see where thes
e generated | 7047 * See [ErrorVerifier.checkForInconsistentMethodInheritance] to see where thes
e generated |
| 7049 * error codes are reported back into the analysis engine. | 7048 * error codes are reported back into the analysis engine. |
| 7050 * | 7049 * |
| 7051 * @param classElt the location of the source for which the exception occurred | 7050 * @param classElt the location of the source for which the exception occurred |
| 7052 * @param offset the offset of the location of the error | 7051 * @param offset the offset of the location of the error |
| 7053 * @param length the length of the location of the error | 7052 * @param length the length of the location of the error |
| 7054 * @param errorCode the error code to be associated with this error | 7053 * @param errorCode the error code to be associated with this error |
| 7055 * @param arguments the arguments used to build the error message | 7054 * @param arguments the arguments used to build the error message |
| 7056 */ | 7055 */ |
| 7057 void _reportError(ClassElement classElt, int offset, int length, ErrorCode err
orCode, List<Object> arguments) { | 7056 void _reportError(ClassElement classElt, int offset, int length, ErrorCode err
orCode, List<Object> arguments) { |
| 7058 HashSet<AnalysisError> errorSet = _errorsInClassElement[classElt]; | 7057 HashSet<AnalysisError> errorSet = _errorsInClassElement[classElt]; |
| (...skipping 3134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10193 } | 10192 } |
| 10194 | 10193 |
| 10195 /** | 10194 /** |
| 10196 * This verifies that the passed file import directive is not contained in a s
ource inside a | 10195 * This verifies that the passed file import directive is not contained in a s
ource inside a |
| 10197 * package "lib" directory hierarchy referencing a source outside that package
"lib" directory | 10196 * package "lib" directory hierarchy referencing a source outside that package
"lib" directory |
| 10198 * hierarchy. | 10197 * hierarchy. |
| 10199 * | 10198 * |
| 10200 * @param uriLiteral the import URL (not `null`) | 10199 * @param uriLiteral the import URL (not `null`) |
| 10201 * @param path the file path being verified (not `null`) | 10200 * @param path the file path being verified (not `null`) |
| 10202 * @return `true` if and only if an error code is generated on the passed node | 10201 * @return `true` if and only if an error code is generated on the passed node |
| 10203 * @see PubSuggestionCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE | 10202 * See [PubSuggestionCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE]. |
| 10204 */ | 10203 */ |
| 10205 bool _checkForFileImportInsideLibReferencesFileOutside(StringLiteral uriLitera
l, String path) { | 10204 bool _checkForFileImportInsideLibReferencesFileOutside(StringLiteral uriLitera
l, String path) { |
| 10206 Source source = _getSource(uriLiteral); | 10205 Source source = _getSource(uriLiteral); |
| 10207 String fullName = _getSourceFullName(source); | 10206 String fullName = _getSourceFullName(source); |
| 10208 if (fullName != null) { | 10207 if (fullName != null) { |
| 10209 int pathIndex = 0; | 10208 int pathIndex = 0; |
| 10210 int fullNameIndex = fullName.length; | 10209 int fullNameIndex = fullName.length; |
| 10211 while (pathIndex < path.length && StringUtilities.startsWith3(path, pathIn
dex, 0x2E, 0x2E, 0x2F)) { | 10210 while (pathIndex < path.length && StringUtilities.startsWith3(path, pathIn
dex, 0x2E, 0x2E, 0x2F)) { |
| 10212 fullNameIndex = JavaString.lastIndexOf(fullName, '/', fullNameIndex); | 10211 fullNameIndex = JavaString.lastIndexOf(fullName, '/', fullNameIndex); |
| 10213 if (fullNameIndex < 4) { | 10212 if (fullNameIndex < 4) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 10230 } | 10229 } |
| 10231 | 10230 |
| 10232 /** | 10231 /** |
| 10233 * This verifies that the passed file import directive is not contained in a s
ource outside a | 10232 * This verifies that the passed file import directive is not contained in a s
ource outside a |
| 10234 * package "lib" directory hierarchy referencing a source inside that package
"lib" directory | 10233 * package "lib" directory hierarchy referencing a source inside that package
"lib" directory |
| 10235 * hierarchy. | 10234 * hierarchy. |
| 10236 * | 10235 * |
| 10237 * @param uriLiteral the import URL (not `null`) | 10236 * @param uriLiteral the import URL (not `null`) |
| 10238 * @param path the file path being verified (not `null`) | 10237 * @param path the file path being verified (not `null`) |
| 10239 * @return `true` if and only if an error code is generated on the passed node | 10238 * @return `true` if and only if an error code is generated on the passed node |
| 10240 * @see PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE | 10239 * See [PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE]. |
| 10241 */ | 10240 */ |
| 10242 bool _checkForFileImportOutsideLibReferencesFileInside(StringLiteral uriLitera
l, String path) { | 10241 bool _checkForFileImportOutsideLibReferencesFileInside(StringLiteral uriLitera
l, String path) { |
| 10243 if (StringUtilities.startsWith4(path, 0, 0x6C, 0x69, 0x62, 0x2F)) { | 10242 if (StringUtilities.startsWith4(path, 0, 0x6C, 0x69, 0x62, 0x2F)) { |
| 10244 if (_checkForFileImportOutsideLibReferencesFileInsideAtIndex(uriLiteral, p
ath, 0)) { | 10243 if (_checkForFileImportOutsideLibReferencesFileInsideAtIndex(uriLiteral, p
ath, 0)) { |
| 10245 return true; | 10244 return true; |
| 10246 } | 10245 } |
| 10247 } | 10246 } |
| 10248 int pathIndex = StringUtilities.indexOf5(path, 0, 0x2F, 0x6C, 0x69, 0x62, 0x
2F); | 10247 int pathIndex = StringUtilities.indexOf5(path, 0, 0x2F, 0x6C, 0x69, 0x62, 0x
2F); |
| 10249 while (pathIndex != -1) { | 10248 while (pathIndex != -1) { |
| 10250 if (_checkForFileImportOutsideLibReferencesFileInsideAtIndex(uriLiteral, p
ath, pathIndex + 1)) { | 10249 if (_checkForFileImportOutsideLibReferencesFileInsideAtIndex(uriLiteral, p
ath, pathIndex + 1)) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 10273 } | 10272 } |
| 10274 return false; | 10273 return false; |
| 10275 } | 10274 } |
| 10276 | 10275 |
| 10277 /** | 10276 /** |
| 10278 * This verifies that the passed package import directive does not contain "..
" | 10277 * This verifies that the passed package import directive does not contain "..
" |
| 10279 * | 10278 * |
| 10280 * @param uriLiteral the import URL (not `null`) | 10279 * @param uriLiteral the import URL (not `null`) |
| 10281 * @param path the path to be validated (not `null`) | 10280 * @param path the path to be validated (not `null`) |
| 10282 * @return `true` if and only if an error code is generated on the passed node | 10281 * @return `true` if and only if an error code is generated on the passed node |
| 10283 * @see PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT | 10282 * See [PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT]. |
| 10284 */ | 10283 */ |
| 10285 bool _checkForPackageImportContainsDotDot(StringLiteral uriLiteral, String pat
h) { | 10284 bool _checkForPackageImportContainsDotDot(StringLiteral uriLiteral, String pat
h) { |
| 10286 if (StringUtilities.startsWith3(path, 0, 0x2E, 0x2E, 0x2F) || StringUtilitie
s.indexOf4(path, 0, 0x2F, 0x2E, 0x2E, 0x2F) >= 0) { | 10285 if (StringUtilities.startsWith3(path, 0, 0x2E, 0x2E, 0x2F) || StringUtilitie
s.indexOf4(path, 0, 0x2F, 0x2E, 0x2E, 0x2F) >= 0) { |
| 10287 // Package import should not to contain ".." | 10286 // Package import should not to contain ".." |
| 10288 _errorReporter.reportErrorForNode(HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
, uriLiteral, []); | 10287 _errorReporter.reportErrorForNode(HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
, uriLiteral, []); |
| 10289 return true; | 10288 return true; |
| 10290 } | 10289 } |
| 10291 return false; | 10290 return false; |
| 10292 } | 10291 } |
| 10293 | 10292 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 10304 CompilationUnitElement element = unit.element; | 10303 CompilationUnitElement element = unit.element; |
| 10305 if (element != null) { | 10304 if (element != null) { |
| 10306 source = element.source; | 10305 source = element.source; |
| 10307 } | 10306 } |
| 10308 } | 10307 } |
| 10309 return source; | 10308 return source; |
| 10310 } | 10309 } |
| 10311 | 10310 |
| 10312 /** | 10311 /** |
| 10313 * Answer the full name of the given source. The returned value will have all | 10312 * Answer the full name of the given source. The returned value will have all |
| 10314 * [File#separatorChar] replace by '/'. | 10313 * [File.separatorChar] replace by '/'. |
| 10315 * | 10314 * |
| 10316 * @param source the source | 10315 * @param source the source |
| 10317 * @return the full name or `null` if it could not be determined | 10316 * @return the full name or `null` if it could not be determined |
| 10318 */ | 10317 */ |
| 10319 String _getSourceFullName(Source source) { | 10318 String _getSourceFullName(Source source) { |
| 10320 if (source != null) { | 10319 if (source != null) { |
| 10321 String fullName = source.fullName; | 10320 String fullName = source.fullName; |
| 10322 if (fullName != null) { | 10321 if (fullName != null) { |
| 10323 return fullName.replaceAll(r'\', '/'); | 10322 return fullName.replaceAll(r'\', '/'); |
| 10324 } | 10323 } |
| (...skipping 2052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12377 * given listener. | 12376 * given listener. |
| 12378 * | 12377 * |
| 12379 * @param errorListener the listener to which analysis errors will be reported | 12378 * @param errorListener the listener to which analysis errors will be reported |
| 12380 */ | 12379 */ |
| 12381 ScopeBuilder(this._errorListener); | 12380 ScopeBuilder(this._errorListener); |
| 12382 | 12381 |
| 12383 /** | 12382 /** |
| 12384 * Return the scope in which the given AST structure should be resolved. | 12383 * Return the scope in which the given AST structure should be resolved. |
| 12385 * | 12384 * |
| 12386 * <b>Note:</b> This method needs to be kept in sync with | 12385 * <b>Note:</b> This method needs to be kept in sync with |
| 12387 * [IncrementalResolver#canBeResolved]. | 12386 * [IncrementalResolver.canBeResolved]. |
| 12388 * | 12387 * |
| 12389 * @param node the root of the AST structure to be resolved | 12388 * @param node the root of the AST structure to be resolved |
| 12390 * @return the scope in which the given AST structure should be resolved | 12389 * @return the scope in which the given AST structure should be resolved |
| 12391 * @throws AnalysisException if the AST structure has not been resolved or is
not part of a | 12390 * @throws AnalysisException if the AST structure has not been resolved or is
not part of a |
| 12392 * [CompilationUnit] | 12391 * [CompilationUnit] |
| 12393 */ | 12392 */ |
| 12394 Scope _scopeForAstNode(AstNode node) { | 12393 Scope _scopeForAstNode(AstNode node) { |
| 12395 if (node is CompilationUnit) { | 12394 if (node is CompilationUnit) { |
| 12396 return _scopeForCompilationUnit(node); | 12395 return _scopeForCompilationUnit(node); |
| 12397 } | 12396 } |
| (...skipping 3139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15537 /** | 15536 /** |
| 15538 * Return the tag that has the given identifier, or {@code null} if there is n
o such tag (the | 15537 * Return the tag that has the given identifier, or {@code null} if there is n
o such tag (the |
| 15539 * identifier is not defined). | 15538 * identifier is not defined). |
| 15540 * | 15539 * |
| 15541 * @return the tag that has the given identifier | 15540 * @return the tag that has the given identifier |
| 15542 */ | 15541 */ |
| 15543 String getTagWithId(String identifier) { | 15542 String getTagWithId(String identifier) { |
| 15544 return idToTagMap[identifier]; | 15543 return idToTagMap[identifier]; |
| 15545 } | 15544 } |
| 15546 } | 15545 } |
| OLD | NEW |