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 |