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 analyzer.src.generated.error_verifier; | 5 library analyzer.src.generated.error_verifier; |
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 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 4971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4982 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR], and | 4982 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR], and |
4983 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS]. | 4983 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS]. |
4984 */ | 4984 */ |
4985 void _checkForNonAbstractClassInheritsAbstractMember( | 4985 void _checkForNonAbstractClassInheritsAbstractMember( |
4986 SimpleIdentifier classNameNode) { | 4986 SimpleIdentifier classNameNode) { |
4987 if (_enclosingClass.isAbstract) { | 4987 if (_enclosingClass.isAbstract) { |
4988 return; | 4988 return; |
4989 } else if (_enclosingClass.hasNoSuchMethod) { | 4989 } else if (_enclosingClass.hasNoSuchMethod) { |
4990 return; | 4990 return; |
4991 } | 4991 } |
4992 // | |
4993 // Store in local sets the set of all method and accessor names | |
4994 // | |
4995 HashSet<ExecutableElement> missingOverrides = | |
4996 new HashSet<ExecutableElement>(); | |
4997 // | |
4998 // Loop through the set of all executable elements declared in the implicit | |
4999 // interface. | |
5000 // | |
5001 Map<String, ExecutableElement> membersInheritedFromInterfaces = | |
5002 _inheritanceManager.getMembersInheritedFromInterfaces(_enclosingClass); | |
5003 Map<String, ExecutableElement> membersInheritedFromSuperclasses = | |
5004 _inheritanceManager.getMembersInheritedFromClasses(_enclosingClass); | |
5005 for (String memberName in membersInheritedFromInterfaces.keys) { | |
5006 ExecutableElement executableElt = | |
5007 membersInheritedFromInterfaces[memberName]; | |
5008 if (memberName == null) { | |
5009 break; | |
5010 } | |
5011 // If the element is not synthetic and can be determined to be defined in | |
5012 // Object, skip it. | |
5013 if (executableElt.enclosingElement != null && | |
5014 (executableElt.enclosingElement as ClassElement).type.isObject) { | |
5015 continue; | |
5016 } | |
5017 // Check to see if some element is in local enclosing class that matches | |
5018 // the name of the required member. | |
5019 if (_isMemberInClassOrMixin(executableElt, _enclosingClass)) { | |
5020 // We do not have to verify that this implementation of the found method | |
5021 // matches the required function type: the set of | |
5022 // StaticWarningCode.INVALID_METHOD_OVERRIDE_* warnings break out the | |
5023 // different specific situations. | |
5024 continue; | |
5025 } | |
5026 // First check to see if this element was declared in the superclass | |
5027 // chain, in which case there is already a concrete implementation. | |
5028 ExecutableElement elt = membersInheritedFromSuperclasses[memberName]; | |
5029 // Check to see if an element was found in the superclass chain with the | |
5030 // correct name. | |
5031 if (elt != null) { | |
5032 // Reference the types, if any are null then continue. | |
5033 InterfaceType enclosingType = _enclosingClass.type; | |
5034 FunctionType concreteType = elt.type; | |
5035 FunctionType requiredMemberType = executableElt.type; | |
5036 if (enclosingType == null || | |
5037 concreteType == null || | |
5038 requiredMemberType == null) { | |
5039 continue; | |
5040 } | |
5041 // Some element was found in the superclass chain that matches the name | |
5042 // of the required member. | |
5043 // If it is not abstract and it is the correct one (types match- the | |
5044 // version of this method that we have has the correct number of | |
5045 // parameters, etc), then this class has a valid implementation of this | |
5046 // method, so skip it. | |
5047 if ((elt is MethodElement && !elt.isAbstract) || | |
5048 (elt is PropertyAccessorElement && !elt.isAbstract)) { | |
5049 // Since we are comparing two function types, we need to do the | |
5050 // appropriate type substitutions first (). | |
5051 FunctionType foundConcreteFT = _inheritanceManager | |
5052 .substituteTypeArgumentsInMemberFromInheritance( | |
5053 concreteType, memberName, enclosingType); | |
5054 FunctionType requiredMemberFT = _inheritanceManager | |
5055 .substituteTypeArgumentsInMemberFromInheritance( | |
5056 requiredMemberType, memberName, enclosingType); | |
5057 foundConcreteFT = _typeSystem.functionTypeToConcreteType( | |
5058 _typeProvider, foundConcreteFT); | |
5059 requiredMemberFT = _typeSystem.functionTypeToConcreteType( | |
5060 _typeProvider, requiredMemberFT); | |
5061 | 4992 |
5062 // Strong mode does override checking for types in CodeChecker, so | 4993 Set<ExecutableElement> missingOverrides = computeMissingOverrides( |
5063 // we can skip it here. Doing it here leads to unnecessary duplicate | 4994 _options.strongMode, |
5064 // error messages in subclasses that inherit from one that has an | 4995 _typeProvider, |
5065 // override error. | 4996 _typeSystem, |
5066 // | 4997 _inheritanceManager, |
5067 // See: https://github.com/dart-lang/sdk/issues/25232 | 4998 _enclosingClass); |
5068 if (_options.strongMode || | 4999 if (missingOverrides.isEmpty) { |
5069 _typeSystem.isSubtypeOf(foundConcreteFT, requiredMemberFT)) { | |
5070 continue; | |
5071 } | |
5072 } | |
5073 } | |
5074 // The not qualifying concrete executable element was found, add it to the | |
5075 // list. | |
5076 missingOverrides.add(executableElt); | |
5077 } | |
5078 // Now that we have the set of missing overrides, generate a warning on this | |
5079 // class. | |
5080 int missingOverridesSize = missingOverrides.length; | |
5081 if (missingOverridesSize == 0) { | |
5082 return; | 5000 return; |
5083 } | 5001 } |
5084 List<ExecutableElement> missingOverridesArray = | 5002 |
5085 new List.from(missingOverrides); | 5003 List<String> missingOverrideNames = <String>[]; |
5086 List<String> stringMembersArrayListSet = new List<String>(); | 5004 for (ExecutableElement element in missingOverrides) { |
5087 for (int i = 0; i < missingOverridesArray.length; i++) { | |
5088 String newStrMember; | |
5089 ExecutableElement element = missingOverridesArray[i]; | |
5090 Element enclosingElement = element.enclosingElement; | 5005 Element enclosingElement = element.enclosingElement; |
5091 String prefix = StringUtilities.EMPTY; | 5006 String prefix = StringUtilities.EMPTY; |
5092 if (element is PropertyAccessorElement) { | 5007 if (element is PropertyAccessorElement) { |
5093 if (element.isGetter) { | 5008 if (element.isGetter) { |
5094 prefix = _GETTER_SPACE; | 5009 prefix = _GETTER_SPACE; |
5095 // "getter " | 5010 // "getter " |
5096 } else { | 5011 } else { |
5097 prefix = _SETTER_SPACE; | 5012 prefix = _SETTER_SPACE; |
5098 // "setter " | 5013 // "setter " |
5099 } | 5014 } |
5100 } | 5015 } |
| 5016 String newStrMember; |
5101 if (enclosingElement != null) { | 5017 if (enclosingElement != null) { |
5102 newStrMember = | 5018 newStrMember = |
5103 "$prefix'${enclosingElement.displayName}.${element.displayName}'"; | 5019 "$prefix'${enclosingElement.displayName}.${element.displayName}'"; |
5104 } else { | 5020 } else { |
5105 newStrMember = "$prefix'${element.displayName}'"; | 5021 newStrMember = "$prefix'${element.displayName}'"; |
5106 } | 5022 } |
5107 stringMembersArrayListSet.add(newStrMember); | 5023 missingOverrideNames.add(newStrMember); |
5108 } | 5024 } |
5109 List<String> stringMembersArray = new List.from(stringMembersArrayListSet); | 5025 missingOverrideNames.sort(); |
5110 stringMembersArray.sort(); | 5026 |
5111 AnalysisErrorWithProperties analysisError; | 5027 if (missingOverrideNames.length == 1) { |
5112 if (stringMembersArray.length == 1) { | 5028 _errorReporter.reportErrorForNode( |
5113 analysisError = _errorReporter.newErrorWithProperties( | |
5114 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE, | 5029 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE, |
5115 classNameNode, | 5030 classNameNode, |
5116 [stringMembersArray[0]]); | 5031 [missingOverrideNames[0]]); |
5117 } else if (stringMembersArray.length == 2) { | 5032 } else if (missingOverrideNames.length == 2) { |
5118 analysisError = _errorReporter.newErrorWithProperties( | 5033 _errorReporter.reportErrorForNode( |
5119 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO, | 5034 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO, |
5120 classNameNode, | 5035 classNameNode, |
5121 [stringMembersArray[0], stringMembersArray[1]]); | 5036 [missingOverrideNames[0], missingOverrideNames[1]]); |
5122 } else if (stringMembersArray.length == 3) { | 5037 } else if (missingOverrideNames.length == 3) { |
5123 analysisError = _errorReporter.newErrorWithProperties( | 5038 _errorReporter.reportErrorForNode( |
5124 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE, | 5039 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE, |
5125 classNameNode, [ | 5040 classNameNode, [ |
5126 stringMembersArray[0], | 5041 missingOverrideNames[0], |
5127 stringMembersArray[1], | 5042 missingOverrideNames[1], |
5128 stringMembersArray[2] | 5043 missingOverrideNames[2] |
5129 ]); | 5044 ]); |
5130 } else if (stringMembersArray.length == 4) { | 5045 } else if (missingOverrideNames.length == 4) { |
5131 analysisError = _errorReporter.newErrorWithProperties( | 5046 _errorReporter.reportErrorForNode( |
5132 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR, | 5047 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR, |
5133 classNameNode, [ | 5048 classNameNode, [ |
5134 stringMembersArray[0], | 5049 missingOverrideNames[0], |
5135 stringMembersArray[1], | 5050 missingOverrideNames[1], |
5136 stringMembersArray[2], | 5051 missingOverrideNames[2], |
5137 stringMembersArray[3] | 5052 missingOverrideNames[3] |
5138 ]); | 5053 ]); |
5139 } else { | 5054 } else { |
5140 analysisError = _errorReporter.newErrorWithProperties( | 5055 _errorReporter.reportErrorForNode( |
5141 StaticWarningCode | 5056 StaticWarningCode |
5142 .NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS, | 5057 .NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS, |
5143 classNameNode, | 5058 classNameNode, |
5144 [ | 5059 [ |
5145 stringMembersArray[0], | 5060 missingOverrideNames[0], |
5146 stringMembersArray[1], | 5061 missingOverrideNames[1], |
5147 stringMembersArray[2], | 5062 missingOverrideNames[2], |
5148 stringMembersArray[3], | 5063 missingOverrideNames[3], |
5149 stringMembersArray.length - 4 | 5064 missingOverrideNames.length - 4 |
5150 ]); | 5065 ]); |
5151 } | 5066 } |
5152 analysisError.setProperty( | |
5153 ErrorProperty.UNIMPLEMENTED_METHODS, missingOverridesArray); | |
5154 _errorReporter.reportError(analysisError); | |
5155 } | 5067 } |
5156 | 5068 |
5157 /** | 5069 /** |
5158 * Check to ensure that the [condition] is of type bool, are. Otherwise an | 5070 * Check to ensure that the [condition] is of type bool, are. Otherwise an |
5159 * error is reported on the expression. | 5071 * error is reported on the expression. |
5160 * | 5072 * |
5161 * See [StaticTypeWarningCode.NON_BOOL_CONDITION]. | 5073 * See [StaticTypeWarningCode.NON_BOOL_CONDITION]. |
5162 */ | 5074 */ |
5163 void _checkForNonBoolCondition(Expression condition) { | 5075 void _checkForNonBoolCondition(Expression condition) { |
5164 DartType conditionType = getStaticType(condition); | 5076 DartType conditionType = getStaticType(condition); |
(...skipping 1365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6530 return true; | 6442 return true; |
6531 } else if (type is InterfaceType) { | 6443 } else if (type is InterfaceType) { |
6532 MethodElement callMethod = | 6444 MethodElement callMethod = |
6533 type.lookUpMethod(FunctionElement.CALL_METHOD_NAME, _currentLibrary); | 6445 type.lookUpMethod(FunctionElement.CALL_METHOD_NAME, _currentLibrary); |
6534 return callMethod != null; | 6446 return callMethod != null; |
6535 } | 6447 } |
6536 return false; | 6448 return false; |
6537 } | 6449 } |
6538 | 6450 |
6539 /** | 6451 /** |
6540 * Return `true` iff the given [classElement] has a concrete method, getter or | |
6541 * setter that matches the name of the given [executableElement] in either the | |
6542 * class itself, or one of its' mixins. | |
6543 * | |
6544 * By "match", only the name of the member is tested to match, it does not | |
6545 * have to equal or be a subtype of the given executable element, this is due | |
6546 * to the specific use where this method is used in | |
6547 * [_checkForNonAbstractClassInheritsAbstractMember]. | |
6548 */ | |
6549 bool _isMemberInClassOrMixin( | |
6550 ExecutableElement executableElement, ClassElement classElement) { | |
6551 ExecutableElement foundElt = null; | |
6552 String executableName = executableElement.name; | |
6553 if (executableElement is MethodElement) { | |
6554 foundElt = classElement.getMethod(executableName); | |
6555 if (foundElt != null && !foundElt.isAbstract) { | |
6556 return true; | |
6557 } | |
6558 List<InterfaceType> mixins = classElement.mixins; | |
6559 for (int i = 0; i < mixins.length && foundElt == null; i++) { | |
6560 foundElt = mixins[i].getMethod(executableName); | |
6561 } | |
6562 if (foundElt != null && !foundElt.isAbstract) { | |
6563 return true; | |
6564 } | |
6565 } else if (executableElement is PropertyAccessorElement) { | |
6566 if (executableElement.isGetter) { | |
6567 foundElt = classElement.getGetter(executableName); | |
6568 } | |
6569 if (foundElt == null && executableElement.isSetter) { | |
6570 foundElt = classElement.getSetter(executableName); | |
6571 } | |
6572 if (foundElt != null && | |
6573 !(foundElt as PropertyAccessorElement).isAbstract) { | |
6574 return true; | |
6575 } | |
6576 List<InterfaceType> mixins = classElement.mixins; | |
6577 for (int i = 0; i < mixins.length && foundElt == null; i++) { | |
6578 foundElt = mixins[i].getGetter(executableName); | |
6579 if (foundElt == null) { | |
6580 foundElt = mixins[i].getSetter(executableName); | |
6581 } | |
6582 } | |
6583 if (foundElt != null && !foundElt.isAbstract) { | |
6584 return true; | |
6585 } | |
6586 } | |
6587 return false; | |
6588 } | |
6589 | |
6590 /** | |
6591 * Return `true` if the given 'this' [expression] is in a valid context. | 6452 * Return `true` if the given 'this' [expression] is in a valid context. |
6592 */ | 6453 */ |
6593 bool _isThisInValidContext(ThisExpression expression) { | 6454 bool _isThisInValidContext(ThisExpression expression) { |
6594 for (AstNode node = expression.parent; node != null; node = node.parent) { | 6455 for (AstNode node = expression.parent; node != null; node = node.parent) { |
6595 if (node is CompilationUnit) { | 6456 if (node is CompilationUnit) { |
6596 return false; | 6457 return false; |
6597 } else if (node is ConstructorDeclaration) { | 6458 } else if (node is ConstructorDeclaration) { |
6598 return node.factoryKeyword == null; | 6459 return node.factoryKeyword == null; |
6599 } else if (node is ConstructorInitializer) { | 6460 } else if (node is ConstructorInitializer) { |
6600 return false; | 6461 return false; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6705 for (InterfaceType mixinType in mixinTypes) { | 6566 for (InterfaceType mixinType in mixinTypes) { |
6706 if (_safeCheckForRecursiveInterfaceInheritance(mixinType.element, path)) { | 6567 if (_safeCheckForRecursiveInterfaceInheritance(mixinType.element, path)) { |
6707 return true; | 6568 return true; |
6708 } | 6569 } |
6709 } | 6570 } |
6710 path.removeAt(path.length - 1); | 6571 path.removeAt(path.length - 1); |
6711 return false; | 6572 return false; |
6712 } | 6573 } |
6713 | 6574 |
6714 /** | 6575 /** |
| 6576 * Returns [ExecutableElement]s that are declared in interfaces implemented |
| 6577 * by the [classElement], but not implemented by the [classElement] or its |
| 6578 * superclasses. |
| 6579 */ |
| 6580 static Set<ExecutableElement> computeMissingOverrides( |
| 6581 bool strongMode, |
| 6582 TypeProvider typeProvider, |
| 6583 TypeSystem typeSystem, |
| 6584 InheritanceManager inheritanceManager, |
| 6585 ClassElement classElement) { |
| 6586 // |
| 6587 // Store in local sets the set of all method and accessor names |
| 6588 // |
| 6589 HashSet<ExecutableElement> missingOverrides = |
| 6590 new HashSet<ExecutableElement>(); |
| 6591 // |
| 6592 // Loop through the set of all executable elements declared in the implicit |
| 6593 // interface. |
| 6594 // |
| 6595 Map<String, ExecutableElement> membersInheritedFromInterfaces = |
| 6596 inheritanceManager.getMembersInheritedFromInterfaces(classElement); |
| 6597 Map<String, ExecutableElement> membersInheritedFromSuperclasses = |
| 6598 inheritanceManager.getMembersInheritedFromClasses(classElement); |
| 6599 for (String memberName in membersInheritedFromInterfaces.keys) { |
| 6600 ExecutableElement executableElt = |
| 6601 membersInheritedFromInterfaces[memberName]; |
| 6602 if (memberName == null) { |
| 6603 break; |
| 6604 } |
| 6605 // If the element is not synthetic and can be determined to be defined in |
| 6606 // Object, skip it. |
| 6607 if (executableElt.enclosingElement != null && |
| 6608 (executableElt.enclosingElement as ClassElement).type.isObject) { |
| 6609 continue; |
| 6610 } |
| 6611 // Check to see if some element is in local enclosing class that matches |
| 6612 // the name of the required member. |
| 6613 if (_isMemberInClassOrMixin(executableElt, classElement)) { |
| 6614 // We do not have to verify that this implementation of the found method |
| 6615 // matches the required function type: the set of |
| 6616 // StaticWarningCode.INVALID_METHOD_OVERRIDE_* warnings break out the |
| 6617 // different specific situations. |
| 6618 continue; |
| 6619 } |
| 6620 // First check to see if this element was declared in the superclass |
| 6621 // chain, in which case there is already a concrete implementation. |
| 6622 ExecutableElement elt = membersInheritedFromSuperclasses[memberName]; |
| 6623 // Check to see if an element was found in the superclass chain with the |
| 6624 // correct name. |
| 6625 if (elt != null) { |
| 6626 // Reference the types, if any are null then continue. |
| 6627 InterfaceType enclosingType = classElement.type; |
| 6628 FunctionType concreteType = elt.type; |
| 6629 FunctionType requiredMemberType = executableElt.type; |
| 6630 if (enclosingType == null || |
| 6631 concreteType == null || |
| 6632 requiredMemberType == null) { |
| 6633 continue; |
| 6634 } |
| 6635 // Some element was found in the superclass chain that matches the name |
| 6636 // of the required member. |
| 6637 // If it is not abstract and it is the correct one (types match- the |
| 6638 // version of this method that we have has the correct number of |
| 6639 // parameters, etc), then this class has a valid implementation of this |
| 6640 // method, so skip it. |
| 6641 if ((elt is MethodElement && !elt.isAbstract) || |
| 6642 (elt is PropertyAccessorElement && !elt.isAbstract)) { |
| 6643 // Since we are comparing two function types, we need to do the |
| 6644 // appropriate type substitutions first (). |
| 6645 FunctionType foundConcreteFT = |
| 6646 inheritanceManager.substituteTypeArgumentsInMemberFromInheritance( |
| 6647 concreteType, memberName, enclosingType); |
| 6648 FunctionType requiredMemberFT = |
| 6649 inheritanceManager.substituteTypeArgumentsInMemberFromInheritance( |
| 6650 requiredMemberType, memberName, enclosingType); |
| 6651 foundConcreteFT = typeSystem.functionTypeToConcreteType( |
| 6652 typeProvider, foundConcreteFT); |
| 6653 requiredMemberFT = typeSystem.functionTypeToConcreteType( |
| 6654 typeProvider, requiredMemberFT); |
| 6655 |
| 6656 // Strong mode does override checking for types in CodeChecker, so |
| 6657 // we can skip it here. Doing it here leads to unnecessary duplicate |
| 6658 // error messages in subclasses that inherit from one that has an |
| 6659 // override error. |
| 6660 // |
| 6661 // See: https://github.com/dart-lang/sdk/issues/25232 |
| 6662 if (strongMode || |
| 6663 typeSystem.isSubtypeOf(foundConcreteFT, requiredMemberFT)) { |
| 6664 continue; |
| 6665 } |
| 6666 } |
| 6667 } |
| 6668 // The not qualifying concrete executable element was found, add it to the |
| 6669 // list. |
| 6670 missingOverrides.add(executableElt); |
| 6671 } |
| 6672 return missingOverrides; |
| 6673 } |
| 6674 |
| 6675 /** |
6715 * Return the static type of the given [expression] that is to be used for | 6676 * Return the static type of the given [expression] that is to be used for |
6716 * type analysis. | 6677 * type analysis. |
6717 */ | 6678 */ |
6718 static DartType getStaticType(Expression expression) { | 6679 static DartType getStaticType(Expression expression) { |
6719 DartType type = expression.staticType; | 6680 DartType type = expression.staticType; |
6720 if (type == null) { | 6681 if (type == null) { |
6721 // TODO(brianwilkerson) This should never happen. | 6682 // TODO(brianwilkerson) This should never happen. |
6722 return DynamicTypeImpl.instance; | 6683 return DynamicTypeImpl.instance; |
6723 } | 6684 } |
6724 return type; | 6685 return type; |
6725 } | 6686 } |
6726 | 6687 |
6727 /** | 6688 /** |
6728 * Return the variable element represented by the given [expression], or | 6689 * Return the variable element represented by the given [expression], or |
6729 * `null` if there is no such element. | 6690 * `null` if there is no such element. |
6730 */ | 6691 */ |
6731 static VariableElement getVariableElement(Expression expression) { | 6692 static VariableElement getVariableElement(Expression expression) { |
6732 if (expression is Identifier) { | 6693 if (expression is Identifier) { |
6733 Element element = expression.staticElement; | 6694 Element element = expression.staticElement; |
6734 if (element is VariableElement) { | 6695 if (element is VariableElement) { |
6735 return element; | 6696 return element; |
6736 } | 6697 } |
6737 } | 6698 } |
6738 return null; | 6699 return null; |
6739 } | 6700 } |
| 6701 |
| 6702 /** |
| 6703 * Return `true` iff the given [classElement] has a concrete method, getter or |
| 6704 * setter that matches the name of the given [executableElement] in either the |
| 6705 * class itself, or one of its' mixins. |
| 6706 * |
| 6707 * By "match", only the name of the member is tested to match, it does not |
| 6708 * have to equal or be a subtype of the given executable element, this is due |
| 6709 * to the specific use where this method is used in |
| 6710 * [_checkForNonAbstractClassInheritsAbstractMember]. |
| 6711 */ |
| 6712 static bool _isMemberInClassOrMixin( |
| 6713 ExecutableElement executableElement, ClassElement classElement) { |
| 6714 ExecutableElement foundElt = null; |
| 6715 String executableName = executableElement.name; |
| 6716 if (executableElement is MethodElement) { |
| 6717 foundElt = classElement.getMethod(executableName); |
| 6718 if (foundElt != null && !foundElt.isAbstract) { |
| 6719 return true; |
| 6720 } |
| 6721 List<InterfaceType> mixins = classElement.mixins; |
| 6722 for (int i = 0; i < mixins.length && foundElt == null; i++) { |
| 6723 foundElt = mixins[i].getMethod(executableName); |
| 6724 } |
| 6725 if (foundElt != null && !foundElt.isAbstract) { |
| 6726 return true; |
| 6727 } |
| 6728 } else if (executableElement is PropertyAccessorElement) { |
| 6729 if (executableElement.isGetter) { |
| 6730 foundElt = classElement.getGetter(executableName); |
| 6731 } |
| 6732 if (foundElt == null && executableElement.isSetter) { |
| 6733 foundElt = classElement.getSetter(executableName); |
| 6734 } |
| 6735 if (foundElt != null && |
| 6736 !(foundElt as PropertyAccessorElement).isAbstract) { |
| 6737 return true; |
| 6738 } |
| 6739 List<InterfaceType> mixins = classElement.mixins; |
| 6740 for (int i = 0; i < mixins.length && foundElt == null; i++) { |
| 6741 foundElt = mixins[i].getGetter(executableName); |
| 6742 if (foundElt == null) { |
| 6743 foundElt = mixins[i].getSetter(executableName); |
| 6744 } |
| 6745 } |
| 6746 if (foundElt != null && !foundElt.isAbstract) { |
| 6747 return true; |
| 6748 } |
| 6749 } |
| 6750 return false; |
| 6751 } |
6740 } | 6752 } |
6741 | 6753 |
6742 class GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference | 6754 class GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference |
6743 extends GeneralizingElementVisitor<Object> { | 6755 extends GeneralizingElementVisitor<Object> { |
6744 List<Element> toCheck; | 6756 List<Element> toCheck; |
6745 | 6757 |
6746 GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference(this.toCheck) | 6758 GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference(this.toCheck) |
6747 : super(); | 6759 : super(); |
6748 | 6760 |
6749 @override | 6761 @override |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6960 class _InvocationCollector extends RecursiveAstVisitor { | 6972 class _InvocationCollector extends RecursiveAstVisitor { |
6961 final List<String> superCalls = <String>[]; | 6973 final List<String> superCalls = <String>[]; |
6962 | 6974 |
6963 @override | 6975 @override |
6964 visitMethodInvocation(MethodInvocation node) { | 6976 visitMethodInvocation(MethodInvocation node) { |
6965 if (node.target is SuperExpression) { | 6977 if (node.target is SuperExpression) { |
6966 superCalls.add(node.methodName.name); | 6978 superCalls.add(node.methodName.name); |
6967 } | 6979 } |
6968 } | 6980 } |
6969 } | 6981 } |
OLD | NEW |