Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 2031053002: Extend @protected to include implemented interfaces. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/hint_code_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 analyzer.src.generated.resolver; 5 library analyzer.src.generated.resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 node.getAncestor((AstNode node) => node is MethodDeclaration); 693 node.getAncestor((AstNode node) => node is MethodDeclaration);
694 if (decl == null) { 694 if (decl == null) {
695 _errorReporter.reportErrorForNode( 695 _errorReporter.reportErrorForNode(
696 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, 696 HintCode.INVALID_USE_OF_PROTECTED_MEMBER,
697 node, 697 node,
698 [node.methodName.toString(), definingClass.name]); 698 [node.methodName.toString(), definingClass.name]);
699 return; 699 return;
700 } 700 }
701 701
702 ClassElement invokingClass = decl.element?.enclosingElement; 702 ClassElement invokingClass = decl.element?.enclosingElement;
703 if (invokingClass != null) { 703 if (!_hasSuperType(invokingClass, definingClass.type)) {
704 if (!_hasSuperClassOrMixin(invokingClass, definingClass.type)) { 704 _errorReporter.reportErrorForNode(
705 _errorReporter.reportErrorForNode( 705 HintCode.INVALID_USE_OF_PROTECTED_MEMBER,
706 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, 706 node,
707 node, 707 [node.methodName.toString(), definingClass.name]);
708 [node.methodName.toString(), definingClass.name]);
709 }
710 } 708 }
711 } 709 }
712 710
713 /** 711 /**
714 * Produces a hint if the given identifier is a protected field or getter 712 * Produces a hint if the given identifier is a protected field or getter
715 * accessed outside a subclass. 713 * accessed outside a subclass.
716 */ 714 */
717 void _checkForInvalidProtectedPropertyAccess(SimpleIdentifier identifier) { 715 void _checkForInvalidProtectedPropertyAccess(SimpleIdentifier identifier) {
718 if (identifier.inDeclarationContext()) { 716 if (identifier.inDeclarationContext()) {
719 return; 717 return;
720 } 718 }
721 Element element = identifier.bestElement; 719 Element element = identifier.bestElement;
722 if (element is PropertyAccessorElement && 720 if (element is PropertyAccessorElement &&
723 element.enclosingElement is ClassElement && 721 element.enclosingElement is ClassElement &&
724 (element.isProtected || element.variable.isProtected)) { 722 (element.isProtected || element.variable.isProtected)) {
725 ClassElement definingClass = element.enclosingElement; 723 ClassElement definingClass = element.enclosingElement;
726 ClassDeclaration accessingClass = 724 ClassDeclaration accessingClass =
727 identifier.getAncestor((AstNode node) => node is ClassDeclaration); 725 identifier.getAncestor((AstNode node) => node is ClassDeclaration);
728 726
729 if (accessingClass == null) { 727 if (accessingClass == null) {
730 _errorReporter.reportErrorForNode( 728 _errorReporter.reportErrorForNode(
731 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, 729 HintCode.INVALID_USE_OF_PROTECTED_MEMBER,
732 identifier, 730 identifier,
733 [identifier.name.toString(), definingClass.name]); 731 [identifier.name.toString(), definingClass.name]);
734 } else if (!_hasSuperClassOrMixin( 732 } else if (!_hasSuperType(accessingClass.element, definingClass.type)) {
735 accessingClass.element, definingClass.type)) {
736 _errorReporter.reportErrorForNode( 733 _errorReporter.reportErrorForNode(
737 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, 734 HintCode.INVALID_USE_OF_PROTECTED_MEMBER,
738 identifier, 735 identifier,
739 [identifier.name.toString(), definingClass.name]); 736 [identifier.name.toString(), definingClass.name]);
740 } 737 }
741 } 738 }
742 } 739 }
743 740
744 /** 741 /**
745 * Check that the imported library does not define a loadLibrary function. The import has already 742 * Check that the imported library does not define a loadLibrary function. The import has already
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 _errorReporter.reportErrorForNode( 952 _errorReporter.reportErrorForNode(
956 HintCode.UNNECESSARY_NO_SUCH_METHOD, node); 953 HintCode.UNNECESSARY_NO_SUCH_METHOD, node);
957 return true; 954 return true;
958 } 955 }
959 } 956 }
960 } 957 }
961 return false; 958 return false;
962 } 959 }
963 960
964 /** 961 /**
962 * Check for situations where the result of a method or function is used, when
963 * it returns 'void'.
964 *
965 * See [HintCode.USE_OF_VOID_RESULT].
966 */
967 void _checkForUseOfVoidResult(Expression expression) {
968 // TODO(jwren) Many other situations of use could be covered. We currently
969 // cover the cases var x = m() and x = m(), but we could also cover cases
970 // such as m().x, m()[k], a + m(), f(m()), return m().
971 if (expression is MethodInvocation) {
972 if (identical(expression.staticType, VoidTypeImpl.instance)) {
973 SimpleIdentifier methodName = expression.methodName;
974 _errorReporter.reportErrorForNode(
975 HintCode.USE_OF_VOID_RESULT, methodName, [methodName.name]);
976 }
977 }
978 }
979
980 /**
965 * Check for the passed class declaration for the 981 * Check for the passed class declaration for the
966 * [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code. 982 * [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code.
967 * 983 *
968 * @param node the class declaration to check 984 * @param node the class declaration to check
969 * @return `true` if and only if a hint code is generated on the passed node 985 * @return `true` if and only if a hint code is generated on the passed node
970 * See [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]. 986 * See [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE].
971 */ 987 */
972 // bool _checkForOverrideEqualsButNotHashCode(ClassDeclaration node) { 988 // bool _checkForOverrideEqualsButNotHashCode(ClassDeclaration node) {
973 // ClassElement classElement = node.element; 989 // ClassElement classElement = node.element;
974 // if (classElement == null) { 990 // if (classElement == null) {
975 // return false; 991 // return false;
976 // } 992 // }
977 // MethodElement equalsOperatorMethodElement = 993 // MethodElement equalsOperatorMethodElement =
978 // classElement.getMethod(sc.TokenType.EQ_EQ.lexeme); 994 // classElement.getMethod(sc.TokenType.EQ_EQ.lexeme);
979 // if (equalsOperatorMethodElement != null) { 995 // if (equalsOperatorMethodElement != null) {
980 // PropertyAccessorElement hashCodeElement = 996 // PropertyAccessorElement hashCodeElement =
981 // classElement.getGetter(_HASHCODE_GETTER_NAME); 997 // classElement.getGetter(_HASHCODE_GETTER_NAME);
982 // if (hashCodeElement == null) { 998 // if (hashCodeElement == null) {
983 // _errorReporter.reportErrorForNode( 999 // _errorReporter.reportErrorForNode(
984 // HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE, 1000 // HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE,
985 // node.name, 1001 // node.name,
986 // [classElement.displayName]); 1002 // [classElement.displayName]);
987 // return true; 1003 // return true;
988 // } 1004 // }
989 // } 1005 // }
990 // return false; 1006 // return false;
991 // } 1007 // }
992 1008
993 /**
994 * Check for situations where the result of a method or function is used, when
995 * it returns 'void'.
996 *
997 * See [HintCode.USE_OF_VOID_RESULT].
998 */
999 void _checkForUseOfVoidResult(Expression expression) {
1000 // TODO(jwren) Many other situations of use could be covered. We currently
1001 // cover the cases var x = m() and x = m(), but we could also cover cases
1002 // such as m().x, m()[k], a + m(), f(m()), return m().
1003 if (expression is MethodInvocation) {
1004 if (identical(expression.staticType, VoidTypeImpl.instance)) {
1005 SimpleIdentifier methodName = expression.methodName;
1006 _errorReporter.reportErrorForNode(
1007 HintCode.USE_OF_VOID_RESULT, methodName, [methodName.name]);
1008 }
1009 }
1010 }
1011
1012 bool _hasSuperClassOrMixin(ClassElement element, InterfaceType type) { 1009 bool _hasSuperClassOrMixin(ClassElement element, InterfaceType type) {
1013 List<ClassElement> seenClasses = <ClassElement>[]; 1010 List<ClassElement> seenClasses = <ClassElement>[];
1014 while (element != null && !seenClasses.contains(element)) { 1011 while (element != null && !seenClasses.contains(element)) {
1015 if (element.type == type) { 1012 if (element.type == type) {
1016 return true; 1013 return true;
1017 } 1014 }
1018 1015
1019 if (element.mixins.any((InterfaceType t) => t == type)) { 1016 if (element.mixins.any((InterfaceType t) => t == type)) {
1020 return true; 1017 return true;
1021 } 1018 }
1022 1019
1023 seenClasses.add(element); 1020 seenClasses.add(element);
1024 element = element.supertype?.element; 1021 element = element.supertype?.element;
1025 } 1022 }
1026 1023
1027 return false; 1024 return false;
1028 } 1025 }
1029 1026
1027 bool _hasSuperType(ClassElement element, InterfaceType type) =>
1028 element != null && element.allSupertypes.contains(type);
1029
1030 /** 1030 /**
1031 * Given a parenthesized expression, this returns the parent (or recursively g rand-parent) of the 1031 * Given a parenthesized expression, this returns the parent (or recursively g rand-parent) of the
1032 * expression that is a parenthesized expression, but whose parent is not a pa renthesized 1032 * expression that is a parenthesized expression, but whose parent is not a pa renthesized
1033 * expression. 1033 * expression.
1034 * 1034 *
1035 * For example given the code `(((e)))`: `(e) -> (((e)))`. 1035 * For example given the code `(((e)))`: `(e) -> (((e)))`.
1036 * 1036 *
1037 * @param parenthesizedExpression some expression whose parent is a parenthesi zed expression 1037 * @param parenthesizedExpression some expression whose parent is a parenthesi zed expression
1038 * @return the first parent or grand-parent that is a parenthesized expression , that does not have 1038 * @return the first parent or grand-parent that is a parenthesized expression , that does not have
1039 * a parenthesized expression parent 1039 * a parenthesized expression parent
(...skipping 9938 matching lines...) Expand 10 before | Expand all | Expand 10 after
10978 return null; 10978 return null;
10979 } 10979 }
10980 if (identical(node.staticElement, variable)) { 10980 if (identical(node.staticElement, variable)) {
10981 if (node.inSetterContext()) { 10981 if (node.inSetterContext()) {
10982 result = true; 10982 result = true;
10983 } 10983 }
10984 } 10984 }
10985 return null; 10985 return null;
10986 } 10986 }
10987 } 10987 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/hint_code_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698