| 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 operator[](Node node); | 8 Element operator[](Node node); |
| 9 Selector getSelector(Send send); | 9 Selector getSelector(Send send); |
| 10 DartType getType(Node node); | 10 DartType getType(Node node); |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 } | 379 } |
| 380 return result; | 380 return result; |
| 381 } | 381 } |
| 382 | 382 |
| 383 /** | 383 /** |
| 384 * Load and resolve the supertypes of [cls]. | 384 * Load and resolve the supertypes of [cls]. |
| 385 * | 385 * |
| 386 * Warning: do not call this method directly. It should only be | 386 * Warning: do not call this method directly. It should only be |
| 387 * called by [resolveClass] and [ClassSupertypeResolver]. | 387 * called by [resolveClass] and [ClassSupertypeResolver]. |
| 388 */ | 388 */ |
| 389 void loadSupertypes(ClassElement cls, Node from) { | 389 void loadSupertypes(ClassElement cls, Spannable from) { |
| 390 compiler.withCurrentElement(cls, () => measure(() { | 390 compiler.withCurrentElement(cls, () => measure(() { |
| 391 if (cls.supertypeLoadState == STATE_DONE) return; | 391 if (cls.supertypeLoadState == STATE_DONE) return; |
| 392 if (cls.supertypeLoadState == STATE_STARTED) { | 392 if (cls.supertypeLoadState == STATE_STARTED) { |
| 393 compiler.reportMessage( | 393 compiler.reportMessage( |
| 394 compiler.spanFromSpannable(from), | 394 compiler.spanFromSpannable(from), |
| 395 MessageKind.CYCLIC_CLASS_HIERARCHY.error([cls.name]), | 395 MessageKind.CYCLIC_CLASS_HIERARCHY.error([cls.name]), |
| 396 Diagnostic.ERROR); | 396 Diagnostic.ERROR); |
| 397 cls.supertypeLoadState = STATE_DONE; | 397 cls.supertypeLoadState = STATE_DONE; |
| 398 cls.allSupertypes = const Link<DartType>().prepend( | 398 cls.allSupertypes = const Link<DartType>().prepend( |
| 399 compiler.objectClass.computeType(compiler)); | 399 compiler.objectClass.computeType(compiler)); |
| 400 // TODO(ahe): We should also set cls.supertype here to avoid | 400 // TODO(ahe): We should also set cls.supertype here to avoid |
| 401 // creating a malformed class hierarchy. | 401 // creating a malformed class hierarchy. |
| 402 return; | 402 return; |
| 403 } | 403 } |
| 404 cls.supertypeLoadState = STATE_STARTED; | 404 cls.supertypeLoadState = STATE_STARTED; |
| 405 compiler.withCurrentElement(cls, () { | 405 compiler.withCurrentElement(cls, () { |
| 406 // TODO(ahe): Cache the node in cls. | 406 // TODO(ahe): Cache the node in cls. |
| 407 cls.parseNode(compiler).accept(new ClassSupertypeResolver(compiler, | 407 cls.parseNode(compiler).accept( |
| 408 cls)); | 408 new ClassSupertypeResolver(compiler, cls)); |
| 409 if (cls.supertypeLoadState != STATE_DONE) { | 409 if (cls.supertypeLoadState != STATE_DONE) { |
| 410 cls.supertypeLoadState = STATE_DONE; | 410 cls.supertypeLoadState = STATE_DONE; |
| 411 } | 411 } |
| 412 }); | 412 }); |
| 413 })); | 413 })); |
| 414 } | 414 } |
| 415 | 415 |
| 416 // TODO(johnniwinther): Remove this queue when resolution has been split into | 416 // TODO(johnniwinther): Remove this queue when resolution has been split into |
| 417 // syntax and semantic resolution. | 417 // syntax and semantic resolution. |
| 418 ClassElement currentlyResolvedClass; | 418 ClassElement currentlyResolvedClass; |
| 419 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>(); | 419 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>(); |
| 420 | 420 |
| 421 void resolveMixinApplication(MixinApplicationElement element) { | |
| 422 // TODO(kasperl): Implement this. | |
| 423 assert(element.resolutionState == STATE_NOT_STARTED); | |
| 424 element.resolutionState = STATE_STARTED; | |
| 425 compiler.reportMessage( | |
| 426 compiler.spanFromSpannable(element.cachedNode), | |
| 427 MessageKind.GENERIC.error(['unimplemented mixin application']), | |
| 428 Diagnostic.ERROR); | |
| 429 element.resolutionState = STATE_DONE; | |
| 430 } | |
| 431 | |
| 432 /** | 421 /** |
| 433 * Resolve the class [element]. | 422 * Resolve the class [element]. |
| 434 * | 423 * |
| 435 * Before calling this method, [element] was constructed by the | 424 * Before calling this method, [element] was constructed by the |
| 436 * scanner and most fields are null or empty. This method fills in | 425 * scanner and most fields are null or empty. This method fills in |
| 437 * these fields and also ensure that the supertypes of [element] are | 426 * these fields and also ensure that the supertypes of [element] are |
| 438 * resolved. | 427 * resolved. |
| 439 * | 428 * |
| 440 * Warning: Do not call this method directly. Instead use | 429 * Warning: Do not call this method directly. Instead use |
| 441 * [:element.ensureResolved(compiler):]. | 430 * [:element.ensureResolved(compiler):]. |
| (...skipping 2299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2741 compiler.ensure(element != null); | 2730 compiler.ensure(element != null); |
| 2742 compiler.ensure(element.resolutionState == STATE_STARTED); | 2731 compiler.ensure(element.resolutionState == STATE_STARTED); |
| 2743 | 2732 |
| 2744 InterfaceType type = element.computeType(compiler); | 2733 InterfaceType type = element.computeType(compiler); |
| 2745 scope = new TypeDeclarationScope(scope, element); | 2734 scope = new TypeDeclarationScope(scope, element); |
| 2746 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. | 2735 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. |
| 2747 // As a side-effect, this may get us back here trying to | 2736 // As a side-effect, this may get us back here trying to |
| 2748 // resolve this class again. | 2737 // resolve this class again. |
| 2749 resolveTypeVariableBounds(node.typeParameters); | 2738 resolveTypeVariableBounds(node.typeParameters); |
| 2750 | 2739 |
| 2751 // Find super type. | 2740 // Resolve super type and deal with the Object class nicely. |
| 2752 DartType supertype = null; | 2741 element.supertype = resolveSupertype(element, node.superclass); |
| 2753 if (node.superclass != null) { | |
| 2754 supertype = typeResolver.resolveTypeAnnotation(node.superclass, scope, | |
| 2755 element, onFailure: error); | |
| 2756 } | |
| 2757 if (supertype != null) { | |
| 2758 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) { | |
| 2759 // Error has already been reported. | |
| 2760 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) { | |
| 2761 // TODO(johnniwinther): Handle dynamic. | |
| 2762 error(node.superclass.typeName, MessageKind.CLASS_NAME_EXPECTED, []); | |
| 2763 } else if (isBlackListed(supertype)) { | |
| 2764 error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]); | |
| 2765 } else { | |
| 2766 element.supertype = supertype; | |
| 2767 } | |
| 2768 } | |
| 2769 final objectElement = compiler.objectClass; | 2742 final objectElement = compiler.objectClass; |
| 2770 if (!identical(element, objectElement) && element.supertype == null) { | 2743 if (!identical(element, objectElement) && element.supertype == null) { |
| 2771 if (objectElement == null) { | 2744 if (objectElement == null) { |
| 2772 compiler.internalError("Internal error: cannot resolve Object", | 2745 compiler.internalError("Internal error: cannot resolve Object", |
| 2773 node: node); | 2746 node: node); |
| 2774 } else { | 2747 } else { |
| 2775 objectElement.ensureResolved(compiler); | 2748 objectElement.ensureResolved(compiler); |
| 2776 } | 2749 } |
| 2777 element.supertype = objectElement.computeType(compiler); | 2750 element.supertype = objectElement.computeType(compiler); |
| 2778 } | 2751 } |
| 2752 |
| 2779 assert(element.interfaces == null); | 2753 assert(element.interfaces == null); |
| 2780 Link<DartType> interfaces = const Link<DartType>(); | 2754 Link<DartType> interfaces = const Link<DartType>(); |
| 2781 for (Link<Node> link = node.interfaces.nodes; | 2755 for (Link<Node> link = node.interfaces.nodes; |
| 2782 !link.isEmpty; | 2756 !link.isEmpty; |
| 2783 link = link.tail) { | 2757 link = link.tail) { |
| 2784 DartType interfaceType = typeResolver.resolveTypeAnnotation( | 2758 DartType interfaceType = typeResolver.resolveTypeAnnotation( |
| 2785 link.head, scope, element, onFailure: error); | 2759 link.head, scope, element, onFailure: error); |
| 2786 if (interfaceType != null) { | 2760 if (interfaceType != null) { |
| 2787 if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) { | 2761 if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) { |
| 2788 // Error has already been reported. | 2762 // Error has already been reported. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2813 } | 2787 } |
| 2814 } | 2788 } |
| 2815 } | 2789 } |
| 2816 } | 2790 } |
| 2817 element.interfaces = interfaces; | 2791 element.interfaces = interfaces; |
| 2818 calculateAllSupertypes(element); | 2792 calculateAllSupertypes(element); |
| 2819 | 2793 |
| 2820 if (node.defaultClause != null) { | 2794 if (node.defaultClause != null) { |
| 2821 element.defaultClass = visit(node.defaultClause); | 2795 element.defaultClass = visit(node.defaultClause); |
| 2822 } | 2796 } |
| 2823 addDefaultConstructorIfNeeded(element); | 2797 element.addDefaultConstructorIfNeeded(compiler); |
| 2824 return element.computeType(compiler); | 2798 return element.computeType(compiler); |
| 2825 } | 2799 } |
| 2826 | 2800 |
| 2801 DartType visitMixinApplication(MixinApplication node) { |
| 2802 compiler.ensure(element != null); |
| 2803 compiler.ensure(element.resolutionState == STATE_STARTED); |
| 2804 |
| 2805 // Generate anonymous mixin application elements for the |
| 2806 // intermediate mixin applications (excluding the last). |
| 2807 DartType supertype = resolveSupertype(element, node.superclass); |
| 2808 Link<Node> link = node.mixins.nodes; |
| 2809 while (!link.tail.isEmpty) { |
| 2810 supertype = applyMixin(supertype, visit(link.head)); |
| 2811 link = link.tail; |
| 2812 } |
| 2813 doApplyMixinTo(element, supertype, visit(link.head)); |
| 2814 return element.computeType(compiler); |
| 2815 } |
| 2816 |
| 2817 DartType applyMixin(DartType supertype, DartType mixinType) { |
| 2818 String superName = supertype.name.slowToString(); |
| 2819 String mixinName = mixinType.name.slowToString(); |
| 2820 // TODO(kasperl): This is a little bit weird. Maybe we should |
| 2821 // restructure the parsed nodes for mixin applications to better |
| 2822 // match the nesting implied by the list of mixins so that each |
| 2823 // mixin application element could get it's own proper node. |
| 2824 MixinApplication fakeTree = element.parseNode(compiler); |
| 2825 ClassElement mixinApplication = new MixinApplicationElementX( |
| 2826 new SourceString("${superName}_${mixinName}"), |
| 2827 element.getCompilationUnit(), |
| 2828 compiler.getNextFreeClassId(), |
| 2829 fakeTree); |
| 2830 doApplyMixinTo(mixinApplication, supertype, mixinType); |
| 2831 mixinApplication.resolutionState = STATE_DONE; |
| 2832 return mixinApplication.computeType(compiler); |
| 2833 } |
| 2834 |
| 2835 void doApplyMixinTo(ClassElement mixinApplication, |
| 2836 DartType supertype, |
| 2837 DartType mixinType) { |
| 2838 assert(mixinApplication.supertype == null); |
| 2839 mixinApplication.supertype = supertype; |
| 2840 |
| 2841 assert(mixinApplication.interfaces == null); |
| 2842 mixinApplication.interfaces = const Link<DartType>(); |
| 2843 |
| 2844 assert(element.mixin == null); |
| 2845 mixinApplication.mixin = mixinType.element; |
| 2846 mixinApplication.mixin.ensureResolved(compiler); |
| 2847 mixinApplication.addDefaultConstructorIfNeeded(compiler); |
| 2848 calculateAllSupertypes(mixinApplication); |
| 2849 } |
| 2850 |
| 2851 |
| 2827 // TODO(johnniwinther): Remove when default class is no longer supported. | 2852 // TODO(johnniwinther): Remove when default class is no longer supported. |
| 2828 DartType visitTypeAnnotation(TypeAnnotation node) { | 2853 DartType visitTypeAnnotation(TypeAnnotation node) { |
| 2829 return visit(node.typeName); | 2854 return visit(node.typeName); |
| 2830 } | 2855 } |
| 2831 | 2856 |
| 2832 // TODO(johnniwinther): Remove when default class is no longer supported. | 2857 // TODO(johnniwinther): Remove when default class is no longer supported. |
| 2833 DartType visitIdentifier(Identifier node) { | 2858 DartType visitIdentifier(Identifier node) { |
| 2834 Element element = scope.lookup(node.source); | 2859 Element element = scope.lookup(node.source); |
| 2835 if (element == null) { | 2860 if (element == null) { |
| 2836 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); | 2861 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2867 PrefixElement prefixElement = element; | 2892 PrefixElement prefixElement = element; |
| 2868 Identifier selector = node.selector.asIdentifier(); | 2893 Identifier selector = node.selector.asIdentifier(); |
| 2869 var e = prefixElement.lookupLocalMember(selector.source); | 2894 var e = prefixElement.lookupLocalMember(selector.source); |
| 2870 if (e == null || !e.impliesType()) { | 2895 if (e == null || !e.impliesType()) { |
| 2871 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]); | 2896 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]); |
| 2872 return null; | 2897 return null; |
| 2873 } | 2898 } |
| 2874 return e.computeType(compiler); | 2899 return e.computeType(compiler); |
| 2875 } | 2900 } |
| 2876 | 2901 |
| 2902 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { |
| 2903 DartType supertype; |
| 2904 if (superclass != null) { |
| 2905 supertype = typeResolver.resolveTypeAnnotation( |
| 2906 superclass, scope, cls, onFailure: error); |
| 2907 } |
| 2908 if (supertype != null) { |
| 2909 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) { |
| 2910 // Error has already been reported. |
| 2911 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) { |
| 2912 // TODO(johnniwinther): Handle dynamic. |
| 2913 error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED, []); |
| 2914 return null; |
| 2915 } else if (isBlackListed(supertype)) { |
| 2916 error(superclass, MessageKind.CANNOT_EXTEND, [supertype]); |
| 2917 return null; |
| 2918 } |
| 2919 } |
| 2920 return supertype; |
| 2921 } |
| 2922 |
| 2877 void calculateAllSupertypes(ClassElement cls) { | 2923 void calculateAllSupertypes(ClassElement cls) { |
| 2878 // TODO(karlklose): check if type arguments match, if a classelement occurs | 2924 // TODO(karlklose): Check if type arguments match, if a class |
| 2879 // more than once in the supertypes. | 2925 // element occurs more than once in the supertypes. |
| 2880 if (cls.allSupertypes != null) return; | 2926 if (cls.allSupertypes != null) return; |
| 2881 final DartType supertype = cls.supertype; | 2927 final DartType supertype = cls.supertype; |
| 2882 if (supertype != null) { | 2928 if (supertype != null) { |
| 2883 var allSupertypes = new LinkBuilder<DartType>(); | 2929 var allSupertypes = new LinkBuilder<DartType>(); |
| 2884 addAllSupertypes(allSupertypes, supertype); | 2930 addAllSupertypes(allSupertypes, supertype); |
| 2885 for (Link<DartType> interfaces = cls.interfaces; | 2931 for (Link<DartType> interfaces = cls.interfaces; |
| 2886 !interfaces.isEmpty; | 2932 !interfaces.isEmpty; |
| 2887 interfaces = interfaces.tail) { | 2933 interfaces = interfaces.tail) { |
| 2888 addAllSupertypes(allSupertypes, interfaces.head); | 2934 addAllSupertypes(allSupertypes, interfaces.head); |
| 2889 } | 2935 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2907 assert(invariant(element, supertypes != null, | 2953 assert(invariant(element, supertypes != null, |
| 2908 message: "Supertypes not computed on $classElement " | 2954 message: "Supertypes not computed on $classElement " |
| 2909 "during resolution of $element")); | 2955 "during resolution of $element")); |
| 2910 while (!supertypes.isEmpty) { | 2956 while (!supertypes.isEmpty) { |
| 2911 DartType supertype = supertypes.head; | 2957 DartType supertype = supertypes.head; |
| 2912 builder.addLast(supertype.subst(typeArguments, typeVariables)); | 2958 builder.addLast(supertype.subst(typeArguments, typeVariables)); |
| 2913 supertypes = supertypes.tail; | 2959 supertypes = supertypes.tail; |
| 2914 } | 2960 } |
| 2915 } | 2961 } |
| 2916 | 2962 |
| 2917 /** | |
| 2918 * Add a synthetic nullary constructor if there are no other | |
| 2919 * constructors. | |
| 2920 */ | |
| 2921 void addDefaultConstructorIfNeeded(ClassElement element) { | |
| 2922 if (element.hasConstructor) return; | |
| 2923 FunctionElement constructor = | |
| 2924 new SynthesizedConstructorElementX.forDefault(element, compiler); | |
| 2925 element.addToScope(constructor, compiler); | |
| 2926 } | |
| 2927 | |
| 2928 isBlackListed(DartType type) { | 2963 isBlackListed(DartType type) { |
| 2929 LibraryElement lib = element.getLibrary(); | 2964 LibraryElement lib = element.getLibrary(); |
| 2930 return | 2965 return |
| 2931 !identical(lib, compiler.coreLibrary) && | 2966 !identical(lib, compiler.coreLibrary) && |
| 2932 !identical(lib, compiler.jsHelperLibrary) && | 2967 !identical(lib, compiler.jsHelperLibrary) && |
| 2933 !identical(lib, compiler.interceptorsLibrary) && | 2968 !identical(lib, compiler.interceptorsLibrary) && |
| 2934 (identical(type.element, compiler.dynamicClass) || | 2969 (identical(type.element, compiler.dynamicClass) || |
| 2935 identical(type.element, compiler.boolClass) || | 2970 identical(type.element, compiler.boolClass) || |
| 2936 identical(type.element, compiler.numClass) || | 2971 identical(type.element, compiler.numClass) || |
| 2937 identical(type.element, compiler.intClass) || | 2972 identical(type.element, compiler.intClass) || |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2949 ClassSupertypeResolver(Compiler compiler, ClassElement cls) | 2984 ClassSupertypeResolver(Compiler compiler, ClassElement cls) |
| 2950 : context = Scope.buildEnclosingScope(cls), | 2985 : context = Scope.buildEnclosingScope(cls), |
| 2951 this.classElement = cls, | 2986 this.classElement = cls, |
| 2952 super(compiler); | 2987 super(compiler); |
| 2953 | 2988 |
| 2954 void loadSupertype(ClassElement element, Node from) { | 2989 void loadSupertype(ClassElement element, Node from) { |
| 2955 compiler.resolver.loadSupertypes(element, from); | 2990 compiler.resolver.loadSupertypes(element, from); |
| 2956 element.ensureResolved(compiler); | 2991 element.ensureResolved(compiler); |
| 2957 } | 2992 } |
| 2958 | 2993 |
| 2994 void visitNodeList(NodeList node) { |
| 2995 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { |
| 2996 link.head.accept(this); |
| 2997 } |
| 2998 } |
| 2999 |
| 2959 void visitClassNode(ClassNode node) { | 3000 void visitClassNode(ClassNode node) { |
| 2960 if (node.superclass == null) { | 3001 if (node.superclass == null) { |
| 2961 if (!identical(classElement, compiler.objectClass)) { | 3002 if (!identical(classElement, compiler.objectClass)) { |
| 2962 loadSupertype(compiler.objectClass, node); | 3003 loadSupertype(compiler.objectClass, node); |
| 2963 } | 3004 } |
| 2964 } else { | 3005 } else { |
| 2965 node.superclass.accept(this); | 3006 node.superclass.accept(this); |
| 2966 } | 3007 } |
| 2967 for (Link<Node> link = node.interfaces.nodes; | 3008 visitNodeList(node.interfaces); |
| 2968 !link.isEmpty; | 3009 } |
| 2969 link = link.tail) { | 3010 |
| 2970 link.head.accept(this); | 3011 void visitMixinApplication(MixinApplication node) { |
| 2971 } | 3012 node.superclass.accept(this); |
| 3013 visitNodeList(node.mixins); |
| 2972 } | 3014 } |
| 2973 | 3015 |
| 2974 void visitTypeAnnotation(TypeAnnotation node) { | 3016 void visitTypeAnnotation(TypeAnnotation node) { |
| 2975 node.typeName.accept(this); | 3017 node.typeName.accept(this); |
| 2976 } | 3018 } |
| 2977 | 3019 |
| 2978 void visitIdentifier(Identifier node) { | 3020 void visitIdentifier(Identifier node) { |
| 2979 Element element = context.lookup(node.source); | 3021 Element element = context.lookup(node.source); |
| 2980 if (element == null) { | 3022 if (element == null) { |
| 2981 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); | 3023 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3408 return e; | 3450 return e; |
| 3409 } | 3451 } |
| 3410 | 3452 |
| 3411 /// Assumed to be called by [resolveRedirectingFactory]. | 3453 /// Assumed to be called by [resolveRedirectingFactory]. |
| 3412 Element visitReturn(Return node) { | 3454 Element visitReturn(Return node) { |
| 3413 Node expression = node.expression; | 3455 Node expression = node.expression; |
| 3414 return finishConstructorReference(visit(expression), | 3456 return finishConstructorReference(visit(expression), |
| 3415 expression, expression); | 3457 expression, expression); |
| 3416 } | 3458 } |
| 3417 } | 3459 } |
| OLD | NEW |