| 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 | 8 import '../common/resolution.dart' show Feature; |
| 9 Feature; | 9 import '../compiler.dart' show Compiler; |
| 10 import '../compiler.dart' show | 10 import '../core_types.dart' show CoreClasses, CoreTypes; |
| 11 Compiler; | |
| 12 import '../core_types.dart' show | |
| 13 CoreClasses, | |
| 14 CoreTypes; | |
| 15 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
| 16 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
| 17 import '../elements/modelx.dart' show | 13 import '../elements/modelx.dart' |
| 18 BaseClassElementX, | 14 show |
| 19 ErroneousElementX, | 15 BaseClassElementX, |
| 20 MixinApplicationElementX, | 16 ErroneousElementX, |
| 21 SynthesizedConstructorElementX, | 17 MixinApplicationElementX, |
| 22 TypeVariableElementX, | 18 SynthesizedConstructorElementX, |
| 23 UnnamedMixinApplicationElementX; | 19 TypeVariableElementX, |
| 24 import '../ordered_typeset.dart' show | 20 UnnamedMixinApplicationElementX; |
| 25 OrderedTypeSet, | 21 import '../ordered_typeset.dart' show OrderedTypeSet, OrderedTypeSetBuilder; |
| 26 OrderedTypeSetBuilder; | |
| 27 import '../tree/tree.dart'; | 22 import '../tree/tree.dart'; |
| 28 import '../util/util.dart' show | 23 import '../util/util.dart' show Link, Setlet; |
| 29 Link, | 24 import '../universe/call_structure.dart' show CallStructure; |
| 30 Setlet; | |
| 31 import '../universe/call_structure.dart' show | |
| 32 CallStructure; | |
| 33 | 25 |
| 34 import 'enum_creator.dart'; | 26 import 'enum_creator.dart'; |
| 35 import 'members.dart' show | 27 import 'members.dart' show lookupInScope; |
| 36 lookupInScope; | 28 import 'registry.dart' show ResolutionRegistry; |
| 37 import 'registry.dart' show | 29 import 'resolution_common.dart' show CommonResolverVisitor, MappingVisitor; |
| 38 ResolutionRegistry; | 30 import 'scope.dart' show Scope, TypeDeclarationScope; |
| 39 import 'resolution_common.dart' show | |
| 40 CommonResolverVisitor, | |
| 41 MappingVisitor; | |
| 42 import 'scope.dart' show | |
| 43 Scope, | |
| 44 TypeDeclarationScope; | |
| 45 | 31 |
| 46 class TypeDefinitionVisitor extends MappingVisitor<DartType> { | 32 class TypeDefinitionVisitor extends MappingVisitor<DartType> { |
| 47 Scope scope; | 33 Scope scope; |
| 48 final TypeDeclarationElement enclosingElement; | 34 final TypeDeclarationElement enclosingElement; |
| 49 TypeDeclarationElement get element => enclosingElement; | 35 TypeDeclarationElement get element => enclosingElement; |
| 50 | 36 |
| 51 TypeDefinitionVisitor(Compiler compiler, | 37 TypeDefinitionVisitor(Compiler compiler, TypeDeclarationElement element, |
| 52 TypeDeclarationElement element, | 38 ResolutionRegistry registry) |
| 53 ResolutionRegistry registry) | |
| 54 : this.enclosingElement = element, | 39 : this.enclosingElement = element, |
| 55 scope = Scope.buildEnclosingScope(element), | 40 scope = Scope.buildEnclosingScope(element), |
| 56 super(compiler, registry); | 41 super(compiler, registry); |
| 57 | 42 |
| 58 CoreTypes get coreTypes => compiler.coreTypes; | 43 CoreTypes get coreTypes => compiler.coreTypes; |
| 59 | 44 |
| 60 DartType get objectType => coreTypes.objectType; | 45 DartType get objectType => coreTypes.objectType; |
| 61 | 46 |
| 62 | |
| 63 void resolveTypeVariableBounds(NodeList node) { | 47 void resolveTypeVariableBounds(NodeList node) { |
| 64 if (node == null) return; | 48 if (node == null) return; |
| 65 | 49 |
| 66 Setlet<String> nameSet = new Setlet<String>(); | 50 Setlet<String> nameSet = new Setlet<String>(); |
| 67 // Resolve the bounds of type variables. | 51 // Resolve the bounds of type variables. |
| 68 Iterator<DartType> types = element.typeVariables.iterator; | 52 Iterator<DartType> types = element.typeVariables.iterator; |
| 69 Link<Node> nodeLink = node.nodes; | 53 Link<Node> nodeLink = node.nodes; |
| 70 while (!nodeLink.isEmpty) { | 54 while (!nodeLink.isEmpty) { |
| 71 types.moveNext(); | 55 types.moveNext(); |
| 72 TypeVariableType typeVariable = types.current; | 56 TypeVariableType typeVariable = types.current; |
| 73 String typeName = typeVariable.name; | 57 String typeName = typeVariable.name; |
| 74 TypeVariable typeNode = nodeLink.head; | 58 TypeVariable typeNode = nodeLink.head; |
| 75 registry.useType(typeNode, typeVariable); | 59 registry.useType(typeNode, typeVariable); |
| 76 if (nameSet.contains(typeName)) { | 60 if (nameSet.contains(typeName)) { |
| 77 reporter.reportErrorMessage( | 61 reporter.reportErrorMessage( |
| 78 typeNode, | 62 typeNode, |
| 79 MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, | 63 MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, |
| 80 {'typeVariableName': typeName}); | 64 {'typeVariableName': typeName}); |
| 81 } | 65 } |
| 82 nameSet.add(typeName); | 66 nameSet.add(typeName); |
| 83 | 67 |
| 84 TypeVariableElementX variableElement = typeVariable.element; | 68 TypeVariableElementX variableElement = typeVariable.element; |
| 85 if (typeNode.bound != null) { | 69 if (typeNode.bound != null) { |
| 86 DartType boundType = typeResolver.resolveTypeAnnotation( | 70 DartType boundType = |
| 87 this, typeNode.bound); | 71 typeResolver.resolveTypeAnnotation(this, typeNode.bound); |
| 88 variableElement.boundCache = boundType; | 72 variableElement.boundCache = boundType; |
| 89 | 73 |
| 90 void checkTypeVariableBound() { | 74 void checkTypeVariableBound() { |
| 91 Link<TypeVariableElement> seenTypeVariables = | 75 Link<TypeVariableElement> seenTypeVariables = |
| 92 const Link<TypeVariableElement>(); | 76 const Link<TypeVariableElement>(); |
| 93 seenTypeVariables = seenTypeVariables.prepend(variableElement); | 77 seenTypeVariables = seenTypeVariables.prepend(variableElement); |
| 94 DartType bound = boundType; | 78 DartType bound = boundType; |
| 95 while (bound.isTypeVariable) { | 79 while (bound.isTypeVariable) { |
| 96 TypeVariableElement element = bound.element; | 80 TypeVariableElement element = bound.element; |
| 97 if (seenTypeVariables.contains(element)) { | 81 if (seenTypeVariables.contains(element)) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 127 * this may lead to cycles. | 111 * this may lead to cycles. |
| 128 * | 112 * |
| 129 * This visitor can assume that the supertypes have already been | 113 * This visitor can assume that the supertypes have already been |
| 130 * resolved, but it cannot call [ResolverTask.resolveClass] directly | 114 * resolved, but it cannot call [ResolverTask.resolveClass] directly |
| 131 * or indirectly (through [ClassElement.ensureResolved]) for any other | 115 * or indirectly (through [ClassElement.ensureResolved]) for any other |
| 132 * types. | 116 * types. |
| 133 */ | 117 */ |
| 134 class ClassResolverVisitor extends TypeDefinitionVisitor { | 118 class ClassResolverVisitor extends TypeDefinitionVisitor { |
| 135 BaseClassElementX get element => enclosingElement; | 119 BaseClassElementX get element => enclosingElement; |
| 136 | 120 |
| 137 ClassResolverVisitor(Compiler compiler, | 121 ClassResolverVisitor( |
| 138 ClassElement classElement, | 122 Compiler compiler, ClassElement classElement, ResolutionRegistry registry) |
| 139 ResolutionRegistry registry) | 123 : super(compiler, classElement, registry); |
| 140 : super(compiler, classElement, registry); | |
| 141 | 124 |
| 142 DartType visitClassNode(ClassNode node) { | 125 DartType visitClassNode(ClassNode node) { |
| 143 if (element == null) { | 126 if (element == null) { |
| 144 throw reporter.internalError(node, 'element is null'); | 127 throw reporter.internalError(node, 'element is null'); |
| 145 } | 128 } |
| 146 if (element.resolutionState != STATE_STARTED) { | 129 if (element.resolutionState != STATE_STARTED) { |
| 147 throw reporter.internalError(element, | 130 throw reporter.internalError( |
| 148 'cyclic resolution of class $element'); | 131 element, 'cyclic resolution of class $element'); |
| 149 } | 132 } |
| 150 | 133 |
| 151 element.computeType(resolution); | 134 element.computeType(resolution); |
| 152 scope = new TypeDeclarationScope(scope, element); | 135 scope = new TypeDeclarationScope(scope, element); |
| 153 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. | 136 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. |
| 154 // 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 |
| 155 // resolve this class again. | 138 // resolve this class again. |
| 156 resolveTypeVariableBounds(node.typeParameters); | 139 resolveTypeVariableBounds(node.typeParameters); |
| 157 | 140 |
| 158 // 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 |
| 159 // class hierarchy, it has already been set to Object). | 142 // class hierarchy, it has already been set to Object). |
| 160 if (element.supertype == null && node.superclass != null) { | 143 if (element.supertype == null && node.superclass != null) { |
| 161 MixinApplication superMixin = node.superclass.asMixinApplication(); | 144 MixinApplication superMixin = node.superclass.asMixinApplication(); |
| 162 if (superMixin != null) { | 145 if (superMixin != null) { |
| 163 DartType supertype = resolveSupertype(element, superMixin.superclass); | 146 DartType supertype = resolveSupertype(element, superMixin.superclass); |
| 164 Link<Node> link = superMixin.mixins.nodes; | 147 Link<Node> link = superMixin.mixins.nodes; |
| 165 while (!link.isEmpty) { | 148 while (!link.isEmpty) { |
| 166 supertype = applyMixin(supertype, | 149 supertype = |
| 167 checkMixinType(link.head), link.head); | 150 applyMixin(supertype, checkMixinType(link.head), link.head); |
| 168 link = link.tail; | 151 link = link.tail; |
| 169 } | 152 } |
| 170 element.supertype = supertype; | 153 element.supertype = supertype; |
| 171 } else { | 154 } else { |
| 172 element.supertype = resolveSupertype(element, node.superclass); | 155 element.supertype = resolveSupertype(element, node.superclass); |
| 173 } | 156 } |
| 174 } | 157 } |
| 175 // If the super type isn't specified, we provide a default. The language | 158 // If the super type isn't specified, we provide a default. The language |
| 176 // specifies [Object] but the backend can pick a specific 'implementation' | 159 // specifies [Object] but the backend can pick a specific 'implementation' |
| 177 // of Object - the JavaScript backend chooses between Object and | 160 // of Object - the JavaScript backend chooses between Object and |
| 178 // Interceptor. | 161 // Interceptor. |
| 179 if (element.supertype == null) { | 162 if (element.supertype == null) { |
| 180 ClassElement superElement = registry.defaultSuperclass(element); | 163 ClassElement superElement = registry.defaultSuperclass(element); |
| 181 // Avoid making the superclass (usually Object) extend itself. | 164 // Avoid making the superclass (usually Object) extend itself. |
| 182 if (element != superElement) { | 165 if (element != superElement) { |
| 183 if (superElement == null) { | 166 if (superElement == null) { |
| 184 reporter.internalError(node, | 167 reporter.internalError( |
| 185 "Cannot resolve default superclass for $element."); | 168 node, "Cannot resolve default superclass for $element."); |
| 186 } else { | 169 } else { |
| 187 superElement.ensureResolved(resolution); | 170 superElement.ensureResolved(resolution); |
| 188 } | 171 } |
| 189 element.supertype = superElement.computeType(resolution); | 172 element.supertype = superElement.computeType(resolution); |
| 190 } | 173 } |
| 191 } | 174 } |
| 192 | 175 |
| 193 if (element.interfaces == null) { | 176 if (element.interfaces == null) { |
| 194 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); | 177 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); |
| 195 } else { | 178 } else { |
| 196 assert(invariant(element, element.hasIncompleteHierarchy)); | 179 assert(invariant(element, element.hasIncompleteHierarchy)); |
| 197 } | 180 } |
| 198 calculateAllSupertypes(element); | 181 calculateAllSupertypes(element); |
| 199 | 182 |
| 200 if (!element.hasConstructor) { | 183 if (!element.hasConstructor) { |
| 201 Element superMember = element.superclass.localLookup(''); | 184 Element superMember = element.superclass.localLookup(''); |
| 202 if (superMember == null) { | 185 if (superMember == null) { |
| 203 MessageKind kind = MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR; | 186 MessageKind kind = MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR; |
| 204 Map arguments = {'className': element.superclass.name}; | 187 Map arguments = {'className': element.superclass.name}; |
| 205 // TODO(ahe): Why is this a compile-time error? Or if it is an error, | 188 // TODO(ahe): Why is this a compile-time error? Or if it is an error, |
| 206 // why do we bother to registerThrowNoSuchMethod below? | 189 // why do we bother to registerThrowNoSuchMethod below? |
| 207 reporter.reportErrorMessage(node, kind, arguments); | 190 reporter.reportErrorMessage(node, kind, arguments); |
| 208 superMember = new ErroneousElementX( | 191 superMember = new ErroneousElementX(kind, arguments, '', element); |
| 209 kind, arguments, '', element); | |
| 210 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); | 192 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); |
| 211 } else if (!superMember.isGenerativeConstructor) { | 193 } else if (!superMember.isGenerativeConstructor) { |
| 212 MessageKind kind = MessageKind.SUPER_CALL_TO_FACTORY; | 194 MessageKind kind = MessageKind.SUPER_CALL_TO_FACTORY; |
| 213 Map arguments = {'className': element.superclass.name}; | 195 Map arguments = {'className': element.superclass.name}; |
| 214 // TODO(ahe): Why is this a compile-time error? Or if it is an error, | 196 // TODO(ahe): Why is this a compile-time error? Or if it is an error, |
| 215 // why do we bother to registerThrowNoSuchMethod below? | 197 // why do we bother to registerThrowNoSuchMethod below? |
| 216 reporter.reportErrorMessage(node, kind, arguments); | 198 reporter.reportErrorMessage(node, kind, arguments); |
| 217 superMember = new ErroneousElementX( | 199 superMember = new ErroneousElementX(kind, arguments, '', element); |
| 218 kind, arguments, '', element); | 200 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); |
| 219 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); | |
| 220 } else { | 201 } else { |
| 221 ConstructorElement superConstructor = superMember; | 202 ConstructorElement superConstructor = superMember; |
| 222 superConstructor.computeType(resolution); | 203 superConstructor.computeType(resolution); |
| 223 if (!CallStructure.NO_ARGS.signatureApplies( | 204 if (!CallStructure.NO_ARGS |
| 224 superConstructor.functionSignature)) { | 205 .signatureApplies(superConstructor.functionSignature)) { |
| 225 MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT; | 206 MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT; |
| 226 reporter.reportErrorMessage(node, kind); | 207 reporter.reportErrorMessage(node, kind); |
| 227 superMember = new ErroneousElementX(kind, {}, '', element); | 208 superMember = new ErroneousElementX(kind, {}, '', element); |
| 228 } | 209 } |
| 229 } | 210 } |
| 230 FunctionElement constructor = | 211 FunctionElement constructor = |
| 231 new SynthesizedConstructorElementX.forDefault(superMember, element); | 212 new SynthesizedConstructorElementX.forDefault(superMember, element); |
| 232 if (superMember.isMalformed) { | 213 if (superMember.isMalformed) { |
| 233 compiler.elementsWithCompileTimeErrors.add(constructor); | 214 compiler.elementsWithCompileTimeErrors.add(constructor); |
| 234 } | 215 } |
| 235 element.setDefaultConstructor(constructor, reporter); | 216 element.setDefaultConstructor(constructor, reporter); |
| 236 } | 217 } |
| 237 return element.computeType(resolution); | 218 return element.computeType(resolution); |
| 238 } | 219 } |
| 239 | 220 |
| 240 @override | 221 @override |
| 241 DartType visitEnum(Enum node) { | 222 DartType visitEnum(Enum node) { |
| 242 if (element == null) { | 223 if (element == null) { |
| 243 throw reporter.internalError(node, 'element is null'); | 224 throw reporter.internalError(node, 'element is null'); |
| 244 } | 225 } |
| 245 if (element.resolutionState != STATE_STARTED) { | 226 if (element.resolutionState != STATE_STARTED) { |
| 246 throw reporter.internalError(element, | 227 throw reporter.internalError( |
| 247 'cyclic resolution of class $element'); | 228 element, 'cyclic resolution of class $element'); |
| 248 } | 229 } |
| 249 | 230 |
| 250 InterfaceType enumType = element.computeType(resolution); | 231 InterfaceType enumType = element.computeType(resolution); |
| 251 element.supertype = objectType; | 232 element.supertype = objectType; |
| 252 element.interfaces = const Link<DartType>(); | 233 element.interfaces = const Link<DartType>(); |
| 253 calculateAllSupertypes(element); | 234 calculateAllSupertypes(element); |
| 254 | 235 |
| 255 if (node.names.nodes.isEmpty) { | 236 if (node.names.nodes.isEmpty) { |
| 256 reporter.reportErrorMessage( | 237 reporter.reportErrorMessage( |
| 257 node, | 238 node, MessageKind.EMPTY_ENUM_DECLARATION, {'enumName': element.name}); |
| 258 MessageKind.EMPTY_ENUM_DECLARATION, | |
| 259 {'enumName': element.name}); | |
| 260 } | 239 } |
| 261 | 240 |
| 262 EnumCreator creator = | 241 EnumCreator creator = |
| 263 new EnumCreator(reporter, compiler.coreTypes, element); | 242 new EnumCreator(reporter, compiler.coreTypes, element); |
| 264 creator.createMembers(); | 243 creator.createMembers(); |
| 265 return enumType; | 244 return enumType; |
| 266 } | 245 } |
| 267 | 246 |
| 268 /// Resolves the mixed type for [mixinNode] and checks that the the mixin type | 247 /// Resolves the mixed type for [mixinNode] and checks that the the mixin type |
| 269 /// is a valid, non-blacklisted interface type. The mixin type is returned. | 248 /// is a valid, non-blacklisted interface type. The mixin type is returned. |
| 270 DartType checkMixinType(TypeAnnotation mixinNode) { | 249 DartType checkMixinType(TypeAnnotation mixinNode) { |
| 271 DartType mixinType = resolveType(mixinNode); | 250 DartType mixinType = resolveType(mixinNode); |
| 272 if (isBlackListed(mixinType)) { | 251 if (isBlackListed(mixinType)) { |
| 273 reporter.reportErrorMessage( | 252 reporter.reportErrorMessage( |
| 274 mixinNode, | 253 mixinNode, MessageKind.CANNOT_MIXIN, {'type': mixinType}); |
| 275 MessageKind.CANNOT_MIXIN, | |
| 276 {'type': mixinType}); | |
| 277 } else if (mixinType.isTypeVariable) { | 254 } else if (mixinType.isTypeVariable) { |
| 278 reporter.reportErrorMessage( | 255 reporter.reportErrorMessage(mixinNode, MessageKind.CLASS_NAME_EXPECTED); |
| 279 mixinNode, | |
| 280 MessageKind.CLASS_NAME_EXPECTED); | |
| 281 } else if (mixinType.isMalformed) { | 256 } else if (mixinType.isMalformed) { |
| 282 reporter.reportErrorMessage( | 257 reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_MALFORMED, |
| 283 mixinNode, | |
| 284 MessageKind.CANNOT_MIXIN_MALFORMED, | |
| 285 {'className': element.name, 'malformedType': mixinType}); | 258 {'className': element.name, 'malformedType': mixinType}); |
| 286 } else if (mixinType.isEnumType) { | 259 } else if (mixinType.isEnumType) { |
| 287 reporter.reportErrorMessage( | 260 reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_ENUM, |
| 288 mixinNode, | |
| 289 MessageKind.CANNOT_MIXIN_ENUM, | |
| 290 {'className': element.name, 'enumType': mixinType}); | 261 {'className': element.name, 'enumType': mixinType}); |
| 291 } | 262 } |
| 292 return mixinType; | 263 return mixinType; |
| 293 } | 264 } |
| 294 | 265 |
| 295 DartType visitNamedMixinApplication(NamedMixinApplication node) { | 266 DartType visitNamedMixinApplication(NamedMixinApplication node) { |
| 296 if (element == null) { | 267 if (element == null) { |
| 297 throw reporter.internalError(node, 'element is null'); | 268 throw reporter.internalError(node, 'element is null'); |
| 298 } | 269 } |
| 299 if (element.resolutionState != STATE_STARTED) { | 270 if (element.resolutionState != STATE_STARTED) { |
| 300 throw reporter.internalError(element, | 271 throw reporter.internalError( |
| 301 'cyclic resolution of class $element'); | 272 element, 'cyclic resolution of class $element'); |
| 302 } | 273 } |
| 303 | 274 |
| 304 if (identical(node.classKeyword.stringValue, 'typedef')) { | 275 if (identical(node.classKeyword.stringValue, 'typedef')) { |
| 305 // TODO(aprelev@gmail.com): Remove this deprecation diagnostic | 276 // TODO(aprelev@gmail.com): Remove this deprecation diagnostic |
| 306 // together with corresponding TODO in parser.dart. | 277 // together with corresponding TODO in parser.dart. |
| 307 reporter.reportWarningMessage( | 278 reporter.reportWarningMessage( |
| 308 node.classKeyword, | 279 node.classKeyword, MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX); |
| 309 MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX); | |
| 310 } | 280 } |
| 311 | 281 |
| 312 element.computeType(resolution); | 282 element.computeType(resolution); |
| 313 scope = new TypeDeclarationScope(scope, element); | 283 scope = new TypeDeclarationScope(scope, element); |
| 314 resolveTypeVariableBounds(node.typeParameters); | 284 resolveTypeVariableBounds(node.typeParameters); |
| 315 | 285 |
| 316 // Generate anonymous mixin application elements for the | 286 // Generate anonymous mixin application elements for the |
| 317 // intermediate mixin applications (excluding the last). | 287 // intermediate mixin applications (excluding the last). |
| 318 DartType supertype = resolveSupertype(element, node.superclass); | 288 DartType supertype = resolveSupertype(element, node.superclass); |
| 319 Link<Node> link = node.mixins.nodes; | 289 Link<Node> link = node.mixins.nodes; |
| 320 while (!link.tail.isEmpty) { | 290 while (!link.tail.isEmpty) { |
| 321 supertype = applyMixin(supertype, checkMixinType(link.head), link.head); | 291 supertype = applyMixin(supertype, checkMixinType(link.head), link.head); |
| 322 link = link.tail; | 292 link = link.tail; |
| 323 } | 293 } |
| 324 doApplyMixinTo(element, supertype, checkMixinType(link.head)); | 294 doApplyMixinTo(element, supertype, checkMixinType(link.head)); |
| 325 return element.computeType(resolution); | 295 return element.computeType(resolution); |
| 326 } | 296 } |
| 327 | 297 |
| 328 DartType applyMixin(DartType supertype, DartType mixinType, Node node) { | 298 DartType applyMixin(DartType supertype, DartType mixinType, Node node) { |
| 329 String superName = supertype.name; | 299 String superName = supertype.name; |
| 330 String mixinName = mixinType.name; | 300 String mixinName = mixinType.name; |
| 331 MixinApplicationElementX mixinApplication = | 301 MixinApplicationElementX mixinApplication = |
| 332 new UnnamedMixinApplicationElementX( | 302 new UnnamedMixinApplicationElementX("${superName}+${mixinName}", |
| 333 "${superName}+${mixinName}", | 303 element.compilationUnit, compiler.getNextFreeClassId(), node); |
| 334 element.compilationUnit, | |
| 335 compiler.getNextFreeClassId(), | |
| 336 node); | |
| 337 // Create synthetic type variables for the mixin application. | 304 // Create synthetic type variables for the mixin application. |
| 338 List<DartType> typeVariables = <DartType>[]; | 305 List<DartType> typeVariables = <DartType>[]; |
| 339 int index = 0; | 306 int index = 0; |
| 340 for (TypeVariableType type in element.typeVariables) { | 307 for (TypeVariableType type in element.typeVariables) { |
| 341 TypeVariableElementX typeVariableElement = new TypeVariableElementX( | 308 TypeVariableElementX typeVariableElement = new TypeVariableElementX( |
| 342 type.name, mixinApplication, index, type.element.node); | 309 type.name, mixinApplication, index, type.element.node); |
| 343 TypeVariableType typeVariable = new TypeVariableType(typeVariableElement); | 310 TypeVariableType typeVariable = new TypeVariableType(typeVariableElement); |
| 344 typeVariables.add(typeVariable); | 311 typeVariables.add(typeVariable); |
| 345 index++; | 312 index++; |
| 346 } | 313 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 357 // Substitute in synthetic type variables in super and mixin types. | 324 // Substitute in synthetic type variables in super and mixin types. |
| 358 supertype = supertype.subst(typeVariables, element.typeVariables); | 325 supertype = supertype.subst(typeVariables, element.typeVariables); |
| 359 mixinType = mixinType.subst(typeVariables, element.typeVariables); | 326 mixinType = mixinType.subst(typeVariables, element.typeVariables); |
| 360 | 327 |
| 361 doApplyMixinTo(mixinApplication, supertype, mixinType); | 328 doApplyMixinTo(mixinApplication, supertype, mixinType); |
| 362 mixinApplication.resolutionState = STATE_DONE; | 329 mixinApplication.resolutionState = STATE_DONE; |
| 363 mixinApplication.supertypeLoadState = STATE_DONE; | 330 mixinApplication.supertypeLoadState = STATE_DONE; |
| 364 // Replace the synthetic type variables by the original type variables in | 331 // Replace the synthetic type variables by the original type variables in |
| 365 // the returned type (which should be the type actually extended). | 332 // the returned type (which should be the type actually extended). |
| 366 InterfaceType mixinThisType = mixinApplication.thisType; | 333 InterfaceType mixinThisType = mixinApplication.thisType; |
| 367 return mixinThisType.subst(element.typeVariables, | 334 return mixinThisType.subst( |
| 368 mixinThisType.typeArguments); | 335 element.typeVariables, mixinThisType.typeArguments); |
| 369 } | 336 } |
| 370 | 337 |
| 371 bool isDefaultConstructor(FunctionElement constructor) { | 338 bool isDefaultConstructor(FunctionElement constructor) { |
| 372 if (constructor.name != '') return false; | 339 if (constructor.name != '') return false; |
| 373 constructor.computeType(resolution); | 340 constructor.computeType(resolution); |
| 374 return constructor.functionSignature.parameterCount == 0; | 341 return constructor.functionSignature.parameterCount == 0; |
| 375 } | 342 } |
| 376 | 343 |
| 377 FunctionElement createForwardingConstructor(ConstructorElement target, | 344 FunctionElement createForwardingConstructor( |
| 378 ClassElement enclosing) { | 345 ConstructorElement target, ClassElement enclosing) { |
| 379 FunctionElement constructor = | 346 FunctionElement constructor = |
| 380 new SynthesizedConstructorElementX.notForDefault( | 347 new SynthesizedConstructorElementX.notForDefault( |
| 381 target.name, target, enclosing); | 348 target.name, target, enclosing); |
| 382 constructor.computeType(resolution); | 349 constructor.computeType(resolution); |
| 383 return constructor; | 350 return constructor; |
| 384 } | 351 } |
| 385 | 352 |
| 386 void doApplyMixinTo( | 353 void doApplyMixinTo(MixinApplicationElementX mixinApplication, |
| 387 MixinApplicationElementX mixinApplication, | 354 DartType supertype, DartType mixinType) { |
| 388 DartType supertype, | |
| 389 DartType mixinType) { | |
| 390 Node node = mixinApplication.parseNode(resolution.parsing); | 355 Node node = mixinApplication.parseNode(resolution.parsing); |
| 391 | 356 |
| 392 if (mixinApplication.supertype != null) { | 357 if (mixinApplication.supertype != null) { |
| 393 // [supertype] is not null if there was a cycle. | 358 // [supertype] is not null if there was a cycle. |
| 394 assert(invariant(node, compiler.compilationFailed)); | 359 assert(invariant(node, compiler.compilationFailed)); |
| 395 supertype = mixinApplication.supertype; | 360 supertype = mixinApplication.supertype; |
| 396 assert(invariant(node, supertype.isObject)); | 361 assert(invariant(node, supertype.isObject)); |
| 397 } else { | 362 } else { |
| 398 mixinApplication.supertype = supertype; | 363 mixinApplication.supertype = supertype; |
| 399 } | 364 } |
| 400 | 365 |
| 401 // Named mixin application may have an 'implements' clause. | 366 // Named mixin application may have an 'implements' clause. |
| 402 NamedMixinApplication namedMixinApplication = | 367 NamedMixinApplication namedMixinApplication = |
| 403 node.asNamedMixinApplication(); | 368 node.asNamedMixinApplication(); |
| 404 Link<DartType> interfaces = (namedMixinApplication != null) | 369 Link<DartType> interfaces = (namedMixinApplication != null) |
| 405 ? resolveInterfaces(namedMixinApplication.interfaces, | 370 ? resolveInterfaces( |
| 406 namedMixinApplication.superclass) | 371 namedMixinApplication.interfaces, namedMixinApplication.superclass) |
| 407 : const Link<DartType>(); | 372 : const Link<DartType>(); |
| 408 | 373 |
| 409 // The class that is the result of a mixin application implements | 374 // The class that is the result of a mixin application implements |
| 410 // the interface of the class that was mixed in so always prepend | 375 // the interface of the class that was mixed in so always prepend |
| 411 // that to the interface list. | 376 // that to the interface list. |
| 412 if (mixinApplication.interfaces == null) { | 377 if (mixinApplication.interfaces == null) { |
| 413 if (mixinType.isInterfaceType) { | 378 if (mixinType.isInterfaceType) { |
| 414 // Avoid malformed types in the interfaces. | 379 // Avoid malformed types in the interfaces. |
| 415 interfaces = interfaces.prepend(mixinType); | 380 interfaces = interfaces.prepend(mixinType); |
| 416 } | 381 } |
| 417 mixinApplication.interfaces = interfaces; | 382 mixinApplication.interfaces = interfaces; |
| 418 } else { | 383 } else { |
| 419 assert(invariant(mixinApplication, | 384 assert( |
| 420 mixinApplication.hasIncompleteHierarchy)); | 385 invariant(mixinApplication, mixinApplication.hasIncompleteHierarchy)); |
| 421 } | 386 } |
| 422 | 387 |
| 423 ClassElement superclass = supertype.element; | 388 ClassElement superclass = supertype.element; |
| 424 if (mixinType.kind != TypeKind.INTERFACE) { | 389 if (mixinType.kind != TypeKind.INTERFACE) { |
| 425 mixinApplication.hasIncompleteHierarchy = true; | 390 mixinApplication.hasIncompleteHierarchy = true; |
| 426 mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf; | 391 mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf; |
| 427 return; | 392 return; |
| 428 } | 393 } |
| 429 | 394 |
| 430 assert(mixinApplication.mixinType == null); | 395 assert(mixinApplication.mixinType == null); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 442 // application is in a different library than the constructor in the | 407 // application is in a different library than the constructor in the |
| 443 // super class and it is not possible to call that constructor from the | 408 // super class and it is not possible to call that constructor from the |
| 444 // library using the mixin application. | 409 // library using the mixin application. |
| 445 return; | 410 return; |
| 446 } | 411 } |
| 447 mixinApplication.addConstructor(forwarder); | 412 mixinApplication.addConstructor(forwarder); |
| 448 }); | 413 }); |
| 449 calculateAllSupertypes(mixinApplication); | 414 calculateAllSupertypes(mixinApplication); |
| 450 } | 415 } |
| 451 | 416 |
| 452 InterfaceType resolveMixinFor(MixinApplicationElement mixinApplication, | 417 InterfaceType resolveMixinFor( |
| 453 DartType mixinType) { | 418 MixinApplicationElement mixinApplication, DartType mixinType) { |
| 454 ClassElement mixin = mixinType.element; | 419 ClassElement mixin = mixinType.element; |
| 455 mixin.ensureResolved(resolution); | 420 mixin.ensureResolved(resolution); |
| 456 | 421 |
| 457 // Check for cycles in the mixin chain. | 422 // Check for cycles in the mixin chain. |
| 458 ClassElement previous = mixinApplication; // For better error messages. | 423 ClassElement previous = mixinApplication; // For better error messages. |
| 459 ClassElement current = mixin; | 424 ClassElement current = mixin; |
| 460 while (current != null && current.isMixinApplication) { | 425 while (current != null && current.isMixinApplication) { |
| 461 MixinApplicationElement currentMixinApplication = current; | 426 MixinApplicationElement currentMixinApplication = current; |
| 462 if (currentMixinApplication == mixinApplication) { | 427 if (currentMixinApplication == mixinApplication) { |
| 463 reporter.reportErrorMessage( | 428 reporter.reportErrorMessage( |
| 464 mixinApplication, | 429 mixinApplication, |
| 465 MessageKind.ILLEGAL_MIXIN_CYCLE, | 430 MessageKind.ILLEGAL_MIXIN_CYCLE, |
| 466 {'mixinName1': current.name, 'mixinName2': previous.name}); | 431 {'mixinName1': current.name, 'mixinName2': previous.name}); |
| 467 // We have found a cycle in the mixin chain. Return null as | 432 // We have found a cycle in the mixin chain. Return null as |
| 468 // the mixin for this application to avoid getting into | 433 // the mixin for this application to avoid getting into |
| (...skipping 14 matching lines...) Expand all Loading... |
| 483 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { | 448 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { |
| 484 DartType supertype = resolveType(superclass); | 449 DartType supertype = resolveType(superclass); |
| 485 if (supertype != null) { | 450 if (supertype != null) { |
| 486 if (supertype.isMalformed) { | 451 if (supertype.isMalformed) { |
| 487 reporter.reportErrorMessage( | 452 reporter.reportErrorMessage( |
| 488 superclass, | 453 superclass, |
| 489 MessageKind.CANNOT_EXTEND_MALFORMED, | 454 MessageKind.CANNOT_EXTEND_MALFORMED, |
| 490 {'className': element.name, 'malformedType': supertype}); | 455 {'className': element.name, 'malformedType': supertype}); |
| 491 return objectType; | 456 return objectType; |
| 492 } else if (supertype.isEnumType) { | 457 } else if (supertype.isEnumType) { |
| 493 reporter.reportErrorMessage( | 458 reporter.reportErrorMessage(superclass, MessageKind.CANNOT_EXTEND_ENUM, |
| 494 superclass, | |
| 495 MessageKind.CANNOT_EXTEND_ENUM, | |
| 496 {'className': element.name, 'enumType': supertype}); | 459 {'className': element.name, 'enumType': supertype}); |
| 497 return objectType; | 460 return objectType; |
| 498 } else if (!supertype.isInterfaceType) { | 461 } else if (!supertype.isInterfaceType) { |
| 499 reporter.reportErrorMessage( | 462 reporter.reportErrorMessage( |
| 500 superclass.typeName, | 463 superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); |
| 501 MessageKind.CLASS_NAME_EXPECTED); | |
| 502 return objectType; | 464 return objectType; |
| 503 } else if (isBlackListed(supertype)) { | 465 } else if (isBlackListed(supertype)) { |
| 504 reporter.reportErrorMessage( | 466 reporter.reportErrorMessage( |
| 505 superclass, | 467 superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); |
| 506 MessageKind.CANNOT_EXTEND, | |
| 507 {'type': supertype}); | |
| 508 return objectType; | 468 return objectType; |
| 509 } | 469 } |
| 510 } | 470 } |
| 511 return supertype; | 471 return supertype; |
| 512 } | 472 } |
| 513 | 473 |
| 514 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { | 474 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { |
| 515 Link<DartType> result = const Link<DartType>(); | 475 Link<DartType> result = const Link<DartType>(); |
| 516 if (interfaces == null) return result; | 476 if (interfaces == null) return result; |
| 517 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { | 477 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 537 reporter.reportErrorMessage( | 497 reporter.reportErrorMessage( |
| 538 superclass, | 498 superclass, |
| 539 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, | 499 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, |
| 540 {'type': interfaceType}); | 500 {'type': interfaceType}); |
| 541 reporter.reportErrorMessage( | 501 reporter.reportErrorMessage( |
| 542 link.head, | 502 link.head, |
| 543 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, | 503 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, |
| 544 {'type': interfaceType}); | 504 {'type': interfaceType}); |
| 545 } | 505 } |
| 546 if (result.contains(interfaceType)) { | 506 if (result.contains(interfaceType)) { |
| 547 reporter.reportErrorMessage( | 507 reporter.reportErrorMessage(link.head, |
| 548 link.head, | 508 MessageKind.DUPLICATE_IMPLEMENTS, {'type': interfaceType}); |
| 549 MessageKind.DUPLICATE_IMPLEMENTS, | |
| 550 {'type': interfaceType}); | |
| 551 } | 509 } |
| 552 result = result.prepend(interfaceType); | 510 result = result.prepend(interfaceType); |
| 553 if (isBlackListed(interfaceType)) { | 511 if (isBlackListed(interfaceType)) { |
| 554 reporter.reportErrorMessage( | 512 reporter.reportErrorMessage(link.head, MessageKind.CANNOT_IMPLEMENT, |
| 555 link.head, | |
| 556 MessageKind.CANNOT_IMPLEMENT, | |
| 557 {'type': interfaceType}); | 513 {'type': interfaceType}); |
| 558 } | 514 } |
| 559 } | 515 } |
| 560 } | 516 } |
| 561 } | 517 } |
| 562 return result; | 518 return result; |
| 563 } | 519 } |
| 564 | 520 |
| 565 /** | 521 /** |
| 566 * Compute the list of all supertypes. | 522 * Compute the list of all supertypes. |
| 567 * | 523 * |
| 568 * The elements of this list are ordered as follows: first the supertype that | 524 * The elements of this list are ordered as follows: first the supertype that |
| 569 * the class extends, then the implemented interfaces, and then the supertypes | 525 * the class extends, then the implemented interfaces, and then the supertypes |
| 570 * of these. The class [Object] appears only once, at the end of the list. | 526 * of these. The class [Object] appears only once, at the end of the list. |
| 571 * | 527 * |
| 572 * For example, for a class `class C extends S implements I1, I2`, we compute | 528 * For example, for a class `class C extends S implements I1, I2`, we compute |
| 573 * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1) | 529 * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1) |
| 574 * ++ supertypes(I2), | 530 * ++ supertypes(I2), |
| 575 * where ++ stands for list concatenation. | 531 * where ++ stands for list concatenation. |
| 576 * | 532 * |
| 577 * This order makes sure that if a class implements an interface twice with | 533 * This order makes sure that if a class implements an interface twice with |
| 578 * different type arguments, the type used in the most specific class comes | 534 * different type arguments, the type used in the most specific class comes |
| 579 * first. | 535 * first. |
| 580 */ | 536 */ |
| 581 void calculateAllSupertypes(BaseClassElementX cls) { | 537 void calculateAllSupertypes(BaseClassElementX cls) { |
| 582 if (cls.allSupertypesAndSelf != null) return; | 538 if (cls.allSupertypesAndSelf != null) return; |
| 583 final DartType supertype = cls.supertype; | 539 final DartType supertype = cls.supertype; |
| 584 if (supertype != null) { | 540 if (supertype != null) { |
| 585 cls.allSupertypesAndSelf = | 541 cls.allSupertypesAndSelf = new OrderedTypeSetBuilder(cls, |
| 586 new OrderedTypeSetBuilder( | 542 reporter: reporter, objectType: coreTypes.objectType) |
| 587 cls, reporter: reporter, objectType: coreTypes.objectType) | 543 .createOrderedTypeSet(supertype, cls.interfaces); |
| 588 .createOrderedTypeSet(supertype, cls.interfaces); | |
| 589 } else { | 544 } else { |
| 590 assert(cls == compiler.coreClasses.objectClass); | 545 assert(cls == compiler.coreClasses.objectClass); |
| 591 cls.allSupertypesAndSelf = | 546 cls.allSupertypesAndSelf = |
| 592 new OrderedTypeSet.singleton(cls.computeType(resolution)); | 547 new OrderedTypeSet.singleton(cls.computeType(resolution)); |
| 593 } | 548 } |
| 594 } | 549 } |
| 595 | 550 |
| 596 isBlackListed(DartType type) { | 551 isBlackListed(DartType type) { |
| 597 LibraryElement lib = element.library; | 552 LibraryElement lib = element.library; |
| 598 return | 553 return !identical(lib, compiler.coreLibrary) && |
| 599 !identical(lib, compiler.coreLibrary) && | 554 !compiler.backend.isBackendLibrary(lib) && |
| 600 !compiler.backend.isBackendLibrary(lib) && | 555 (type.isDynamic || |
| 601 (type.isDynamic || | 556 type == coreTypes.boolType || |
| 602 type == coreTypes.boolType || | 557 type == coreTypes.numType || |
| 603 type == coreTypes.numType || | 558 type == coreTypes.intType || |
| 604 type == coreTypes.intType || | 559 type == coreTypes.doubleType || |
| 605 type == coreTypes.doubleType || | 560 type == coreTypes.stringType || |
| 606 type == coreTypes.stringType || | 561 type == coreTypes.nullType); |
| 607 type == coreTypes.nullType); | |
| 608 } | 562 } |
| 609 } | 563 } |
| 610 | 564 |
| 611 class ClassSupertypeResolver extends CommonResolverVisitor { | 565 class ClassSupertypeResolver extends CommonResolverVisitor { |
| 612 Scope context; | 566 Scope context; |
| 613 ClassElement classElement; | 567 ClassElement classElement; |
| 614 | 568 |
| 615 ClassSupertypeResolver(Compiler compiler, ClassElement cls) | 569 ClassSupertypeResolver(Compiler compiler, ClassElement cls) |
| 616 : context = Scope.buildEnclosingScope(cls), | 570 : context = Scope.buildEnclosingScope(cls), |
| 617 this.classElement = cls, | 571 this.classElement = cls, |
| 618 super(compiler); | 572 super(compiler); |
| 619 | 573 |
| 620 CoreClasses get coreClasses => compiler.coreClasses; | 574 CoreClasses get coreClasses => compiler.coreClasses; |
| 621 | 575 |
| 622 void loadSupertype(ClassElement element, Node from) { | 576 void loadSupertype(ClassElement element, Node from) { |
| 623 if (!element.isResolved) { | 577 if (!element.isResolved) { |
| 624 compiler.resolver.loadSupertypes(element, from); | 578 compiler.resolver.loadSupertypes(element, from); |
| 625 element.ensureResolved(resolution); | 579 element.ensureResolved(resolution); |
| 626 } | 580 } |
| 627 } | 581 } |
| 628 | 582 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 Element element = lookupInScope(reporter, prefix, context, prefix.source); | 635 Element element = lookupInScope(reporter, prefix, context, prefix.source); |
| 682 if (element == null || !identical(element.kind, ElementKind.PREFIX)) { | 636 if (element == null || !identical(element.kind, ElementKind.PREFIX)) { |
| 683 reporter.reportErrorMessage( | 637 reporter.reportErrorMessage( |
| 684 node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); | 638 node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); |
| 685 return; | 639 return; |
| 686 } | 640 } |
| 687 PrefixElement prefixElement = element; | 641 PrefixElement prefixElement = element; |
| 688 Identifier selector = node.selector.asIdentifier(); | 642 Identifier selector = node.selector.asIdentifier(); |
| 689 var e = prefixElement.lookupLocalMember(selector.source); | 643 var e = prefixElement.lookupLocalMember(selector.source); |
| 690 if (e == null || !e.impliesType) { | 644 if (e == null || !e.impliesType) { |
| 691 reporter.reportErrorMessage( | 645 reporter.reportErrorMessage(node.selector, |
| 692 node.selector, | 646 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.selector}); |
| 693 MessageKind.CANNOT_RESOLVE_TYPE, | |
| 694 {'typeName': node.selector}); | |
| 695 return; | 647 return; |
| 696 } | 648 } |
| 697 loadSupertype(e, node); | 649 loadSupertype(e, node); |
| 698 } | 650 } |
| 699 } | 651 } |
| OLD | NEW |