| 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 library dart2js.resolution.class_hierarchy; | 5 library dart2js.resolution.class_hierarchy; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/resolution.dart' show Resolution; | 8 import '../common/resolution.dart' show Resolution; |
| 9 import '../core_types.dart' show CommonElements; | 9 import '../core_types.dart' show CommonElements; |
| 10 import '../elements/resolution_types.dart'; | 10 import '../elements/resolution_types.dart'; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 import '../tree/tree.dart'; | 21 import '../tree/tree.dart'; |
| 22 import '../universe/call_structure.dart' show CallStructure; | 22 import '../universe/call_structure.dart' show CallStructure; |
| 23 import '../universe/feature.dart' show Feature; | 23 import '../universe/feature.dart' show Feature; |
| 24 import '../util/util.dart' show Link, Setlet; | 24 import '../util/util.dart' show Link, Setlet; |
| 25 import 'enum_creator.dart'; | 25 import 'enum_creator.dart'; |
| 26 import 'members.dart' show lookupInScope; | 26 import 'members.dart' show lookupInScope; |
| 27 import 'registry.dart' show ResolutionRegistry; | 27 import 'registry.dart' show ResolutionRegistry; |
| 28 import 'resolution_common.dart' show CommonResolverVisitor, MappingVisitor; | 28 import 'resolution_common.dart' show CommonResolverVisitor, MappingVisitor; |
| 29 import 'scope.dart' show Scope, TypeDeclarationScope; | 29 import 'scope.dart' show Scope, TypeDeclarationScope; |
| 30 | 30 |
| 31 class TypeDefinitionVisitor extends MappingVisitor<DartType> { | 31 class TypeDefinitionVisitor extends MappingVisitor<ResolutionDartType> { |
| 32 Scope scope; | 32 Scope scope; |
| 33 final TypeDeclarationElement enclosingElement; | 33 final TypeDeclarationElement enclosingElement; |
| 34 TypeDeclarationElement get element => enclosingElement; | 34 TypeDeclarationElement get element => enclosingElement; |
| 35 | 35 |
| 36 TypeDefinitionVisitor(Resolution resolution, TypeDeclarationElement element, | 36 TypeDefinitionVisitor(Resolution resolution, TypeDeclarationElement element, |
| 37 ResolutionRegistry registry) | 37 ResolutionRegistry registry) |
| 38 : this.enclosingElement = element, | 38 : this.enclosingElement = element, |
| 39 scope = Scope.buildEnclosingScope(element), | 39 scope = Scope.buildEnclosingScope(element), |
| 40 super(resolution, registry); | 40 super(resolution, registry); |
| 41 | 41 |
| 42 CommonElements get commonElements => resolution.commonElements; | 42 CommonElements get commonElements => resolution.commonElements; |
| 43 | 43 |
| 44 DartType get objectType => commonElements.objectType; | 44 ResolutionDartType get objectType => commonElements.objectType; |
| 45 | 45 |
| 46 void resolveTypeVariableBounds(NodeList node) { | 46 void resolveTypeVariableBounds(NodeList node) { |
| 47 if (node == null) return; | 47 if (node == null) return; |
| 48 | 48 |
| 49 Setlet<String> nameSet = new Setlet<String>(); | 49 Setlet<String> nameSet = new Setlet<String>(); |
| 50 // Resolve the bounds of type variables. | 50 // Resolve the bounds of type variables. |
| 51 Iterator<DartType> types = element.typeVariables.iterator; | 51 Iterator<ResolutionDartType> types = element.typeVariables.iterator; |
| 52 Link<Node> nodeLink = node.nodes; | 52 Link<Node> nodeLink = node.nodes; |
| 53 while (!nodeLink.isEmpty) { | 53 while (!nodeLink.isEmpty) { |
| 54 types.moveNext(); | 54 types.moveNext(); |
| 55 TypeVariableType typeVariable = types.current; | 55 ResolutionTypeVariableType typeVariable = types.current; |
| 56 String typeName = typeVariable.name; | 56 String typeName = typeVariable.name; |
| 57 TypeVariable typeNode = nodeLink.head; | 57 TypeVariable typeNode = nodeLink.head; |
| 58 registry.useType(typeNode, typeVariable); | 58 registry.useType(typeNode, typeVariable); |
| 59 if (nameSet.contains(typeName)) { | 59 if (nameSet.contains(typeName)) { |
| 60 reporter.reportErrorMessage( | 60 reporter.reportErrorMessage( |
| 61 typeNode, | 61 typeNode, |
| 62 MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, | 62 MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, |
| 63 {'typeVariableName': typeName}); | 63 {'typeVariableName': typeName}); |
| 64 } | 64 } |
| 65 nameSet.add(typeName); | 65 nameSet.add(typeName); |
| 66 | 66 |
| 67 TypeVariableElementX variableElement = typeVariable.element; | 67 TypeVariableElementX variableElement = typeVariable.element; |
| 68 if (typeNode.bound != null) { | 68 if (typeNode.bound != null) { |
| 69 DartType boundType = | 69 ResolutionDartType boundType = |
| 70 typeResolver.resolveTypeAnnotation(this, typeNode.bound); | 70 typeResolver.resolveTypeAnnotation(this, typeNode.bound); |
| 71 variableElement.boundCache = boundType; | 71 variableElement.boundCache = boundType; |
| 72 | 72 |
| 73 void checkTypeVariableBound() { | 73 void checkTypeVariableBound() { |
| 74 Link<TypeVariableElement> seenTypeVariables = | 74 Link<TypeVariableElement> seenTypeVariables = |
| 75 const Link<TypeVariableElement>(); | 75 const Link<TypeVariableElement>(); |
| 76 seenTypeVariables = seenTypeVariables.prepend(variableElement); | 76 seenTypeVariables = seenTypeVariables.prepend(variableElement); |
| 77 DartType bound = boundType; | 77 ResolutionDartType bound = boundType; |
| 78 while (bound.isTypeVariable) { | 78 while (bound.isTypeVariable) { |
| 79 TypeVariableElement element = bound.element; | 79 TypeVariableElement element = bound.element; |
| 80 if (seenTypeVariables.contains(element)) { | 80 if (seenTypeVariables.contains(element)) { |
| 81 if (identical(element, variableElement)) { | 81 if (identical(element, variableElement)) { |
| 82 // Only report an error on the checked type variable to avoid | 82 // Only report an error on the checked type variable to avoid |
| 83 // generating multiple errors for the same cyclicity. | 83 // generating multiple errors for the same cyclicity. |
| 84 reporter.reportWarningMessage( | 84 reporter.reportWarningMessage( |
| 85 typeNode.name, | 85 typeNode.name, |
| 86 MessageKind.CYCLIC_TYPE_VARIABLE, | 86 MessageKind.CYCLIC_TYPE_VARIABLE, |
| 87 {'typeVariableName': variableElement.name}); | 87 {'typeVariableName': variableElement.name}); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 115 * or indirectly (through [ClassElement.ensureResolved]) for any other | 115 * or indirectly (through [ClassElement.ensureResolved]) for any other |
| 116 * types. | 116 * types. |
| 117 */ | 117 */ |
| 118 class ClassResolverVisitor extends TypeDefinitionVisitor { | 118 class ClassResolverVisitor extends TypeDefinitionVisitor { |
| 119 BaseClassElementX get element => enclosingElement; | 119 BaseClassElementX get element => enclosingElement; |
| 120 | 120 |
| 121 ClassResolverVisitor(Resolution resolution, ClassElement classElement, | 121 ClassResolverVisitor(Resolution resolution, ClassElement classElement, |
| 122 ResolutionRegistry registry) | 122 ResolutionRegistry registry) |
| 123 : super(resolution, classElement, registry); | 123 : super(resolution, classElement, registry); |
| 124 | 124 |
| 125 DartType visitClassNode(ClassNode node) { | 125 ResolutionDartType visitClassNode(ClassNode node) { |
| 126 if (element == null) { | 126 if (element == null) { |
| 127 throw reporter.internalError(node, 'element is null'); | 127 throw reporter.internalError(node, 'element is null'); |
| 128 } | 128 } |
| 129 if (element.resolutionState != STATE_STARTED) { | 129 if (element.resolutionState != STATE_STARTED) { |
| 130 throw reporter.internalError( | 130 throw reporter.internalError( |
| 131 element, 'cyclic resolution of class $element'); | 131 element, 'cyclic resolution of class $element'); |
| 132 } | 132 } |
| 133 | 133 |
| 134 element.computeType(resolution); | 134 element.computeType(resolution); |
| 135 scope = new TypeDeclarationScope(scope, element); | 135 scope = new TypeDeclarationScope(scope, element); |
| 136 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. | 136 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. |
| 137 // As a side-effect, this may get us back here trying to | 137 // As a side-effect, this may get us back here trying to |
| 138 // resolve this class again. | 138 // resolve this class again. |
| 139 resolveTypeVariableBounds(node.typeParameters); | 139 resolveTypeVariableBounds(node.typeParameters); |
| 140 | 140 |
| 141 // Setup the supertype for the element (if there is a cycle in the | 141 // Setup the supertype for the element (if there is a cycle in the |
| 142 // class hierarchy, it has already been set to Object). | 142 // class hierarchy, it has already been set to Object). |
| 143 if (element.supertype == null && node.superclass != null) { | 143 if (element.supertype == null && node.superclass != null) { |
| 144 MixinApplication superMixin = node.superclass.asMixinApplication(); | 144 MixinApplication superMixin = node.superclass.asMixinApplication(); |
| 145 if (superMixin != null) { | 145 if (superMixin != null) { |
| 146 DartType supertype = resolveSupertype(element, superMixin.superclass); | 146 ResolutionDartType supertype = |
| 147 resolveSupertype(element, superMixin.superclass); |
| 147 Link<Node> link = superMixin.mixins.nodes; | 148 Link<Node> link = superMixin.mixins.nodes; |
| 148 while (!link.isEmpty) { | 149 while (!link.isEmpty) { |
| 149 supertype = | 150 supertype = |
| 150 applyMixin(supertype, checkMixinType(link.head), link.head); | 151 applyMixin(supertype, checkMixinType(link.head), link.head); |
| 151 link = link.tail; | 152 link = link.tail; |
| 152 } | 153 } |
| 153 element.supertype = supertype; | 154 element.supertype = supertype; |
| 154 } else { | 155 } else { |
| 155 element.supertype = resolveSupertype(element, node.superclass); | 156 element.supertype = resolveSupertype(element, node.superclass); |
| 156 } | 157 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 constructor, | 217 constructor, |
| 217 reporter.createMessage(node, erroneousElement.messageKind, | 218 reporter.createMessage(node, erroneousElement.messageKind, |
| 218 erroneousElement.messageArguments)); | 219 erroneousElement.messageArguments)); |
| 219 } | 220 } |
| 220 element.setDefaultConstructor(constructor, reporter); | 221 element.setDefaultConstructor(constructor, reporter); |
| 221 } | 222 } |
| 222 return element.computeType(resolution); | 223 return element.computeType(resolution); |
| 223 } | 224 } |
| 224 | 225 |
| 225 @override | 226 @override |
| 226 DartType visitEnum(Enum node) { | 227 ResolutionDartType visitEnum(Enum node) { |
| 227 if (element == null) { | 228 if (element == null) { |
| 228 throw reporter.internalError(node, 'element is null'); | 229 throw reporter.internalError(node, 'element is null'); |
| 229 } | 230 } |
| 230 if (element.resolutionState != STATE_STARTED) { | 231 if (element.resolutionState != STATE_STARTED) { |
| 231 throw reporter.internalError( | 232 throw reporter.internalError( |
| 232 element, 'cyclic resolution of class $element'); | 233 element, 'cyclic resolution of class $element'); |
| 233 } | 234 } |
| 234 | 235 |
| 235 InterfaceType enumType = element.computeType(resolution); | 236 ResolutionInterfaceType enumType = element.computeType(resolution); |
| 236 element.supertype = objectType; | 237 element.supertype = objectType; |
| 237 element.interfaces = const Link<DartType>(); | 238 element.interfaces = const Link<ResolutionDartType>(); |
| 238 calculateAllSupertypes(element); | 239 calculateAllSupertypes(element); |
| 239 | 240 |
| 240 if (node.names.nodes.isEmpty) { | 241 if (node.names.nodes.isEmpty) { |
| 241 reporter.reportErrorMessage( | 242 reporter.reportErrorMessage( |
| 242 node, MessageKind.EMPTY_ENUM_DECLARATION, {'enumName': element.name}); | 243 node, MessageKind.EMPTY_ENUM_DECLARATION, {'enumName': element.name}); |
| 243 } | 244 } |
| 244 | 245 |
| 245 EnumCreator creator = | 246 EnumCreator creator = |
| 246 new EnumCreator(reporter, resolution.commonElements, element); | 247 new EnumCreator(reporter, resolution.commonElements, element); |
| 247 creator.createMembers(); | 248 creator.createMembers(); |
| 248 return enumType; | 249 return enumType; |
| 249 } | 250 } |
| 250 | 251 |
| 251 /// Resolves the mixed type for [mixinNode] and checks that the mixin type | 252 /// Resolves the mixed type for [mixinNode] and checks that the mixin type |
| 252 /// is a valid, non-blacklisted interface type. The mixin type is returned. | 253 /// is a valid, non-blacklisted interface type. The mixin type is returned. |
| 253 DartType checkMixinType(TypeAnnotation mixinNode) { | 254 ResolutionDartType checkMixinType(TypeAnnotation mixinNode) { |
| 254 DartType mixinType = resolveType(mixinNode); | 255 ResolutionDartType mixinType = resolveType(mixinNode); |
| 255 if (isBlackListed(mixinType)) { | 256 if (isBlackListed(mixinType)) { |
| 256 reporter.reportErrorMessage( | 257 reporter.reportErrorMessage( |
| 257 mixinNode, MessageKind.CANNOT_MIXIN, {'type': mixinType}); | 258 mixinNode, MessageKind.CANNOT_MIXIN, {'type': mixinType}); |
| 258 } else if (mixinType.isTypeVariable) { | 259 } else if (mixinType.isTypeVariable) { |
| 259 reporter.reportErrorMessage(mixinNode, MessageKind.CLASS_NAME_EXPECTED); | 260 reporter.reportErrorMessage(mixinNode, MessageKind.CLASS_NAME_EXPECTED); |
| 260 } else if (mixinType.isMalformed) { | 261 } else if (mixinType.isMalformed) { |
| 261 reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_MALFORMED, | 262 reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_MALFORMED, |
| 262 {'className': element.name, 'malformedType': mixinType}); | 263 {'className': element.name, 'malformedType': mixinType}); |
| 263 } else if (mixinType.isEnumType) { | 264 } else if (mixinType.isEnumType) { |
| 264 reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_ENUM, | 265 reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_ENUM, |
| 265 {'className': element.name, 'enumType': mixinType}); | 266 {'className': element.name, 'enumType': mixinType}); |
| 266 } | 267 } |
| 267 return mixinType; | 268 return mixinType; |
| 268 } | 269 } |
| 269 | 270 |
| 270 DartType visitNamedMixinApplication(NamedMixinApplication node) { | 271 ResolutionDartType visitNamedMixinApplication(NamedMixinApplication node) { |
| 271 if (element == null) { | 272 if (element == null) { |
| 272 throw reporter.internalError(node, 'element is null'); | 273 throw reporter.internalError(node, 'element is null'); |
| 273 } | 274 } |
| 274 if (element.resolutionState != STATE_STARTED) { | 275 if (element.resolutionState != STATE_STARTED) { |
| 275 throw reporter.internalError( | 276 throw reporter.internalError( |
| 276 element, 'cyclic resolution of class $element'); | 277 element, 'cyclic resolution of class $element'); |
| 277 } | 278 } |
| 278 | 279 |
| 279 element.computeType(resolution); | 280 element.computeType(resolution); |
| 280 scope = new TypeDeclarationScope(scope, element); | 281 scope = new TypeDeclarationScope(scope, element); |
| 281 resolveTypeVariableBounds(node.typeParameters); | 282 resolveTypeVariableBounds(node.typeParameters); |
| 282 | 283 |
| 283 // Generate anonymous mixin application elements for the | 284 // Generate anonymous mixin application elements for the |
| 284 // intermediate mixin applications (excluding the last). | 285 // intermediate mixin applications (excluding the last). |
| 285 DartType supertype = resolveSupertype(element, node.superclass); | 286 ResolutionDartType supertype = resolveSupertype(element, node.superclass); |
| 286 Link<Node> link = node.mixins.nodes; | 287 Link<Node> link = node.mixins.nodes; |
| 287 while (!link.tail.isEmpty) { | 288 while (!link.tail.isEmpty) { |
| 288 supertype = applyMixin(supertype, checkMixinType(link.head), link.head); | 289 supertype = applyMixin(supertype, checkMixinType(link.head), link.head); |
| 289 link = link.tail; | 290 link = link.tail; |
| 290 } | 291 } |
| 291 doApplyMixinTo(element, supertype, checkMixinType(link.head)); | 292 doApplyMixinTo(element, supertype, checkMixinType(link.head)); |
| 292 return element.computeType(resolution); | 293 return element.computeType(resolution); |
| 293 } | 294 } |
| 294 | 295 |
| 295 DartType applyMixin(DartType supertype, DartType mixinType, Node node) { | 296 ResolutionDartType applyMixin( |
| 297 ResolutionDartType supertype, ResolutionDartType mixinType, Node node) { |
| 296 String superName = supertype.name; | 298 String superName = supertype.name; |
| 297 String mixinName = mixinType.name; | 299 String mixinName = mixinType.name; |
| 298 MixinApplicationElementX mixinApplication = | 300 MixinApplicationElementX mixinApplication = |
| 299 new UnnamedMixinApplicationElementX("${superName}+${mixinName}", | 301 new UnnamedMixinApplicationElementX("${superName}+${mixinName}", |
| 300 element, resolution.idGenerator.getNextFreeId(), node); | 302 element, resolution.idGenerator.getNextFreeId(), node); |
| 301 // Create synthetic type variables for the mixin application. | 303 // Create synthetic type variables for the mixin application. |
| 302 List<DartType> typeVariables = <DartType>[]; | 304 List<ResolutionDartType> typeVariables = <ResolutionDartType>[]; |
| 303 int index = 0; | 305 int index = 0; |
| 304 for (TypeVariableType type in element.typeVariables) { | 306 for (ResolutionTypeVariableType type in element.typeVariables) { |
| 305 TypeVariableElementX typeVariableElement = new TypeVariableElementX( | 307 TypeVariableElementX typeVariableElement = new TypeVariableElementX( |
| 306 type.name, mixinApplication, index, type.element.node); | 308 type.name, mixinApplication, index, type.element.node); |
| 307 TypeVariableType typeVariable = new TypeVariableType(typeVariableElement); | 309 ResolutionTypeVariableType typeVariable = |
| 310 new ResolutionTypeVariableType(typeVariableElement); |
| 308 typeVariables.add(typeVariable); | 311 typeVariables.add(typeVariable); |
| 309 index++; | 312 index++; |
| 310 } | 313 } |
| 311 // Setup bounds on the synthetic type variables. | 314 // Setup bounds on the synthetic type variables. |
| 312 for (TypeVariableType type in element.typeVariables) { | 315 for (ResolutionTypeVariableType type in element.typeVariables) { |
| 313 TypeVariableType typeVariable = typeVariables[type.element.index]; | 316 ResolutionTypeVariableType typeVariable = |
| 317 typeVariables[type.element.index]; |
| 314 TypeVariableElementX typeVariableElement = typeVariable.element; | 318 TypeVariableElementX typeVariableElement = typeVariable.element; |
| 315 typeVariableElement.typeCache = typeVariable; | 319 typeVariableElement.typeCache = typeVariable; |
| 316 typeVariableElement.boundCache = | 320 typeVariableElement.boundCache = |
| 317 type.element.bound.subst(typeVariables, element.typeVariables); | 321 type.element.bound.subst(typeVariables, element.typeVariables); |
| 318 } | 322 } |
| 319 // Setup this and raw type for the mixin application. | 323 // Setup this and raw type for the mixin application. |
| 320 mixinApplication.computeThisAndRawType(resolution, typeVariables); | 324 mixinApplication.computeThisAndRawType(resolution, typeVariables); |
| 321 // Substitute in synthetic type variables in super and mixin types. | 325 // Substitute in synthetic type variables in super and mixin types. |
| 322 supertype = supertype.subst(typeVariables, element.typeVariables); | 326 supertype = supertype.subst(typeVariables, element.typeVariables); |
| 323 mixinType = mixinType.subst(typeVariables, element.typeVariables); | 327 mixinType = mixinType.subst(typeVariables, element.typeVariables); |
| 324 | 328 |
| 325 doApplyMixinTo(mixinApplication, supertype, mixinType); | 329 doApplyMixinTo(mixinApplication, supertype, mixinType); |
| 326 mixinApplication.resolutionState = STATE_DONE; | 330 mixinApplication.resolutionState = STATE_DONE; |
| 327 mixinApplication.supertypeLoadState = STATE_DONE; | 331 mixinApplication.supertypeLoadState = STATE_DONE; |
| 328 // Replace the synthetic type variables by the original type variables in | 332 // Replace the synthetic type variables by the original type variables in |
| 329 // the returned type (which should be the type actually extended). | 333 // the returned type (which should be the type actually extended). |
| 330 InterfaceType mixinThisType = mixinApplication.thisType; | 334 ResolutionInterfaceType mixinThisType = mixinApplication.thisType; |
| 331 return mixinThisType.subst( | 335 return mixinThisType.subst( |
| 332 element.typeVariables, mixinThisType.typeArguments); | 336 element.typeVariables, mixinThisType.typeArguments); |
| 333 } | 337 } |
| 334 | 338 |
| 335 bool isDefaultConstructor(FunctionElement constructor) { | 339 bool isDefaultConstructor(FunctionElement constructor) { |
| 336 if (constructor.name != '') return false; | 340 if (constructor.name != '') return false; |
| 337 constructor.computeType(resolution); | 341 constructor.computeType(resolution); |
| 338 return constructor.functionSignature.parameterCount == 0; | 342 return constructor.functionSignature.parameterCount == 0; |
| 339 } | 343 } |
| 340 | 344 |
| 341 FunctionElement createForwardingConstructor( | 345 FunctionElement createForwardingConstructor( |
| 342 ConstructorElement target, ClassElement enclosing) { | 346 ConstructorElement target, ClassElement enclosing) { |
| 343 FunctionElement constructor = | 347 FunctionElement constructor = |
| 344 new SynthesizedConstructorElementX.notForDefault( | 348 new SynthesizedConstructorElementX.notForDefault( |
| 345 target.name, target, enclosing); | 349 target.name, target, enclosing); |
| 346 constructor.computeType(resolution); | 350 constructor.computeType(resolution); |
| 347 return constructor; | 351 return constructor; |
| 348 } | 352 } |
| 349 | 353 |
| 350 void doApplyMixinTo(MixinApplicationElementX mixinApplication, | 354 void doApplyMixinTo(MixinApplicationElementX mixinApplication, |
| 351 DartType supertype, DartType mixinType) { | 355 ResolutionDartType supertype, ResolutionDartType mixinType) { |
| 352 Node node = mixinApplication.parseNode(resolution.parsingContext); | 356 Node node = mixinApplication.parseNode(resolution.parsingContext); |
| 353 | 357 |
| 354 if (mixinApplication.supertype != null) { | 358 if (mixinApplication.supertype != null) { |
| 355 // [supertype] is not null if there was a cycle. | 359 // [supertype] is not null if there was a cycle. |
| 356 assert(invariant(node, reporter.hasReportedError)); | 360 assert(invariant(node, reporter.hasReportedError)); |
| 357 supertype = mixinApplication.supertype; | 361 supertype = mixinApplication.supertype; |
| 358 assert(invariant(node, supertype.isObject)); | 362 assert(invariant(node, supertype.isObject)); |
| 359 } else { | 363 } else { |
| 360 mixinApplication.supertype = supertype; | 364 mixinApplication.supertype = supertype; |
| 361 } | 365 } |
| 362 | 366 |
| 363 // Named mixin application may have an 'implements' clause. | 367 // Named mixin application may have an 'implements' clause. |
| 364 NamedMixinApplication namedMixinApplication = | 368 NamedMixinApplication namedMixinApplication = |
| 365 node.asNamedMixinApplication(); | 369 node.asNamedMixinApplication(); |
| 366 Link<DartType> interfaces = (namedMixinApplication != null) | 370 Link<ResolutionDartType> interfaces = (namedMixinApplication != null) |
| 367 ? resolveInterfaces( | 371 ? resolveInterfaces( |
| 368 namedMixinApplication.interfaces, namedMixinApplication.superclass) | 372 namedMixinApplication.interfaces, namedMixinApplication.superclass) |
| 369 : const Link<DartType>(); | 373 : const Link<ResolutionDartType>(); |
| 370 | 374 |
| 371 // The class that is the result of a mixin application implements | 375 // The class that is the result of a mixin application implements |
| 372 // the interface of the class that was mixed in so always prepend | 376 // the interface of the class that was mixed in so always prepend |
| 373 // that to the interface list. | 377 // that to the interface list. |
| 374 if (mixinApplication.interfaces == null) { | 378 if (mixinApplication.interfaces == null) { |
| 375 if (mixinType.isInterfaceType) { | 379 if (mixinType.isInterfaceType) { |
| 376 // Avoid malformed types in the interfaces. | 380 // Avoid malformed types in the interfaces. |
| 377 interfaces = interfaces.prepend(mixinType); | 381 interfaces = interfaces.prepend(mixinType); |
| 378 } | 382 } |
| 379 mixinApplication.interfaces = interfaces; | 383 mixinApplication.interfaces = interfaces; |
| 380 } else { | 384 } else { |
| 381 assert( | 385 assert( |
| 382 invariant(mixinApplication, mixinApplication.hasIncompleteHierarchy)); | 386 invariant(mixinApplication, mixinApplication.hasIncompleteHierarchy)); |
| 383 } | 387 } |
| 384 | 388 |
| 385 ClassElement superclass = supertype.element; | 389 ClassElement superclass = supertype.element; |
| 386 if (mixinType.kind != TypeKind.INTERFACE) { | 390 if (mixinType.kind != ResolutionTypeKind.INTERFACE) { |
| 387 mixinApplication.hasIncompleteHierarchy = true; | 391 mixinApplication.hasIncompleteHierarchy = true; |
| 388 mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf; | 392 mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf; |
| 389 return; | 393 return; |
| 390 } | 394 } |
| 391 | 395 |
| 392 assert(mixinApplication.mixinType == null); | 396 assert(mixinApplication.mixinType == null); |
| 393 mixinApplication.mixinType = resolveMixinFor(mixinApplication, mixinType); | 397 mixinApplication.mixinType = resolveMixinFor(mixinApplication, mixinType); |
| 394 | 398 |
| 395 // Create forwarding constructors for constructor defined in the superclass | 399 // Create forwarding constructors for constructor defined in the superclass |
| 396 // because they are now hidden by the mixin application. | 400 // because they are now hidden by the mixin application. |
| 397 superclass.forEachLocalMember((Element member) { | 401 superclass.forEachLocalMember((Element member) { |
| 398 if (!member.isGenerativeConstructor) return; | 402 if (!member.isGenerativeConstructor) return; |
| 399 FunctionElement forwarder = | 403 FunctionElement forwarder = |
| 400 createForwardingConstructor(member, mixinApplication); | 404 createForwardingConstructor(member, mixinApplication); |
| 401 if (Name.isPrivateName(member.name) && | 405 if (Name.isPrivateName(member.name) && |
| 402 mixinApplication.library != superclass.library) { | 406 mixinApplication.library != superclass.library) { |
| 403 // Do not create a forwarder to the super constructor, because the mixin | 407 // Do not create a forwarder to the super constructor, because the mixin |
| 404 // application is in a different library than the constructor in the | 408 // application is in a different library than the constructor in the |
| 405 // super class and it is not possible to call that constructor from the | 409 // super class and it is not possible to call that constructor from the |
| 406 // library using the mixin application. | 410 // library using the mixin application. |
| 407 return; | 411 return; |
| 408 } | 412 } |
| 409 mixinApplication.addConstructor(forwarder); | 413 mixinApplication.addConstructor(forwarder); |
| 410 }); | 414 }); |
| 411 calculateAllSupertypes(mixinApplication); | 415 calculateAllSupertypes(mixinApplication); |
| 412 } | 416 } |
| 413 | 417 |
| 414 InterfaceType resolveMixinFor( | 418 ResolutionInterfaceType resolveMixinFor( |
| 415 MixinApplicationElement mixinApplication, DartType mixinType) { | 419 MixinApplicationElement mixinApplication, ResolutionDartType mixinType) { |
| 416 ClassElement mixin = mixinType.element; | 420 ClassElement mixin = mixinType.element; |
| 417 mixin.ensureResolved(resolution); | 421 mixin.ensureResolved(resolution); |
| 418 | 422 |
| 419 // Check for cycles in the mixin chain. | 423 // Check for cycles in the mixin chain. |
| 420 ClassElement previous = mixinApplication; // For better error messages. | 424 ClassElement previous = mixinApplication; // For better error messages. |
| 421 ClassElement current = mixin; | 425 ClassElement current = mixin; |
| 422 while (current != null && current.isMixinApplication) { | 426 while (current != null && current.isMixinApplication) { |
| 423 MixinApplicationElement currentMixinApplication = current; | 427 MixinApplicationElement currentMixinApplication = current; |
| 424 if (currentMixinApplication == mixinApplication) { | 428 if (currentMixinApplication == mixinApplication) { |
| 425 reporter.reportErrorMessage( | 429 reporter.reportErrorMessage( |
| 426 mixinApplication, | 430 mixinApplication, |
| 427 MessageKind.ILLEGAL_MIXIN_CYCLE, | 431 MessageKind.ILLEGAL_MIXIN_CYCLE, |
| 428 {'mixinName1': current.name, 'mixinName2': previous.name}); | 432 {'mixinName1': current.name, 'mixinName2': previous.name}); |
| 429 // We have found a cycle in the mixin chain. Return null as | 433 // We have found a cycle in the mixin chain. Return null as |
| 430 // the mixin for this application to avoid getting into | 434 // the mixin for this application to avoid getting into |
| 431 // infinite recursion when traversing members. | 435 // infinite recursion when traversing members. |
| 432 return null; | 436 return null; |
| 433 } | 437 } |
| 434 previous = current; | 438 previous = current; |
| 435 current = currentMixinApplication.mixin; | 439 current = currentMixinApplication.mixin; |
| 436 } | 440 } |
| 437 return mixinType; | 441 return mixinType; |
| 438 } | 442 } |
| 439 | 443 |
| 440 DartType resolveType(TypeAnnotation node) { | 444 ResolutionDartType resolveType(TypeAnnotation node) { |
| 441 return typeResolver.resolveTypeAnnotation(this, node); | 445 return typeResolver.resolveTypeAnnotation(this, node); |
| 442 } | 446 } |
| 443 | 447 |
| 444 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { | 448 ResolutionDartType resolveSupertype( |
| 445 DartType supertype = resolveType(superclass); | 449 ClassElement cls, TypeAnnotation superclass) { |
| 450 ResolutionDartType supertype = resolveType(superclass); |
| 446 if (supertype != null) { | 451 if (supertype != null) { |
| 447 if (supertype.isMalformed) { | 452 if (supertype.isMalformed) { |
| 448 reporter.reportErrorMessage( | 453 reporter.reportErrorMessage( |
| 449 superclass, | 454 superclass, |
| 450 MessageKind.CANNOT_EXTEND_MALFORMED, | 455 MessageKind.CANNOT_EXTEND_MALFORMED, |
| 451 {'className': element.name, 'malformedType': supertype}); | 456 {'className': element.name, 'malformedType': supertype}); |
| 452 return objectType; | 457 return objectType; |
| 453 } else if (supertype.isEnumType) { | 458 } else if (supertype.isEnumType) { |
| 454 reporter.reportErrorMessage(superclass, MessageKind.CANNOT_EXTEND_ENUM, | 459 reporter.reportErrorMessage(superclass, MessageKind.CANNOT_EXTEND_ENUM, |
| 455 {'className': element.name, 'enumType': supertype}); | 460 {'className': element.name, 'enumType': supertype}); |
| 456 return objectType; | 461 return objectType; |
| 457 } else if (!supertype.isInterfaceType) { | 462 } else if (!supertype.isInterfaceType) { |
| 458 reporter.reportErrorMessage( | 463 reporter.reportErrorMessage( |
| 459 superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); | 464 superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); |
| 460 return objectType; | 465 return objectType; |
| 461 } else if (isBlackListed(supertype)) { | 466 } else if (isBlackListed(supertype)) { |
| 462 reporter.reportErrorMessage( | 467 reporter.reportErrorMessage( |
| 463 superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); | 468 superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); |
| 464 return objectType; | 469 return objectType; |
| 465 } | 470 } |
| 466 } | 471 } |
| 467 return supertype; | 472 return supertype; |
| 468 } | 473 } |
| 469 | 474 |
| 470 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { | 475 Link<ResolutionDartType> resolveInterfaces( |
| 471 Link<DartType> result = const Link<DartType>(); | 476 NodeList interfaces, Node superclass) { |
| 477 Link<ResolutionDartType> result = const Link<ResolutionDartType>(); |
| 472 if (interfaces == null) return result; | 478 if (interfaces == null) return result; |
| 473 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { | 479 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { |
| 474 DartType interfaceType = resolveType(link.head); | 480 ResolutionDartType interfaceType = resolveType(link.head); |
| 475 if (interfaceType != null) { | 481 if (interfaceType != null) { |
| 476 if (interfaceType.isMalformed) { | 482 if (interfaceType.isMalformed) { |
| 477 reporter.reportErrorMessage( | 483 reporter.reportErrorMessage( |
| 478 link.head, | 484 link.head, |
| 479 MessageKind.CANNOT_IMPLEMENT_MALFORMED, | 485 MessageKind.CANNOT_IMPLEMENT_MALFORMED, |
| 480 {'className': element.name, 'malformedType': interfaceType}); | 486 {'className': element.name, 'malformedType': interfaceType}); |
| 481 } else if (interfaceType.isEnumType) { | 487 } else if (interfaceType.isEnumType) { |
| 482 reporter.reportErrorMessage( | 488 reporter.reportErrorMessage( |
| 483 link.head, | 489 link.head, |
| 484 MessageKind.CANNOT_IMPLEMENT_ENUM, | 490 MessageKind.CANNOT_IMPLEMENT_ENUM, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1) | 531 * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1) |
| 526 * ++ supertypes(I2), | 532 * ++ supertypes(I2), |
| 527 * where ++ stands for list concatenation. | 533 * where ++ stands for list concatenation. |
| 528 * | 534 * |
| 529 * This order makes sure that if a class implements an interface twice with | 535 * This order makes sure that if a class implements an interface twice with |
| 530 * different type arguments, the type used in the most specific class comes | 536 * different type arguments, the type used in the most specific class comes |
| 531 * first. | 537 * first. |
| 532 */ | 538 */ |
| 533 void calculateAllSupertypes(BaseClassElementX cls) { | 539 void calculateAllSupertypes(BaseClassElementX cls) { |
| 534 if (cls.allSupertypesAndSelf != null) return; | 540 if (cls.allSupertypesAndSelf != null) return; |
| 535 final DartType supertype = cls.supertype; | 541 final ResolutionDartType supertype = cls.supertype; |
| 536 if (supertype != null) { | 542 if (supertype != null) { |
| 537 cls.allSupertypesAndSelf = new OrderedTypeSetBuilder(cls, | 543 cls.allSupertypesAndSelf = new OrderedTypeSetBuilder(cls, |
| 538 reporter: reporter, objectType: commonElements.objectType) | 544 reporter: reporter, objectType: commonElements.objectType) |
| 539 .createOrderedTypeSet(supertype, cls.interfaces); | 545 .createOrderedTypeSet(supertype, cls.interfaces); |
| 540 } else { | 546 } else { |
| 541 assert(cls == resolution.commonElements.objectClass); | 547 assert(cls == resolution.commonElements.objectClass); |
| 542 cls.allSupertypesAndSelf = | 548 cls.allSupertypesAndSelf = |
| 543 new OrderedTypeSet.singleton(cls.computeType(resolution)); | 549 new OrderedTypeSet.singleton(cls.computeType(resolution)); |
| 544 } | 550 } |
| 545 } | 551 } |
| 546 | 552 |
| 547 isBlackListed(DartType type) { | 553 isBlackListed(ResolutionDartType type) { |
| 548 LibraryElement lib = element.library; | 554 LibraryElement lib = element.library; |
| 549 return !identical(lib, resolution.commonElements.coreLibrary) && | 555 return !identical(lib, resolution.commonElements.coreLibrary) && |
| 550 !resolution.target.isTargetSpecificLibrary(lib) && | 556 !resolution.target.isTargetSpecificLibrary(lib) && |
| 551 (type.isDynamic || | 557 (type.isDynamic || |
| 552 type == commonElements.boolType || | 558 type == commonElements.boolType || |
| 553 type == commonElements.numType || | 559 type == commonElements.numType || |
| 554 type == commonElements.intType || | 560 type == commonElements.intType || |
| 555 type == commonElements.doubleType || | 561 type == commonElements.doubleType || |
| 556 type == commonElements.stringType || | 562 type == commonElements.stringType || |
| 557 type == commonElements.nullType); | 563 type == commonElements.nullType); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 Identifier selector = node.selector.asIdentifier(); | 644 Identifier selector = node.selector.asIdentifier(); |
| 639 var e = prefixElement.lookupLocalMember(selector.source); | 645 var e = prefixElement.lookupLocalMember(selector.source); |
| 640 if (e == null || !e.impliesType) { | 646 if (e == null || !e.impliesType) { |
| 641 reporter.reportErrorMessage(node.selector, | 647 reporter.reportErrorMessage(node.selector, |
| 642 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.selector}); | 648 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.selector}); |
| 643 return; | 649 return; |
| 644 } | 650 } |
| 645 loadSupertype(e, node); | 651 loadSupertype(e, node); |
| 646 } | 652 } |
| 647 } | 653 } |
| OLD | NEW |