OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of resolution; | 5 part of resolution; |
6 | 6 |
7 abstract class TreeElements { | 7 abstract class TreeElements { |
8 Element get currentElement; | 8 Element get currentElement; |
9 Set<Node> get superUses; | 9 Set<Node> get superUses; |
10 | 10 |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
295 return compiler.withCurrentElement(element, () { | 295 return compiler.withCurrentElement(element, () { |
296 FunctionExpression tree = element.parseNode(compiler); | 296 FunctionExpression tree = element.parseNode(compiler); |
297 if (tree.modifiers.isExternal()) { | 297 if (tree.modifiers.isExternal()) { |
298 error(tree, MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION); | 298 error(tree, MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION); |
299 return; | 299 return; |
300 } | 300 } |
301 if (isConstructor) { | 301 if (isConstructor) { |
302 if (tree.returnType != null) { | 302 if (tree.returnType != null) { |
303 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); | 303 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); |
304 } | 304 } |
305 resolveConstructorImplementation(element, tree); | |
306 } | 305 } |
307 ResolverVisitor visitor = visitorFor(element); | 306 ResolverVisitor visitor = visitorFor(element); |
308 visitor.useElement(tree, element); | 307 visitor.useElement(tree, element); |
309 visitor.setupFunction(tree, element); | 308 visitor.setupFunction(tree, element); |
310 | 309 |
311 if (isConstructor) { | 310 if (isConstructor) { |
312 // Even if there is no initializer list we still have to do the | 311 // Even if there is no initializer list we still have to do the |
313 // resolution in case there is an implicit super constructor call. | 312 // resolution in case there is an implicit super constructor call. |
314 InitializerResolver resolver = new InitializerResolver(visitor); | 313 InitializerResolver resolver = new InitializerResolver(visitor); |
315 FunctionElement redirection = | 314 FunctionElement redirection = |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 var mapping = new TreeElementMapping(element); | 349 var mapping = new TreeElementMapping(element); |
351 return new ResolverVisitor(compiler, element, mapping); | 350 return new ResolverVisitor(compiler, element, mapping); |
352 } | 351 } |
353 | 352 |
354 void visitBody(ResolverVisitor visitor, Statement body) { | 353 void visitBody(ResolverVisitor visitor, Statement body) { |
355 if (!compiler.analyzeSignaturesOnly) { | 354 if (!compiler.analyzeSignaturesOnly) { |
356 visitor.visit(body); | 355 visitor.visit(body); |
357 } | 356 } |
358 } | 357 } |
359 | 358 |
360 void resolveConstructorImplementation(FunctionElement constructor, | |
ahe
2013/05/03 13:57:34
YAY!
| |
361 FunctionExpression node) { | |
362 if (!identical(constructor.defaultImplementation, constructor)) return; | |
363 ClassElement intrface = constructor.getEnclosingClass(); | |
364 if (!intrface.isInterface()) return; | |
365 DartType defaultType = intrface.defaultClass; | |
366 if (defaultType == null) { | |
367 error(node, MessageKind.NO_DEFAULT_CLASS, | |
368 {'interfaceName': intrface.name}); | |
369 } | |
370 ClassElement defaultClass = defaultType.element; | |
371 defaultClass.ensureResolved(compiler); | |
372 assert(defaultClass.resolutionState == STATE_DONE); | |
373 assert(defaultClass.supertypeLoadState == STATE_DONE); | |
374 if (defaultClass.isInterface()) { | |
375 error(node, MessageKind.CANNOT_INSTANTIATE_INTERFACE, | |
376 {'interfaceName': defaultClass.name}); | |
377 } | |
378 // We have now established the following: | |
379 // [intrface] is an interface, let's say "MyInterface". | |
380 // [defaultClass] is a class, let's say "MyClass". | |
381 | |
382 Selector selector; | |
383 // If the default class implements the interface then we must use the | |
384 // default class' name. Otherwise we look for a factory with the name | |
385 // of the interface. | |
386 if (defaultClass.implementsInterface(intrface)) { | |
387 var constructorNameString = constructor.name.slowToString(); | |
388 // Create selector based on constructor.name but where interface | |
389 // is replaced with default class name. | |
390 // TODO(ahe): Don't use string manipulations here. | |
391 int classNameSeparatorIndex = constructorNameString.indexOf('\$'); | |
392 if (classNameSeparatorIndex < 0) { | |
393 selector = new Selector.callDefaultConstructor( | |
394 defaultClass.getLibrary()); | |
395 } else { | |
396 selector = new Selector.callConstructor( | |
397 new SourceString( | |
398 constructorNameString.substring(classNameSeparatorIndex + 1)), | |
399 defaultClass.getLibrary()); | |
400 } | |
401 constructor.defaultImplementation = | |
402 defaultClass.lookupConstructor(selector); | |
403 } else { | |
404 selector = | |
405 new Selector.callConstructor(constructor.name, | |
406 defaultClass.getLibrary()); | |
407 constructor.defaultImplementation = | |
408 defaultClass.lookupFactoryConstructor(selector); | |
409 } | |
410 if (constructor.defaultImplementation == null) { | |
411 // We failed to find a constructor named either | |
412 // "MyInterface.name" or "MyClass.name". | |
413 // TODO(aprelev@gmail.com): Use constructorNameForDiagnostics in | |
414 // the error message below. | |
415 error(node, | |
416 MessageKind.CANNOT_FIND_CONSTRUCTOR2, | |
417 {'constructorName': selector.name, 'className': defaultClass.name}); | |
418 } | |
419 } | |
420 | |
421 TreeElements resolveField(VariableElement element) { | 359 TreeElements resolveField(VariableElement element) { |
422 Node tree = element.parseNode(compiler); | 360 Node tree = element.parseNode(compiler); |
423 if(element.modifiers.isStatic() && element.variables.isTopLevel()) { | 361 if(element.modifiers.isStatic() && element.variables.isTopLevel()) { |
424 error(element.modifiers.getStatic(), | 362 error(element.modifiers.getStatic(), |
425 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); | 363 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); |
426 } | 364 } |
427 ResolverVisitor visitor = visitorFor(element); | 365 ResolverVisitor visitor = visitorFor(element); |
428 // TODO(johnniwinther): Avoid analyzing initializers if | 366 // TODO(johnniwinther): Avoid analyzing initializers if |
429 // [Compiler.analyzeSignaturesOnly] is set. | 367 // [Compiler.analyzeSignaturesOnly] is set. |
430 initializerDo(tree, visitor.visit); | 368 initializerDo(tree, visitor.visit); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
559 element.patch.ensureResolved(compiler); | 497 element.patch.ensureResolved(compiler); |
560 } | 498 } |
561 } else { // Handle patch classes: | 499 } else { // Handle patch classes: |
562 element.resolutionState = STATE_STARTED; | 500 element.resolutionState = STATE_STARTED; |
563 // Ensure handling origin before patch. | 501 // Ensure handling origin before patch. |
564 element.origin.ensureResolved(compiler); | 502 element.origin.ensureResolved(compiler); |
565 // Ensure that the type is computed. | 503 // Ensure that the type is computed. |
566 element.computeType(compiler); | 504 element.computeType(compiler); |
567 // Copy class hiearchy from origin. | 505 // Copy class hiearchy from origin. |
568 element.supertype = element.origin.supertype; | 506 element.supertype = element.origin.supertype; |
569 element.defaultClass = element.origin.defaultClass; | |
570 element.interfaces = element.origin.interfaces; | 507 element.interfaces = element.origin.interfaces; |
571 element.allSupertypes = element.origin.allSupertypes; | 508 element.allSupertypes = element.origin.allSupertypes; |
572 // Stepwise assignment to ensure invariant. | 509 // Stepwise assignment to ensure invariant. |
573 element.supertypeLoadState = STATE_STARTED; | 510 element.supertypeLoadState = STATE_STARTED; |
574 element.supertypeLoadState = STATE_DONE; | 511 element.supertypeLoadState = STATE_DONE; |
575 element.resolutionState = STATE_DONE; | 512 element.resolutionState = STATE_DONE; |
576 // TODO(johnniwinther): Check matching type variables and | 513 // TODO(johnniwinther): Check matching type variables and |
577 // empty extends/implements clauses. | 514 // empty extends/implements clauses. |
578 } | 515 } |
579 for (MetadataAnnotation metadata in element.metadata) { | 516 for (MetadataAnnotation metadata in element.metadata) { |
(...skipping 1987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2567 } | 2504 } |
2568 resolveSelector(node.send, constructor); | 2505 resolveSelector(node.send, constructor); |
2569 resolveArguments(node.send.argumentsNode); | 2506 resolveArguments(node.send.argumentsNode); |
2570 useElement(node.send, constructor); | 2507 useElement(node.send, constructor); |
2571 if (Elements.isUnresolved(constructor)) return constructor; | 2508 if (Elements.isUnresolved(constructor)) return constructor; |
2572 Selector callSelector = mapping.getSelector(node.send); | 2509 Selector callSelector = mapping.getSelector(node.send); |
2573 if (!callSelector.applies(constructor, compiler)) { | 2510 if (!callSelector.applies(constructor, compiler)) { |
2574 warnArgumentMismatch(node.send, constructor); | 2511 warnArgumentMismatch(node.send, constructor); |
2575 compiler.backend.registerThrowNoSuchMethod(mapping); | 2512 compiler.backend.registerThrowNoSuchMethod(mapping); |
2576 } | 2513 } |
2577 compiler.withCurrentElement(constructor, () { | |
2578 FunctionExpression tree = constructor.parseNode(compiler); | |
2579 compiler.resolver.resolveConstructorImplementation(constructor, tree); | |
2580 }); | |
2581 | 2514 |
2582 if (constructor.defaultImplementation != constructor) { | 2515 // [constructor] might be the implementation element |
2583 // Support for deprecated interface support. | |
2584 // TODO(ngeoffray): Remove once we remove such support. | |
2585 world.registerStaticUse(constructor.declaration); | |
2586 world.registerInstantiatedClass( | |
2587 constructor.getEnclosingClass().declaration, mapping); | |
2588 constructor = constructor.defaultImplementation; | |
2589 } | |
2590 // [constructor.defaultImplementation] might be the implementation element | |
2591 // and only declaration elements may be registered. | 2516 // and only declaration elements may be registered. |
2592 world.registerStaticUse(constructor.declaration); | 2517 world.registerStaticUse(constructor.declaration); |
2593 ClassElement cls = constructor.getEnclosingClass(); | 2518 ClassElement cls = constructor.getEnclosingClass(); |
2594 InterfaceType type = mapping.getType(node); | 2519 InterfaceType type = mapping.getType(node); |
2595 world.registerInstantiatedType(type, mapping); | 2520 world.registerInstantiatedType(type, mapping); |
2596 if (constructor.isFactoryConstructor() && !type.typeArguments.isEmpty) { | 2521 if (constructor.isFactoryConstructor() && !type.typeArguments.isEmpty) { |
2597 world.registerFactoryWithTypeArguments(mapping); | 2522 world.registerFactoryWithTypeArguments(mapping); |
2598 } | 2523 } |
2599 if (cls.isAbstract(compiler)) { | 2524 if (cls.isAbstract(compiler)) { |
2600 compiler.backend.registerAbstractClassInstantiation(mapping); | 2525 compiler.backend.registerAbstractClassInstantiation(mapping); |
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3230 superElement.ensureResolved(compiler); | 3155 superElement.ensureResolved(compiler); |
3231 } | 3156 } |
3232 element.supertype = superElement.computeType(compiler); | 3157 element.supertype = superElement.computeType(compiler); |
3233 } | 3158 } |
3234 } | 3159 } |
3235 | 3160 |
3236 assert(element.interfaces == null); | 3161 assert(element.interfaces == null); |
3237 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); | 3162 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); |
3238 calculateAllSupertypes(element); | 3163 calculateAllSupertypes(element); |
3239 | 3164 |
3240 if (node.defaultClause != null) { | |
3241 element.defaultClass = visit(node.defaultClause); | |
3242 } | |
3243 element.addDefaultConstructorIfNeeded(compiler); | 3165 element.addDefaultConstructorIfNeeded(compiler); |
3244 return element.computeType(compiler); | 3166 return element.computeType(compiler); |
3245 } | 3167 } |
3246 | 3168 |
3247 DartType visitNamedMixinApplication(NamedMixinApplication node) { | 3169 DartType visitNamedMixinApplication(NamedMixinApplication node) { |
3248 compiler.ensure(element != null); | 3170 compiler.ensure(element != null); |
3249 compiler.ensure(element.resolutionState == STATE_STARTED); | 3171 compiler.ensure(element.resolutionState == STATE_STARTED); |
3250 | 3172 |
3251 InterfaceType type = element.computeType(compiler); | 3173 InterfaceType type = element.computeType(compiler); |
3252 scope = new TypeDeclarationScope(scope, element); | 3174 scope = new TypeDeclarationScope(scope, element); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3325 // infinite recursion when traversing members. | 3247 // infinite recursion when traversing members. |
3326 return null; | 3248 return null; |
3327 } | 3249 } |
3328 previous = current; | 3250 previous = current; |
3329 current = currentMixinApplication.mixin; | 3251 current = currentMixinApplication.mixin; |
3330 } | 3252 } |
3331 compiler.world.registerMixinUse(mixinApplication, mixin); | 3253 compiler.world.registerMixinUse(mixinApplication, mixin); |
3332 return mixin; | 3254 return mixin; |
3333 } | 3255 } |
3334 | 3256 |
3335 // TODO(johnniwinther): Remove when default class is no longer supported. | |
3336 DartType visitTypeAnnotation(TypeAnnotation node) { | |
3337 return visit(node.typeName); | |
3338 } | |
3339 | |
3340 DartType resolveType(TypeAnnotation node) { | 3257 DartType resolveType(TypeAnnotation node) { |
3341 // TODO(johnniwinther): Report errors/warnings on resolution failures. | 3258 // TODO(johnniwinther): Report errors/warnings on resolution failures. |
3342 return typeResolver.resolveTypeAnnotation(this, node); | 3259 return typeResolver.resolveTypeAnnotation(this, node); |
3343 } | 3260 } |
3344 | 3261 |
3345 // TODO(johnniwinther): Remove when default class is no longer supported. | |
3346 DartType visitIdentifier(Identifier node) { | |
3347 Element element = scope.lookup(node.source); | |
3348 if (element == null) { | |
3349 error(node, MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node}); | |
3350 return null; | |
3351 } else if (!element.impliesType() && !element.isTypeVariable()) { | |
3352 error(node, MessageKind.NOT_A_TYPE, {'node': node}); | |
3353 return null; | |
3354 } else { | |
3355 if (element.isTypeVariable()) { | |
3356 TypeVariableElement variableElement = element; | |
3357 return variableElement.type; | |
3358 } else if (element.isTypedef()) { | |
3359 compiler.unimplemented('visitIdentifier for typedefs', node: node); | |
3360 } else { | |
3361 // TODO(ngeoffray): Use type variables. | |
3362 return element.computeType(compiler); | |
3363 } | |
3364 } | |
3365 return null; | |
3366 } | |
3367 | |
3368 // TODO(johnniwinther): Remove when default class is no longer supported. | |
3369 DartType visitSend(Send node) { | |
3370 Identifier prefix = node.receiver.asIdentifier(); | |
3371 if (prefix == null) { | |
3372 error(node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); | |
3373 return null; | |
3374 } | |
3375 Element element = scope.lookup(prefix.source); | |
3376 if (element == null || !identical(element.kind, ElementKind.PREFIX)) { | |
3377 error(node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); | |
3378 return null; | |
3379 } | |
3380 PrefixElement prefixElement = element; | |
3381 Identifier selector = node.selector.asIdentifier(); | |
3382 var e = prefixElement.lookupLocalMember(selector.source); | |
3383 if (e == null || !e.impliesType()) { | |
3384 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, | |
3385 {'typeName': node.selector}); | |
3386 return null; | |
3387 } | |
3388 return e.computeType(compiler); | |
3389 } | |
3390 | |
3391 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { | 3262 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { |
3392 DartType supertype = typeResolver.resolveTypeAnnotation( | 3263 DartType supertype = typeResolver.resolveTypeAnnotation( |
3393 this, superclass, onFailure: error); | 3264 this, superclass, onFailure: error); |
3394 if (supertype != null) { | 3265 if (supertype != null) { |
3395 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) { | 3266 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) { |
3396 // Error has already been reported. | 3267 // Error has already been reported. |
3397 return null; | 3268 return null; |
3398 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) { | 3269 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) { |
3399 // TODO(johnniwinther): Handle dynamic. | 3270 // TODO(johnniwinther): Handle dynamic. |
3400 error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); | 3271 error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); |
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3912 /// Finishes resolution of a constructor reference and records the | 3783 /// Finishes resolution of a constructor reference and records the |
3913 /// type of the constructed instance on [expression]. | 3784 /// type of the constructed instance on [expression]. |
3914 FunctionElement finishConstructorReference(Element e, | 3785 FunctionElement finishConstructorReference(Element e, |
3915 Node diagnosticNode, | 3786 Node diagnosticNode, |
3916 Node expression) { | 3787 Node expression) { |
3917 // Find the unnamed constructor if the reference resolved to a | 3788 // Find the unnamed constructor if the reference resolved to a |
3918 // class. | 3789 // class. |
3919 if (!Elements.isUnresolved(e) && e.isClass()) { | 3790 if (!Elements.isUnresolved(e) && e.isClass()) { |
3920 ClassElement cls = e; | 3791 ClassElement cls = e; |
3921 cls.ensureResolved(compiler); | 3792 cls.ensureResolved(compiler); |
3922 if (cls.isInterface() && (cls.defaultClass == null)) { | |
3923 // TODO(ahe): Remove this check and error message when we | |
3924 // don't have interfaces anymore. | |
3925 error(diagnosticNode, | |
3926 MessageKind.CANNOT_INSTANTIATE_INTERFACE, | |
3927 {'interfaceName': cls.name}); | |
3928 } | |
3929 // The unnamed constructor may not exist, so [e] may become unresolved. | 3793 // The unnamed constructor may not exist, so [e] may become unresolved. |
3930 e = lookupConstructor(cls, diagnosticNode, const SourceString('')); | 3794 e = lookupConstructor(cls, diagnosticNode, const SourceString('')); |
3931 } | 3795 } |
3932 if (type == null) { | 3796 if (type == null) { |
3933 if (Elements.isUnresolved(e)) { | 3797 if (Elements.isUnresolved(e)) { |
3934 type = compiler.dynamicClass.computeType(compiler); | 3798 type = compiler.dynamicClass.computeType(compiler); |
3935 } else { | 3799 } else { |
3936 type = e.getEnclosingClass().computeType(compiler).asRaw(); | 3800 type = e.getEnclosingClass().computeType(compiler).asRaw(); |
3937 } | 3801 } |
3938 } | 3802 } |
3939 resolver.mapping.setType(expression, type); | 3803 resolver.mapping.setType(expression, type); |
3940 return e; | 3804 return e; |
3941 } | 3805 } |
3942 | 3806 |
3943 visitTypeAnnotation(TypeAnnotation node) { | 3807 visitTypeAnnotation(TypeAnnotation node) { |
3944 assert(invariant(node, type == null)); | 3808 assert(invariant(node, type == null)); |
3945 type = resolver.resolveTypeRequired(node); | 3809 type = resolver.resolveTypeRequired(node); |
3946 return resolver.mapping[node]; | 3810 return resolver.mapping[node]; |
3947 } | 3811 } |
3948 | 3812 |
3949 visitSend(Send node) { | 3813 visitSend(Send node) { |
3950 Element e = visit(node.receiver); | 3814 Element e = visit(node.receiver); |
3951 if (Elements.isUnresolved(e)) return e; | 3815 if (Elements.isUnresolved(e)) return e; |
3952 Identifier name = node.selector.asIdentifier(); | 3816 Identifier name = node.selector.asIdentifier(); |
3953 if (name == null) internalError(node.selector, 'unexpected node'); | 3817 if (name == null) internalError(node.selector, 'unexpected node'); |
3954 | 3818 |
3955 if (identical(e.kind, ElementKind.CLASS)) { | 3819 if (identical(e.kind, ElementKind.CLASS)) { |
3956 ClassElement cls = e; | 3820 ClassElement cls = e; |
3957 cls.ensureResolved(compiler); | 3821 cls.ensureResolved(compiler); |
3958 if (cls.isInterface() && (cls.defaultClass == null)) { | |
3959 error(node.receiver, | |
3960 MessageKind.CANNOT_INSTANTIATE_INTERFACE, | |
3961 {'interfaceName': cls.name}); | |
3962 } | |
3963 return lookupConstructor(cls, name, name.source); | 3822 return lookupConstructor(cls, name, name.source); |
3964 } else if (identical(e.kind, ElementKind.PREFIX)) { | 3823 } else if (identical(e.kind, ElementKind.PREFIX)) { |
3965 PrefixElement prefix = e; | 3824 PrefixElement prefix = e; |
3966 e = prefix.lookupLocalMember(name.source); | 3825 e = prefix.lookupLocalMember(name.source); |
3967 if (e == null) { | 3826 if (e == null) { |
3968 return failOrReturnErroneousElement(resolver.enclosingElement, name, | 3827 return failOrReturnErroneousElement(resolver.enclosingElement, name, |
3969 name.source, | 3828 name.source, |
3970 MessageKind.CANNOT_RESOLVE, | 3829 MessageKind.CANNOT_RESOLVE, |
3971 {'name': name}); | 3830 {'name': name}); |
3972 } else if (!identical(e.kind, ElementKind.CLASS)) { | 3831 } else if (!identical(e.kind, ElementKind.CLASS)) { |
(...skipping 28 matching lines...) Expand all Loading... | |
4001 return e; | 3860 return e; |
4002 } | 3861 } |
4003 | 3862 |
4004 /// Assumed to be called by [resolveRedirectingFactory]. | 3863 /// Assumed to be called by [resolveRedirectingFactory]. |
4005 Element visitReturn(Return node) { | 3864 Element visitReturn(Return node) { |
4006 Node expression = node.expression; | 3865 Node expression = node.expression; |
4007 return finishConstructorReference(visit(expression), | 3866 return finishConstructorReference(visit(expression), |
4008 expression, expression); | 3867 expression, expression); |
4009 } | 3868 } |
4010 } | 3869 } |
OLD | NEW |