OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013, the Dart project authors. | 2 * Copyright (c) 2013, the Dart project authors. |
3 * | 3 * |
4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except | 4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except |
5 * in compliance with the License. You may obtain a copy of the License at | 5 * in compliance with the License. You may obtain a copy of the License at |
6 * | 6 * |
7 * http://www.eclipse.org/legal/epl-v10.html | 7 * http://www.eclipse.org/legal/epl-v10.html |
8 * | 8 * |
9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License | 9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License |
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express | 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express |
11 * or implied. See the License for the specific language governing permissions a
nd limitations under | 11 * or implied. See the License for the specific language governing permissions a
nd limitations under |
12 * the License. | 12 * the License. |
13 */ | 13 */ |
14 package com.google.dart.engine.internal.hint; | 14 package com.google.dart.engine.internal.hint; |
15 | 15 |
| 16 import com.google.dart.engine.ast.ASTNode; |
16 import com.google.dart.engine.ast.AsExpression; | 17 import com.google.dart.engine.ast.AsExpression; |
| 18 import com.google.dart.engine.ast.AssignmentExpression; |
17 import com.google.dart.engine.ast.BinaryExpression; | 19 import com.google.dart.engine.ast.BinaryExpression; |
18 import com.google.dart.engine.ast.ClassDeclaration; | 20 import com.google.dart.engine.ast.ClassDeclaration; |
| 21 import com.google.dart.engine.ast.ConstructorName; |
| 22 import com.google.dart.engine.ast.ExportDirective; |
19 import com.google.dart.engine.ast.Expression; | 23 import com.google.dart.engine.ast.Expression; |
20 import com.google.dart.engine.ast.Identifier; | 24 import com.google.dart.engine.ast.Identifier; |
| 25 import com.google.dart.engine.ast.ImportDirective; |
| 26 import com.google.dart.engine.ast.IndexExpression; |
| 27 import com.google.dart.engine.ast.InstanceCreationExpression; |
21 import com.google.dart.engine.ast.IsExpression; | 28 import com.google.dart.engine.ast.IsExpression; |
22 import com.google.dart.engine.ast.MethodDeclaration; | 29 import com.google.dart.engine.ast.MethodDeclaration; |
23 import com.google.dart.engine.ast.MethodInvocation; | 30 import com.google.dart.engine.ast.MethodInvocation; |
24 import com.google.dart.engine.ast.NullLiteral; | 31 import com.google.dart.engine.ast.NullLiteral; |
25 import com.google.dart.engine.ast.ParenthesizedExpression; | 32 import com.google.dart.engine.ast.ParenthesizedExpression; |
| 33 import com.google.dart.engine.ast.PostfixExpression; |
| 34 import com.google.dart.engine.ast.PrefixExpression; |
| 35 import com.google.dart.engine.ast.RedirectingConstructorInvocation; |
| 36 import com.google.dart.engine.ast.SimpleIdentifier; |
| 37 import com.google.dart.engine.ast.SuperConstructorInvocation; |
26 import com.google.dart.engine.ast.TypeName; | 38 import com.google.dart.engine.ast.TypeName; |
27 import com.google.dart.engine.ast.visitor.RecursiveASTVisitor; | 39 import com.google.dart.engine.ast.visitor.RecursiveASTVisitor; |
28 import com.google.dart.engine.element.ClassElement; | 40 import com.google.dart.engine.element.ClassElement; |
| 41 import com.google.dart.engine.element.ConstructorElement; |
29 import com.google.dart.engine.element.Element; | 42 import com.google.dart.engine.element.Element; |
30 import com.google.dart.engine.element.ExecutableElement; | 43 import com.google.dart.engine.element.ExecutableElement; |
31 import com.google.dart.engine.element.LibraryElement; | 44 import com.google.dart.engine.element.LibraryElement; |
32 import com.google.dart.engine.element.MethodElement; | 45 import com.google.dart.engine.element.MethodElement; |
33 import com.google.dart.engine.element.PropertyAccessorElement; | 46 import com.google.dart.engine.element.PropertyAccessorElement; |
34 import com.google.dart.engine.error.HintCode; | 47 import com.google.dart.engine.error.HintCode; |
35 import com.google.dart.engine.internal.error.ErrorReporter; | 48 import com.google.dart.engine.internal.error.ErrorReporter; |
36 import com.google.dart.engine.scanner.Keyword; | 49 import com.google.dart.engine.scanner.Keyword; |
37 import com.google.dart.engine.scanner.TokenType; | 50 import com.google.dart.engine.scanner.TokenType; |
38 import com.google.dart.engine.type.InterfaceType; | 51 import com.google.dart.engine.type.InterfaceType; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 this.errorReporter = errorReporter; | 111 this.errorReporter = errorReporter; |
99 } | 112 } |
100 | 113 |
101 @Override | 114 @Override |
102 public Void visitAsExpression(AsExpression node) { | 115 public Void visitAsExpression(AsExpression node) { |
103 checkForUnnecessaryCast(node); | 116 checkForUnnecessaryCast(node); |
104 return super.visitAsExpression(node); | 117 return super.visitAsExpression(node); |
105 } | 118 } |
106 | 119 |
107 @Override | 120 @Override |
| 121 public Void visitAssignmentExpression(AssignmentExpression node) { |
| 122 TokenType operatorType = node.getOperator().getType(); |
| 123 if (operatorType != TokenType.EQ) { |
| 124 checkForDeprecatedMemberUse(node.getBestElement(), node); |
| 125 } |
| 126 return super.visitAssignmentExpression(node); |
| 127 } |
| 128 |
| 129 @Override |
108 public Void visitBinaryExpression(BinaryExpression node) { | 130 public Void visitBinaryExpression(BinaryExpression node) { |
109 checkForDivisionOptimizationHint(node); | 131 checkForDivisionOptimizationHint(node); |
| 132 checkForDeprecatedMemberUse(node.getBestElement(), node); |
110 return super.visitBinaryExpression(node); | 133 return super.visitBinaryExpression(node); |
111 } | 134 } |
112 | 135 |
113 @Override | 136 @Override |
114 public Void visitClassDeclaration(ClassDeclaration node) { | 137 public Void visitClassDeclaration(ClassDeclaration node) { |
115 ClassElement outerClass = enclosingClass; | 138 ClassElement outerClass = enclosingClass; |
116 try { | 139 try { |
117 enclosingClass = node.getElement(); | 140 enclosingClass = node.getElement(); |
118 // Commented out until we decide that we want this hint in the analyzer | 141 // Commented out until we decide that we want this hint in the analyzer |
119 // checkForOverrideEqualsButNotHashCode(node); | 142 // checkForOverrideEqualsButNotHashCode(node); |
120 return super.visitClassDeclaration(node); | 143 return super.visitClassDeclaration(node); |
121 } finally { | 144 } finally { |
122 enclosingClass = outerClass; | 145 enclosingClass = outerClass; |
123 } | 146 } |
124 } | 147 } |
125 | 148 |
126 @Override | 149 @Override |
| 150 public Void visitExportDirective(ExportDirective node) { |
| 151 checkForDeprecatedMemberUse(node.getUriElement(), node); |
| 152 return super.visitExportDirective(node); |
| 153 } |
| 154 |
| 155 @Override |
| 156 public Void visitImportDirective(ImportDirective node) { |
| 157 checkForDeprecatedMemberUse(node.getUriElement(), node); |
| 158 return super.visitImportDirective(node); |
| 159 } |
| 160 |
| 161 @Override |
| 162 public Void visitIndexExpression(IndexExpression node) { |
| 163 checkForDeprecatedMemberUse(node.getBestElement(), node); |
| 164 return super.visitIndexExpression(node); |
| 165 } |
| 166 |
| 167 @Override |
| 168 public Void visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 169 checkForDeprecatedMemberUse(node.getStaticElement(), node); |
| 170 return super.visitInstanceCreationExpression(node); |
| 171 } |
| 172 |
| 173 @Override |
127 public Void visitIsExpression(IsExpression node) { | 174 public Void visitIsExpression(IsExpression node) { |
128 checkAllTypeChecks(node); | 175 checkAllTypeChecks(node); |
129 return super.visitIsExpression(node); | 176 return super.visitIsExpression(node); |
130 } | 177 } |
131 | 178 |
132 @Override | 179 @Override |
133 public Void visitMethodDeclaration(MethodDeclaration node) { | 180 public Void visitMethodDeclaration(MethodDeclaration node) { |
134 // Commented out until we decide that we want this hint in the analyzer | |
135 checkForOverridingPrivateMember(node); | 181 checkForOverridingPrivateMember(node); |
136 return super.visitMethodDeclaration(node); | 182 return super.visitMethodDeclaration(node); |
137 } | 183 } |
138 | 184 |
| 185 @Override |
| 186 public Void visitPostfixExpression(PostfixExpression node) { |
| 187 checkForDeprecatedMemberUse(node.getBestElement(), node); |
| 188 return super.visitPostfixExpression(node); |
| 189 } |
| 190 |
| 191 @Override |
| 192 public Void visitPrefixExpression(PrefixExpression node) { |
| 193 checkForDeprecatedMemberUse(node.getBestElement(), node); |
| 194 return super.visitPrefixExpression(node); |
| 195 } |
| 196 |
| 197 @Override |
| 198 public Void visitRedirectingConstructorInvocation(RedirectingConstructorInvoca
tion node) { |
| 199 checkForDeprecatedMemberUse(node.getStaticElement(), node); |
| 200 return super.visitRedirectingConstructorInvocation(node); |
| 201 } |
| 202 |
| 203 @Override |
| 204 public Void visitSimpleIdentifier(SimpleIdentifier node) { |
| 205 checkForDeprecatedMemberUse(node); |
| 206 return super.visitSimpleIdentifier(node); |
| 207 } |
| 208 |
| 209 @Override |
| 210 public Void visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 211 checkForDeprecatedMemberUse(node.getStaticElement(), node); |
| 212 return super.visitSuperConstructorInvocation(node); |
| 213 } |
| 214 |
139 /** | 215 /** |
140 * Check for the passed is expression for the unnecessary type check hint code
s as well as null | 216 * Check for the passed is expression for the unnecessary type check hint code
s as well as null |
141 * checks expressed using an is expression. | 217 * checks expressed using an is expression. |
142 * | 218 * |
143 * @param node the is expression to check | 219 * @param node the is expression to check |
144 * @return {@code true} if and only if a hint code is generated on the passed
node | 220 * @return {@code true} if and only if a hint code is generated on the passed
node |
145 * @see HintCode#TYPE_CHECK_IS_NOT_NULL | 221 * @see HintCode#TYPE_CHECK_IS_NOT_NULL |
146 * @see HintCode#TYPE_CHECK_IS_NULL | 222 * @see HintCode#TYPE_CHECK_IS_NULL |
147 * @see HintCode#UNNECESSARY_TYPE_CHECK_TRUE | 223 * @see HintCode#UNNECESSARY_TYPE_CHECK_TRUE |
148 * @see HintCode#UNNECESSARY_TYPE_CHECK_FALSE | 224 * @see HintCode#UNNECESSARY_TYPE_CHECK_FALSE |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 // the is not case | 265 // the is not case |
190 errorReporter.reportError(HintCode.TYPE_CHECK_IS_NOT_NULL, node); | 266 errorReporter.reportError(HintCode.TYPE_CHECK_IS_NOT_NULL, node); |
191 } | 267 } |
192 return true; | 268 return true; |
193 } | 269 } |
194 } | 270 } |
195 return false; | 271 return false; |
196 } | 272 } |
197 | 273 |
198 /** | 274 /** |
| 275 * Given some {@link Element}, look at the associated metadata and report the
use of the member if |
| 276 * it is declared as deprecated. |
| 277 * |
| 278 * @param element some element to check for deprecated use of |
| 279 * @param node the node use for the location of the error |
| 280 * @return {@code true} if and only if a hint code is generated on the passed
node |
| 281 * @see HintCode#DEPRECATED_MEMBER_USE |
| 282 */ |
| 283 private boolean checkForDeprecatedMemberUse(Element element, ASTNode node) { |
| 284 if (element != null && element.isDeprecated()) { |
| 285 String displayName = element.getDisplayName(); |
| 286 if (element instanceof ConstructorElement) { |
| 287 // TODO(jwren) We should modify ConstructorElement.getDisplayName(), or
have the logic |
| 288 // centralized elsewhere, instead of doing this logic here. |
| 289 ConstructorElement constructorElement = (ConstructorElement) element; |
| 290 displayName = constructorElement.getEnclosingElement().getDisplayName(); |
| 291 if (!constructorElement.getDisplayName().isEmpty()) { |
| 292 displayName = displayName + '.' + constructorElement.getDisplayName(); |
| 293 } |
| 294 } |
| 295 errorReporter.reportError(HintCode.DEPRECATED_MEMBER_USE, node, displayNam
e); |
| 296 return true; |
| 297 } |
| 298 return false; |
| 299 } |
| 300 |
| 301 /** |
| 302 * For {@link SimpleIdentifier}s, only call {@link #checkForDeprecatedMemberUs
e(Element, ASTNode)} |
| 303 * if the node is not in a declaration context. |
| 304 * <p> |
| 305 * Also, if the identifier is a constructor name in a constructor invocation,
then calls to the |
| 306 * deprecated constructor will be caught by |
| 307 * {@link #visitInstanceCreationExpression(InstanceCreationExpression)} and |
| 308 * {@link #visitSuperConstructorInvocation(SuperConstructorInvocation)}, and c
an be ignored by |
| 309 * this visit method. |
| 310 * |
| 311 * @param identifier some simple identifier to check for deprecated use of |
| 312 * @return {@code true} if and only if a hint code is generated on the passed
node |
| 313 * @see HintCode#DEPRECATED_MEMBER_USE |
| 314 */ |
| 315 private boolean checkForDeprecatedMemberUse(SimpleIdentifier identifier) { |
| 316 if (identifier.inDeclarationContext() |
| 317 || (identifier.getParent() instanceof ConstructorName && identifier == (
(ConstructorName) identifier.getParent()).getName()) |
| 318 || (identifier.getParent() instanceof SuperConstructorInvocation && iden
tifier == ((SuperConstructorInvocation) identifier.getParent()).getConstructorNa
me())) { |
| 319 return false; |
| 320 } |
| 321 return checkForDeprecatedMemberUse(identifier.getBestElement(), identifier); |
| 322 } |
| 323 |
| 324 /** |
199 * Check for the passed binary expression for the {@link HintCode#DIVISION_OPT
IMIZATION}. | 325 * Check for the passed binary expression for the {@link HintCode#DIVISION_OPT
IMIZATION}. |
200 * | 326 * |
201 * @param node the binary expression to check | 327 * @param node the binary expression to check |
202 * @return {@code true} if and only if a hint code is generated on the passed
node | 328 * @return {@code true} if and only if a hint code is generated on the passed
node |
203 * @see HintCode#DIVISION_OPTIMIZATION | 329 * @see HintCode#DIVISION_OPTIMIZATION |
204 */ | 330 */ |
205 private boolean checkForDivisionOptimizationHint(BinaryExpression node) { | 331 private boolean checkForDivisionOptimizationHint(BinaryExpression node) { |
206 // Return if the operator is not '/' | 332 // Return if the operator is not '/' |
207 if (!node.getOperator().getType().equals(TokenType.SLASH)) { | 333 if (!node.getOperator().getType().equals(TokenType.SLASH)) { |
208 return false; | 334 return false; |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 // !(x instanceof TypeParameterType) checks. | 475 // !(x instanceof TypeParameterType) checks. |
350 if (lhsType != null && rhsType != null && !lhsType.isDynamic() && !rhsType.i
sDynamic() | 476 if (lhsType != null && rhsType != null && !lhsType.isDynamic() && !rhsType.i
sDynamic() |
351 && !(lhsType instanceof TypeParameterType) && !(rhsType instanceof TypeP
arameterType) | 477 && !(lhsType instanceof TypeParameterType) && !(rhsType instanceof TypeP
arameterType) |
352 && lhsType.isSubtypeOf(rhsType)) { | 478 && lhsType.isSubtypeOf(rhsType)) { |
353 errorReporter.reportError(HintCode.UNNECESSARY_CAST, node); | 479 errorReporter.reportError(HintCode.UNNECESSARY_CAST, node); |
354 return true; | 480 return true; |
355 } | 481 } |
356 return false; | 482 return false; |
357 } | 483 } |
358 } | 484 } |
OLD | NEW |