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 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 * formal, and finally, initialized in the initializers list. | 166 * formal, and finally, initialized in the initializers list. |
167 */ | 167 */ |
168 private enum INIT_STATE { | 168 private enum INIT_STATE { |
169 NOT_INIT, | 169 NOT_INIT, |
170 INIT_IN_DECLARATION, | 170 INIT_IN_DECLARATION, |
171 INIT_IN_FIELD_FORMAL, | 171 INIT_IN_FIELD_FORMAL, |
172 INIT_IN_INITIALIZERS | 172 INIT_IN_INITIALIZERS |
173 } | 173 } |
174 | 174 |
175 /** | 175 /** |
176 * Checks if the given expression is the reference to the type. | |
177 * | |
178 * @param expr the expression to evaluate | |
179 * @return {@code true} if the given expression is the reference to the type | |
180 */ | |
181 private static boolean isTypeReference(Expression expr) { | |
182 if (expr instanceof Identifier) { | |
183 Identifier identifier = (Identifier) expr; | |
184 return identifier.getStaticElement() instanceof ClassElement; | |
185 } | |
186 return false; | |
187 } | |
188 | |
189 /** | |
190 * The error reporter by which errors will be reported. | 176 * The error reporter by which errors will be reported. |
191 */ | 177 */ |
192 private ErrorReporter errorReporter; | 178 private ErrorReporter errorReporter; |
193 | 179 |
194 /** | 180 /** |
195 * The current library that is being analyzed. | 181 * The current library that is being analyzed. |
196 */ | 182 */ |
197 private LibraryElement currentLibrary; | 183 private LibraryElement currentLibrary; |
198 | 184 |
199 /** | 185 /** |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 } finally { | 807 } finally { |
822 enclosingFunction = previousFunction; | 808 enclosingFunction = previousFunction; |
823 isInStaticMethod = false; | 809 isInStaticMethod = false; |
824 } | 810 } |
825 } | 811 } |
826 | 812 |
827 @Override | 813 @Override |
828 public Void visitMethodInvocation(MethodInvocation node) { | 814 public Void visitMethodInvocation(MethodInvocation node) { |
829 Expression target = node.getRealTarget(); | 815 Expression target = node.getRealTarget(); |
830 SimpleIdentifier methodName = node.getMethodName(); | 816 SimpleIdentifier methodName = node.getMethodName(); |
831 checkForStaticAccessToInstanceMember(target, methodName); | 817 if (target != null) { |
832 checkForInstanceAccessToStaticMember(target, methodName); | 818 ClassElement typeReference = ElementResolver.getTypeReference(target); |
833 if (target == null) { | 819 checkForStaticAccessToInstanceMember(typeReference, methodName); |
| 820 checkForInstanceAccessToStaticMember(typeReference, methodName); |
| 821 } else { |
834 checkForUnqualifiedReferenceToNonLocalStaticMember(methodName); | 822 checkForUnqualifiedReferenceToNonLocalStaticMember(methodName); |
835 } | 823 } |
836 return super.visitMethodInvocation(node); | 824 return super.visitMethodInvocation(node); |
837 } | 825 } |
838 | 826 |
839 @Override | 827 @Override |
840 public Void visitNativeClause(NativeClause node) { | 828 public Void visitNativeClause(NativeClause node) { |
841 // TODO(brianwilkerson) Figure out the right rule for when 'native' is allow
ed. | 829 // TODO(brianwilkerson) Figure out the right rule for when 'native' is allow
ed. |
842 if (!isInSystemLibrary) { | 830 if (!isInSystemLibrary) { |
843 errorReporter.reportError(ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, n
ode); | 831 errorReporter.reportError(ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, n
ode); |
(...skipping 10 matching lines...) Expand all Loading... |
854 @Override | 842 @Override |
855 public Void visitPostfixExpression(PostfixExpression node) { | 843 public Void visitPostfixExpression(PostfixExpression node) { |
856 checkForAssignmentToFinal(node.getOperand()); | 844 checkForAssignmentToFinal(node.getOperand()); |
857 checkForIntNotAssignable(node.getOperand()); | 845 checkForIntNotAssignable(node.getOperand()); |
858 return super.visitPostfixExpression(node); | 846 return super.visitPostfixExpression(node); |
859 } | 847 } |
860 | 848 |
861 @Override | 849 @Override |
862 public Void visitPrefixedIdentifier(PrefixedIdentifier node) { | 850 public Void visitPrefixedIdentifier(PrefixedIdentifier node) { |
863 if (!(node.getParent() instanceof Annotation)) { | 851 if (!(node.getParent() instanceof Annotation)) { |
864 checkForStaticAccessToInstanceMember(node.getPrefix(), node.getIdentifier(
)); | 852 ClassElement typeReference = ElementResolver.getTypeReference(node.getPref
ix()); |
865 checkForInstanceAccessToStaticMember(node.getPrefix(), node.getIdentifier(
)); | 853 SimpleIdentifier name = node.getIdentifier(); |
| 854 checkForStaticAccessToInstanceMember(typeReference, name); |
| 855 checkForInstanceAccessToStaticMember(typeReference, name); |
866 } | 856 } |
867 return super.visitPrefixedIdentifier(node); | 857 return super.visitPrefixedIdentifier(node); |
868 } | 858 } |
869 | 859 |
870 @Override | 860 @Override |
871 public Void visitPrefixExpression(PrefixExpression node) { | 861 public Void visitPrefixExpression(PrefixExpression node) { |
872 TokenType operatorType = node.getOperator().getType(); | 862 TokenType operatorType = node.getOperator().getType(); |
873 Expression operand = node.getOperand(); | 863 Expression operand = node.getOperand(); |
874 if (operatorType == TokenType.BANG) { | 864 if (operatorType == TokenType.BANG) { |
875 checkForNonBoolNegationExpression(operand); | 865 checkForNonBoolNegationExpression(operand); |
876 } else if (operatorType.isIncrementOperator()) { | 866 } else if (operatorType.isIncrementOperator()) { |
877 checkForAssignmentToFinal(operand); | 867 checkForAssignmentToFinal(operand); |
878 } | 868 } |
879 checkForIntNotAssignable(operand); | 869 checkForIntNotAssignable(operand); |
880 return super.visitPrefixExpression(node); | 870 return super.visitPrefixExpression(node); |
881 } | 871 } |
882 | 872 |
883 @Override | 873 @Override |
884 public Void visitPropertyAccess(PropertyAccess node) { | 874 public Void visitPropertyAccess(PropertyAccess node) { |
885 Expression target = node.getRealTarget(); | 875 ClassElement typeReference = ElementResolver.getTypeReference(node.getRealTa
rget()); |
886 SimpleIdentifier propertyName = node.getPropertyName(); | 876 SimpleIdentifier propertyName = node.getPropertyName(); |
887 checkForStaticAccessToInstanceMember(target, propertyName); | 877 checkForStaticAccessToInstanceMember(typeReference, propertyName); |
888 checkForInstanceAccessToStaticMember(target, propertyName); | 878 checkForInstanceAccessToStaticMember(typeReference, propertyName); |
889 return super.visitPropertyAccess(node); | 879 return super.visitPropertyAccess(node); |
890 } | 880 } |
891 | 881 |
892 @Override | 882 @Override |
893 public Void visitRedirectingConstructorInvocation(RedirectingConstructorInvoca
tion node) { | 883 public Void visitRedirectingConstructorInvocation(RedirectingConstructorInvoca
tion node) { |
894 isInConstructorInitializer = true; | 884 isInConstructorInitializer = true; |
895 try { | 885 try { |
896 return super.visitRedirectingConstructorInvocation(node); | 886 return super.visitRedirectingConstructorInvocation(node); |
897 } finally { | 887 } finally { |
898 isInConstructorInitializer = false; | 888 isInConstructorInitializer = false; |
(...skipping 2418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3317 if (errors == null || errors.isEmpty()) { | 3307 if (errors == null || errors.isEmpty()) { |
3318 return false; | 3308 return false; |
3319 } | 3309 } |
3320 for (AnalysisError error : errors) { | 3310 for (AnalysisError error : errors) { |
3321 errorReporter.reportError(error); | 3311 errorReporter.reportError(error); |
3322 } | 3312 } |
3323 return true; | 3313 return true; |
3324 } | 3314 } |
3325 | 3315 |
3326 /** | 3316 /** |
3327 * This checks that if the given "target" is not a type reference then the "na
me" is reference to | 3317 * This checks the given "typeReference" is not a type reference and that then
the "name" is |
3328 * an instance member. | 3318 * reference to an instance member. |
3329 * | 3319 * |
3330 * @param target the target of the name access to evaluate | 3320 * @param typeReference the resolved {@link ClassElement} of the left hand sid
e of the expression, |
| 3321 * or {@code null}, aka, the class element of 'C' in 'C.x', see |
| 3322 * {@link #getTypeReference(Expression)} |
3331 * @param name the accessed name to evaluate | 3323 * @param name the accessed name to evaluate |
3332 * @return {@code true} if and only if an error code is generated on the passe
d node | 3324 * @return {@code true} if and only if an error code is generated on the passe
d node |
3333 * @see StaticTypeWarningCode#INSTANCE_ACCESS_TO_STATIC_MEMBER | 3325 * @see StaticTypeWarningCode#INSTANCE_ACCESS_TO_STATIC_MEMBER |
3334 */ | 3326 */ |
3335 private boolean checkForInstanceAccessToStaticMember(Expression target, Simple
Identifier name) { | 3327 private boolean checkForInstanceAccessToStaticMember(ClassElement typeReferenc
e, |
3336 // OK, no target | 3328 SimpleIdentifier name) { |
3337 if (target == null) { | 3329 // OK, in comment |
| 3330 if (isInComment) { |
3338 return false; | 3331 return false; |
3339 } | 3332 } |
3340 // OK, in comment | 3333 // OK, target is a type |
3341 if (isInComment) { | 3334 if (typeReference != null) { |
3342 return false; | 3335 return false; |
3343 } | 3336 } |
3344 // prepare member Element | 3337 // prepare member Element |
3345 Element element = name.getStaticElement(); | 3338 Element element = name.getStaticElement(); |
3346 if (!(element instanceof ExecutableElement)) { | 3339 if (!(element instanceof ExecutableElement)) { |
3347 return false; | 3340 return false; |
3348 } | 3341 } |
3349 ExecutableElement executableElement = (ExecutableElement) element; | 3342 ExecutableElement executableElement = (ExecutableElement) element; |
3350 // OK, top-level element | 3343 // OK, top-level element |
3351 if (!(executableElement.getEnclosingElement() instanceof ClassElement)) { | 3344 if (!(executableElement.getEnclosingElement() instanceof ClassElement)) { |
3352 return false; | 3345 return false; |
3353 } | 3346 } |
3354 // OK, instance member | 3347 // OK, instance member |
3355 if (!executableElement.isStatic()) { | 3348 if (!executableElement.isStatic()) { |
3356 return false; | 3349 return false; |
3357 } | 3350 } |
3358 // OK, target is a type | |
3359 if (isTypeReference(target)) { | |
3360 return false; | |
3361 } | |
3362 // report problem | 3351 // report problem |
3363 errorReporter.reportError( | 3352 errorReporter.reportError( |
3364 StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, | 3353 StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, |
3365 name, | 3354 name, |
3366 name.getName()); | 3355 name.getName()); |
3367 return true; | 3356 return true; |
3368 } | 3357 } |
3369 | 3358 |
3370 /** | 3359 /** |
3371 * This verifies that an 'int' can be assigned to the parameter corresponding
to the given | 3360 * This verifies that an 'int' can be assigned to the parameter corresponding
to the given |
(...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4571 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, | 4560 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, |
4572 returnExpression, | 4561 returnExpression, |
4573 staticReturnType.getDisplayName(), | 4562 staticReturnType.getDisplayName(), |
4574 expectedReturnType.getDisplayName(), | 4563 expectedReturnType.getDisplayName(), |
4575 enclosingFunction.getDisplayName()); | 4564 enclosingFunction.getDisplayName()); |
4576 return true; | 4565 return true; |
4577 } | 4566 } |
4578 } | 4567 } |
4579 | 4568 |
4580 /** | 4569 /** |
4581 * This checks that if the given "target" is the type reference then the "name
" is not the | 4570 * This checks the given "typeReference" and that the "name" is not the refere
nce to an instance |
4582 * reference to a instance member. | 4571 * member. |
4583 * | 4572 * |
4584 * @param target the target of the name access to evaluate | 4573 * @param typeReference the resolved {@link ClassElement} of the left hand sid
e of the expression, |
| 4574 * or {@code null}, aka, the class element of 'C' in 'C.x', see |
| 4575 * {@link #getTypeReference(Expression)} |
4585 * @param name the accessed name to evaluate | 4576 * @param name the accessed name to evaluate |
4586 * @return {@code true} if and only if an error code is generated on the passe
d node | 4577 * @return {@code true} if and only if an error code is generated on the passe
d node |
4587 * @see StaticWarningCode#STATIC_ACCESS_TO_INSTANCE_MEMBER | 4578 * @see StaticWarningCode#STATIC_ACCESS_TO_INSTANCE_MEMBER |
4588 */ | 4579 */ |
4589 private boolean checkForStaticAccessToInstanceMember(Expression target, Simple
Identifier name) { | 4580 private boolean checkForStaticAccessToInstanceMember(ClassElement typeReferenc
e, |
| 4581 SimpleIdentifier name) { |
| 4582 // OK, target is not a type |
| 4583 if (typeReference == null) { |
| 4584 return false; |
| 4585 } |
4590 // prepare member Element | 4586 // prepare member Element |
4591 Element element = name.getStaticElement(); | 4587 Element element = name.getStaticElement(); |
4592 if (!(element instanceof ExecutableElement)) { | 4588 if (!(element instanceof ExecutableElement)) { |
4593 return false; | 4589 return false; |
4594 } | 4590 } |
4595 ExecutableElement memberElement = (ExecutableElement) element; | 4591 ExecutableElement memberElement = (ExecutableElement) element; |
4596 // OK, static | 4592 // OK, static |
4597 if (memberElement.isStatic()) { | 4593 if (memberElement.isStatic()) { |
4598 return false; | 4594 return false; |
4599 } | 4595 } |
4600 // OK, target is not a type | |
4601 if (!isTypeReference(target)) { | |
4602 return false; | |
4603 } | |
4604 // report problem | 4596 // report problem |
4605 errorReporter.reportError( | 4597 errorReporter.reportError( |
4606 StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, | 4598 StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, |
4607 name, | 4599 name, |
4608 name.getName()); | 4600 name.getName()); |
4609 return true; | 4601 return true; |
4610 } | 4602 } |
4611 | 4603 |
4612 /** | 4604 /** |
4613 * This checks that the type of the passed 'switch' expression is assignable t
o the type of the | 4605 * This checks that the type of the passed 'switch' expression is assignable t
o the type of the |
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5407 if (superClassElt != null) { | 5399 if (superClassElt != null) { |
5408 return memberHasConcreteMethodImplementationInSuperclassChain( | 5400 return memberHasConcreteMethodImplementationInSuperclassChain( |
5409 superClassElt, | 5401 superClassElt, |
5410 methodName, | 5402 methodName, |
5411 superclassChain); | 5403 superclassChain); |
5412 } | 5404 } |
5413 } | 5405 } |
5414 return false; | 5406 return false; |
5415 } | 5407 } |
5416 } | 5408 } |
OLD | NEW |