| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be | 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
| 6 // refactored to fit into analyzer. | 6 // refactored to fit into analyzer. |
| 7 library analyzer.src.task.strong.checker; | 7 library analyzer.src.task.strong.checker; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| 11 import 'package:analyzer/dart/ast/token.dart' show TokenType; | 11 import 'package:analyzer/dart/ast/token.dart' show TokenType; |
| 12 import 'package:analyzer/dart/ast/token.dart'; | 12 import 'package:analyzer/dart/ast/token.dart'; |
| 13 import 'package:analyzer/dart/ast/visitor.dart'; | 13 import 'package:analyzer/dart/ast/visitor.dart'; |
| 14 import 'package:analyzer/dart/element/element.dart'; | 14 import 'package:analyzer/dart/element/element.dart'; |
| 15 import 'package:analyzer/dart/element/type.dart'; | 15 import 'package:analyzer/dart/element/type.dart'; |
| 16 import 'package:analyzer/src/dart/element/element.dart'; |
| 16 import 'package:analyzer/src/dart/element/type.dart'; | 17 import 'package:analyzer/src/dart/element/type.dart'; |
| 17 import 'package:analyzer/src/error/codes.dart' show StrongModeCode; | 18 import 'package:analyzer/src/error/codes.dart' show StrongModeCode; |
| 18 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; | 19 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; |
| 19 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 20 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| 20 import 'package:analyzer/src/generated/type_system.dart'; | 21 import 'package:analyzer/src/generated/type_system.dart'; |
| 21 | 22 |
| 22 import 'ast_properties.dart'; | 23 import 'ast_properties.dart'; |
| 23 | 24 |
| 24 /// Given an [expression] and a corresponding [typeSystem] and [typeProvider], | 25 /// Given an [expression] and a corresponding [typeSystem] and [typeProvider], |
| 25 /// gets the known static type of the expression. | 26 /// gets the known static type of the expression. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 } else if (expression is PropertyAccess) { | 68 } else if (expression is PropertyAccess) { |
| 68 return expression.propertyName.staticElement; | 69 return expression.propertyName.staticElement; |
| 69 } else if (expression is Identifier) { | 70 } else if (expression is Identifier) { |
| 70 return expression.staticElement; | 71 return expression.staticElement; |
| 71 } | 72 } |
| 72 return null; | 73 return null; |
| 73 } | 74 } |
| 74 | 75 |
| 75 /// Return the field on type corresponding to member, or null if none | 76 /// Return the field on type corresponding to member, or null if none |
| 76 /// exists or the "field" is actually a getter/setter. | 77 /// exists or the "field" is actually a getter/setter. |
| 77 PropertyInducingElement _getMemberField( | 78 FieldElement _getMemberField( |
| 78 InterfaceType type, PropertyAccessorElement member) { | 79 InterfaceType type, PropertyAccessorElement member) { |
| 79 String memberName = member.name; | 80 String memberName = member.name; |
| 80 PropertyInducingElement field; | 81 FieldElement field; |
| 81 if (member.isGetter) { | 82 if (member.isGetter) { |
| 82 // The subclass member is an explicit getter or a field | 83 // The subclass member is an explicit getter or a field |
| 83 // - lookup the getter on the superclass. | 84 // - lookup the getter on the superclass. |
| 84 var getter = type.getGetter(memberName); | 85 var getter = type.getGetter(memberName); |
| 85 if (getter == null || getter.isStatic) return null; | 86 if (getter == null || getter.isStatic) return null; |
| 86 field = getter.variable; | 87 field = getter.variable; |
| 87 } else if (!member.isSynthetic) { | 88 } else if (!member.isSynthetic) { |
| 88 // The subclass member is an explicit setter | 89 // The subclass member is an explicit setter |
| 89 // - lookup the setter on the superclass. | 90 // - lookup the setter on the superclass. |
| 90 // Note: an implicit (synthetic) setter would have already been flagged on | 91 // Note: an implicit (synthetic) setter would have already been flagged on |
| (...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 AstNode node, AstNode errorLocation, bool isSubclass) { | 1382 AstNode node, AstNode errorLocation, bool isSubclass) { |
| 1382 assert(!element.isStatic); | 1383 assert(!element.isStatic); |
| 1383 | 1384 |
| 1384 FunctionType subType = _elementType(element); | 1385 FunctionType subType = _elementType(element); |
| 1385 // TODO(vsm): Test for generic | 1386 // TODO(vsm): Test for generic |
| 1386 FunctionType baseType = _getMemberType(type, element); | 1387 FunctionType baseType = _getMemberType(type, element); |
| 1387 if (baseType == null) return false; | 1388 if (baseType == null) return false; |
| 1388 | 1389 |
| 1389 if (isSubclass && element is PropertyAccessorElement) { | 1390 if (isSubclass && element is PropertyAccessorElement) { |
| 1390 // Disallow any overriding if the base class defines this member | 1391 // Disallow any overriding if the base class defines this member |
| 1391 // as a field. We effectively treat fields as final / non-virtual. | 1392 // as a field. We effectively treat fields as final / non-virtual, |
| 1392 PropertyInducingElement field = _getMemberField(type, element); | 1393 // unless they are explicitly marked as @virtual |
| 1393 if (field != null) { | 1394 var field = _getMemberField(type, element); |
| 1395 if (field != null && !field.isVirtual) { |
| 1394 _checker._recordMessage( | 1396 _checker._recordMessage( |
| 1395 errorLocation, StrongModeCode.INVALID_FIELD_OVERRIDE, [ | 1397 errorLocation, StrongModeCode.INVALID_FIELD_OVERRIDE, [ |
| 1396 element.enclosingElement.name, | 1398 element.enclosingElement.name, |
| 1397 element.name, | 1399 element.name, |
| 1398 subType, | 1400 subType, |
| 1399 type, | 1401 type, |
| 1400 baseType | 1402 baseType |
| 1401 ]); | 1403 ]); |
| 1402 } | 1404 } |
| 1403 } | 1405 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1463 var visited = new Set<InterfaceType>(); | 1465 var visited = new Set<InterfaceType>(); |
| 1464 do { | 1466 do { |
| 1465 visited.add(current); | 1467 visited.add(current); |
| 1466 current.mixins.reversed.forEach( | 1468 current.mixins.reversed.forEach( |
| 1467 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1469 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); |
| 1468 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1470 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); |
| 1469 current = current.superclass; | 1471 current = current.superclass; |
| 1470 } while (!current.isObject && !visited.contains(current)); | 1472 } while (!current.isObject && !visited.contains(current)); |
| 1471 } | 1473 } |
| 1472 } | 1474 } |
| OLD | NEW |