Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: pkg/compiler/lib/src/resolution/members.dart

Issue 1152903003: Create SendStructure for unary and binary in resolution. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 AnalyzableElement get analyzedElement; 8 AnalyzableElement get analyzedElement;
9 Iterable<Node> get superUses; 9 Iterable<Node> get superUses;
10 10
(...skipping 2630 matching lines...) Expand 10 before | Expand all | Expand 10 after
2641 } 2641 }
2642 if (currentClass.supertype == null) { 2642 if (currentClass.supertype == null) {
2643 // This is just to guard against internal errors, so no need 2643 // This is just to guard against internal errors, so no need
2644 // for a real error message. 2644 // for a real error message.
2645 error(node.receiver, MessageKind.GENERIC, 2645 error(node.receiver, MessageKind.GENERIC,
2646 {'text': "Object has no superclass"}); 2646 {'text': "Object has no superclass"});
2647 return null; 2647 return null;
2648 } 2648 }
2649 // TODO(johnniwinther): Ensure correct behavior if currentClass is a 2649 // TODO(johnniwinther): Ensure correct behavior if currentClass is a
2650 // patch. 2650 // patch.
2651 target = currentClass.lookupSuperSelector(selector); 2651 target = currentClass.lookupSuperByName(selector.memberName);
2652 // [target] may be null which means invoking noSuchMethod on 2652 // [target] may be null which means invoking noSuchMethod on
2653 // super. 2653 // super.
2654 if (target == null) { 2654 if (target == null) {
2655 target = reportAndCreateErroneousElement( 2655 target = reportAndCreateErroneousElement(
2656 node, name, MessageKind.NO_SUCH_SUPER_MEMBER, 2656 node, name, MessageKind.NO_SUCH_SUPER_MEMBER,
2657 {'className': currentClass, 'memberName': name}); 2657 {'className': currentClass.name, 'memberName': name});
2658 // We still need to register the invocation, because we might 2658 // We still need to register the invocation, because we might
2659 // call [:super.noSuchMethod:] which calls 2659 // call [:super.noSuchMethod:] which calls
2660 // [JSInvocationMirror._invokeOn]. 2660 // [JSInvocationMirror._invokeOn].
2661 registry.registerDynamicInvocation(selector); 2661 registry.registerDynamicInvocation(selector);
2662 registry.registerSuperNoSuchMethod(); 2662 registry.registerSuperNoSuchMethod();
2663 } 2663 }
2664 } else if (resolvedReceiver == null || 2664 } else if (resolvedReceiver == null ||
2665 Elements.isUnresolved(resolvedReceiver.element)) { 2665 Elements.isUnresolved(resolvedReceiver.element)) {
2666 return null; 2666 return null;
2667 } else if (resolvedReceiver.element.isClass) { 2667 } else if (resolvedReceiver.element.isClass) {
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
2852 // This is a hack for the case of prefix.Type, we need to store 2852 // This is a hack for the case of prefix.Type, we need to store
2853 // the element on the selector, so [analyzeConstant] can build 2853 // the element on the selector, so [analyzeConstant] can build
2854 // the type literal from the selector. 2854 // the type literal from the selector.
2855 registry.useElement(node.selector, target); 2855 registry.useElement(node.selector, target);
2856 } 2856 }
2857 analyzeConstantDeferred(node.selector, enforceConst: false); 2857 analyzeConstantDeferred(node.selector, enforceConst: false);
2858 } 2858 }
2859 } 2859 }
2860 } 2860 }
2861 2861
2862 /// Check that access to `super` is currently allowed.
2863 bool checkSuperAccess(Node node) {
2864 registry.registerSuperUse(node);
karlklose 2015/05/26 08:23:32 Move this to after the checks?
Johnni Winther 2015/05/26 08:53:11 Done.
2865 if (!inInstanceContext) {
2866 compiler.reportError(node, MessageKind.NO_SUPER_AVAILABLE);
2867 return false;
2868 }
2869 if (currentClass.supertype == null) {
2870 // This is just to guard against internal errors, so no need
2871 // for a real error message.
2872 compiler.reportError(node, MessageKind.GENERIC,
2873 {'text': "Object has no superclass"});
2874 return false;
2875 }
2876 return true;
2877 }
2878
2879 /// Compute the [AccessSemantics] corresponding to a super access of [target].
2880 AccessSemantics computeSuperAccess(Spannable node, Element target) {
2881 if (target.isErroneous) {
2882 return new StaticAccess.unresolvedSuper(target);
2883 } else if (target.isGetter) {
2884 return new StaticAccess.superGetter(target);
2885 } else if (target.isSetter) {
2886 return new StaticAccess.superSetter(target);
2887 } else if (target.isField) {
2888 return new StaticAccess.superField(target);
2889 } else {
2890 assert(invariant(node, target.isFunction,
2891 message: "Unexpected super target '$target'."));
2892 return new StaticAccess.superMethod(target);
2893 }
2894 }
2895
2896 AccessSemantics computeSuperSemantics(Spannable node,
2897 Selector selector,
2898 {Name alternateName}) {
2899 Name name = selector.memberName;
2900 // TODO(johnniwinther): Ensure correct behavior if currentClass is a
2901 // patch.
2902 Element target = currentClass.lookupSuperByName(name);
2903 // [target] may be null which means invoking noSuchMethod on super.
2904 if (target == null) {
2905 Element error = reportAndCreateErroneousElement(
2906 node, name.text, MessageKind.NO_SUCH_SUPER_MEMBER,
2907 {'className': currentClass.name, 'memberName': name});
2908 if (alternateName != null) {
2909 target = currentClass.lookupSuperByName(alternateName);
2910 }
2911 if (target == null) {
2912 // If a setter wasn't resolved, use the [ErroneousElement].
2913 target = error;
2914 }
2915 // We still need to register the invocation, because we might
2916 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn].
2917 registry.registerDynamicInvocation(selector);
2918 registry.registerSuperNoSuchMethod();
2919 }
2920 return computeSuperAccess(node, target);
2921 }
2922
2923 ResolutionResult visitExpression(Node node) {
2924 bool oldSendIsMemberAccess = sendIsMemberAccess;
2925 sendIsMemberAccess = false;
2926 ResolutionResult result = visit(node);
2927 sendIsMemberAccess = oldSendIsMemberAccess;
2928 return result;
2929 }
2930
2931 ResolutionResult handleIs(Send node) {
2932 Node expression = node.receiver;
2933 visitExpression(expression);
2934
2935 // TODO(johnniwinther): Use seen type tests to avoid registration of
2936 // mutation/access to unpromoted variables.
2937
2938 Send notTypeNode = node.arguments.head.asSend();
2939 DartType type;
2940 SendStructure sendStructure;
2941 if (notTypeNode != null) {
2942 // `e is! T`.
2943 Node typeNode = notTypeNode.receiver;
2944 type = resolveTypeAnnotation(typeNode);
2945 sendStructure = new IsNotStructure(type);
2946 } else {
2947 // `e is T`.
2948 Node typeNode = node.arguments.head;
2949 type = resolveTypeAnnotation(typeNode);
2950 sendStructure = new IsStructure(type);
2951 }
2952 registry.registerIsCheck(type);
2953 registry.registerSendStructure(node, sendStructure);
2954 return null;
karlklose 2015/05/26 08:23:32 Not this change, but: I really do not like to retu
Johnni Winther 2015/05/26 08:53:11 Acknowledged.
2955 }
2956
2957 ResolutionResult handleAs(Send node) {
2958 Node expression = node.receiver;
2959 visitExpression(expression);
2960
2961 Node typeNode = node.arguments.head;
2962 DartType type = resolveTypeAnnotation(typeNode);
2963 registry.registerAsCheck(type);
2964 registry.registerSendStructure(node, new AsStructure(type));
2965 return null;
2966 }
2967
2968 ResolutionResult handleUnresolvedUnary(Send node, String text) {
2969 Node expression = node.receiver;
2970 if (node.isSuperCall) {
2971 checkSuperAccess(node);
2972 } else {
2973 visitExpression(expression);
2974 }
2975
2976 registry.registerSendStructure(node, const InvalidUnaryStructure());
2977 return null;
2978 }
2979
2980 ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) {
2981 Node expression = node.receiver;
2982 Selector selector = operator.selector;
2983 // TODO(johnniwinther): Remove this when all information goes through the
2984 // [SendStructure].
2985 registry.setSelector(node, selector);
2986
2987 AccessSemantics semantics;
2988 if (node.isSuperCall) {
2989 if (checkSuperAccess(node)) {
2990 semantics = computeSuperSemantics(node, selector);
2991 // TODO(johnniwinther): Add information to [AccessSemantics] about
2992 // whether it is erroneous.
2993 switch (semantics.kind) {
karlklose 2015/05/26 08:23:32 How about if (semantics.kind == AccessKind.SUPER_
Johnni Winther 2015/05/26 08:53:11 Done.
2994 case AccessKind.SUPER_METHOD:
2995 registry.registerStaticUse(semantics.element.declaration);
2996 break;
2997 default:
2998 }
2999 // TODO(johnniwinther): Remove this when all information goes through
3000 // the [SendStructure].
3001 registry.useElement(node, semantics.element);
3002 }
3003 } else {
3004 visitExpression(expression);
3005 semantics = new DynamicAccess.dynamicProperty(expression);
3006 registry.registerDynamicInvocation(selector);
3007 }
3008 if (semantics != null) {
3009 // TODO(johnniwinther): Support invalid super access as an
3010 // [AccessSemantics].
3011 registry.registerSendStructure(node,
3012 new UnaryStructure(semantics, operator));
3013 }
3014 return null;
3015 }
3016
3017 ResolutionResult handleNot(Send node, UnaryOperator operator) {
3018 assert(invariant(node, operator.kind == UnaryOperatorKind.NOT));
3019
3020 Node expression = node.receiver;
3021 visitExpression(expression);
3022 registry.registerSendStructure(node,
3023 new NotStructure(new DynamicAccess.dynamicProperty(expression)));
3024 return null;
3025 }
3026
3027 ResolutionResult handleLogicalAnd(Send node) {
3028 Node left = node.receiver;
3029 Node right = node.arguments.head;
3030 doInPromotionScope(left, () => visitExpression(left));
3031 doInPromotionScope(right, () => visitExpression(right));
3032 registry.registerSendStructure(node, const LogicalAndStructure());
3033 return null;
3034 }
3035
3036 ResolutionResult handleLogicalOr(Send node) {
3037 Node left = node.receiver;
3038 Node right = node.arguments.head;
3039 visitExpression(left);
3040 visitExpression(right);
3041 registry.registerSendStructure(node, const LogicalOrStructure());
3042 return null;
3043 }
3044
3045 ResolutionResult handleUnresolvedBinary(Send node, String text) {
3046 Node left = node.receiver;
3047 Node right = node.arguments.head;
3048 if (node.isSuperCall) {
3049 checkSuperAccess(node);
3050 } else {
3051 visitExpression(left);
3052 }
3053 visitExpression(right);
3054 registry.registerSendStructure(node, const InvalidBinaryStructure());
3055 return null;
3056 }
3057
3058 ResolutionResult handleUserDefinableBinary(Send node,
3059 BinaryOperator operator) {
3060 Node left = node.receiver;
3061 Node right = node.arguments.head;
3062 AccessSemantics semantics;
3063 Selector selector;
3064 if (operator.kind == BinaryOperatorKind.INDEX) {
3065 selector = new Selector.index();
3066 } else {
3067 selector = new Selector.binaryOperator(operator.selectorName);
3068 }
3069 // TODO(johnniwinther): Remove this when all information goes through the
3070 // [SendStructure].
3071 registry.setSelector(node, selector);
3072
3073 if (node.isSuperCall) {
3074 if (checkSuperAccess(node)) {
3075 semantics = computeSuperSemantics(node, selector);
3076 // TODO(johnniwinther): Add information to [AccessSemantics] about
3077 // whether it is erroneous.
3078 switch (semantics.kind) {
karlklose 2015/05/26 08:23:33 See comment for l. 2993.
Johnni Winther 2015/05/26 08:53:11 Done.
3079 case AccessKind.SUPER_METHOD:
3080 registry.registerStaticUse(semantics.element.declaration);
3081 break;
3082 default:
3083 }
3084 // TODO(johnniwinther): Remove this when all information goes through
3085 // the [SendStructure].
3086 registry.useElement(node, semantics.element);
3087
3088 }
3089 } else {
3090 visitExpression(left);
3091 registry.registerDynamicInvocation(selector);
3092 semantics = new DynamicAccess.dynamicProperty(left);
3093 }
3094 visitExpression(right);
3095
3096 if (semantics != null) {
3097 // TODO(johnniwinther): Support invalid super access as an
3098 // [AccessSemantics].
3099 SendStructure sendStructure;
3100 switch (operator.kind) {
3101 case BinaryOperatorKind.EQ:
3102 sendStructure = new EqualsStructure(semantics);
3103 break;
3104 case BinaryOperatorKind.NOT_EQ:
3105 sendStructure = new NotEqualsStructure(semantics);
3106 break;
3107 case BinaryOperatorKind.INDEX:
3108 sendStructure = new IndexStructure(semantics);
3109 break;
3110 case BinaryOperatorKind.ADD:
3111 case BinaryOperatorKind.SUB:
3112 case BinaryOperatorKind.MUL:
3113 case BinaryOperatorKind.DIV:
3114 case BinaryOperatorKind.IDIV:
3115 case BinaryOperatorKind.MOD:
3116 case BinaryOperatorKind.SHL:
3117 case BinaryOperatorKind.SHR:
3118 case BinaryOperatorKind.GTEQ:
3119 case BinaryOperatorKind.GT:
3120 case BinaryOperatorKind.LTEQ:
3121 case BinaryOperatorKind.LT:
3122 case BinaryOperatorKind.AND:
3123 case BinaryOperatorKind.OR:
3124 case BinaryOperatorKind.XOR:
3125 sendStructure = new BinaryStructure(semantics, operator);
3126 break;
3127 case BinaryOperatorKind.LOGICAL_AND:
3128 case BinaryOperatorKind.LOGICAL_OR:
3129 internalError(node, "Unexpected binary operator '${operator}'.");
3130 break;
3131 }
3132 registry.registerSendStructure(node, sendStructure);
3133 }
3134 return null;
3135 }
3136
2862 ResolutionResult visitSend(Send node) { 3137 ResolutionResult visitSend(Send node) {
3138 if (node.isOperator) {
3139 String operatorText = node.selector.asOperator().source;
3140 if (operatorText == 'is') {
3141 return handleIs(node);
3142 } else if (operatorText == 'as') {
3143 return handleAs(node);
3144 } else if (node.arguments.isEmpty) {
3145 UnaryOperator operator = UnaryOperator.parse(operatorText);
3146 if (operator == null) {
3147 return handleUnresolvedUnary(node, operatorText);
3148 } else {
3149 switch (operator.kind) {
3150 case UnaryOperatorKind.NOT:
3151 return handleNot(node, operator);
3152 case UnaryOperatorKind.COMPLEMENT:
3153 case UnaryOperatorKind.NEGATE:
3154 assert(invariant(node, operator.isUserDefinable,
3155 message: "Unexpected unary operator '${operator}'."));
3156 return handleUserDefinableUnary(node, operator);
3157 }
3158 return handleUserDefinableUnary(node, operator);
3159 }
3160 } else {
3161 BinaryOperator operator = BinaryOperator.parse(operatorText);
3162 if (operator == null) {
3163 return handleUnresolvedBinary(node, operatorText);
3164 } else {
3165 switch (operator.kind) {
3166 case BinaryOperatorKind.LOGICAL_AND:
3167 return handleLogicalAnd(node);
3168 case BinaryOperatorKind.LOGICAL_OR:
3169 return handleLogicalOr(node);
3170 case BinaryOperatorKind.EQ:
3171 case BinaryOperatorKind.NOT_EQ:
3172 case BinaryOperatorKind.INDEX:
3173 case BinaryOperatorKind.ADD:
3174 case BinaryOperatorKind.SUB:
3175 case BinaryOperatorKind.MUL:
3176 case BinaryOperatorKind.DIV:
3177 case BinaryOperatorKind.IDIV:
3178 case BinaryOperatorKind.MOD:
3179 case BinaryOperatorKind.SHL:
3180 case BinaryOperatorKind.SHR:
3181 case BinaryOperatorKind.GTEQ:
3182 case BinaryOperatorKind.GT:
3183 case BinaryOperatorKind.LTEQ:
3184 case BinaryOperatorKind.LT:
3185 case BinaryOperatorKind.AND:
3186 case BinaryOperatorKind.OR:
3187 case BinaryOperatorKind.XOR:
3188 return handleUserDefinableBinary(node, operator);
3189 }
3190 }
3191 }
3192 }
3193
2863 bool oldSendIsMemberAccess = sendIsMemberAccess; 3194 bool oldSendIsMemberAccess = sendIsMemberAccess;
2864 sendIsMemberAccess = node.isPropertyAccess || node.isCall; 3195 sendIsMemberAccess = node.isPropertyAccess || node.isCall;
2865 ResolutionResult result; 3196
2866 if (node.isLogicalAnd) { 3197 ResolutionResult result = resolveSend(node);
2867 result = doInPromotionScope(node.receiver, () => resolveSend(node));
2868 } else {
2869 result = resolveSend(node);
2870 }
2871 sendIsMemberAccess = oldSendIsMemberAccess; 3198 sendIsMemberAccess = oldSendIsMemberAccess;
2872 3199
2873 Element target = result != null ? result.element : null; 3200 Element target = result != null ? result.element : null;
2874 3201
2875 if (target != null 3202 if (target != null
2876 && target == compiler.mirrorSystemGetNameFunction 3203 && target == compiler.mirrorSystemGetNameFunction
2877 && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) { 3204 && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
2878 compiler.reportHint( 3205 compiler.reportHint(
2879 node.selector, MessageKind.STATIC_FUNCTION_BLOAT, 3206 node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
2880 {'class': compiler.mirrorSystemClass.name, 3207 {'class': compiler.mirrorSystemClass.name,
(...skipping 30 matching lines...) Expand all
2911 if (isPotentiallyMutableTarget(target)) { 3238 if (isPotentiallyMutableTarget(target)) {
2912 if (enclosingElement != target.enclosingElement) { 3239 if (enclosingElement != target.enclosingElement) {
2913 for (Node scope in promotionScope) { 3240 for (Node scope in promotionScope) {
2914 registry.setAccessedByClosureIn(scope, target, node); 3241 registry.setAccessedByClosureIn(scope, target, node);
2915 } 3242 }
2916 } 3243 }
2917 } 3244 }
2918 } 3245 }
2919 3246
2920 bool resolvedArguments = false; 3247 bool resolvedArguments = false;
2921 if (node.isOperator) { 3248 resolveArguments(node.argumentsNode);
2922 String operatorString = node.selector.asOperator().source;
2923 SendStructure sendStructure;
2924 if (operatorString == 'is') {
2925 // TODO(johnniwinther): Use seen type tests to avoid registration of
2926 // mutation/access to unpromoted variables.
2927 DartType type =
2928 resolveTypeAnnotation(node.typeAnnotationFromIsCheckOrCast);
2929 if (type != null) {
2930 sendStructure = node.isIsNotCheck
2931 ? new IsNotStructure(type) : new IsStructure(type);
2932 registry.registerIsCheck(type);
2933 }
2934 resolvedArguments = true;
2935 } else if (identical(operatorString, 'as')) {
2936 DartType type = resolveTypeAnnotation(node.arguments.head);
2937 if (type != null) {
2938 sendStructure = new AsStructure(type);
2939 registry.registerAsCheck(type);
2940 }
2941 resolvedArguments = true;
2942 } else if (identical(operatorString, '&&')) {
2943 doInPromotionScope(node.arguments.head,
2944 () => resolveArguments(node.argumentsNode));
2945 sendStructure = const LogicalAndStructure();
2946 resolvedArguments = true;
2947 } else if (operatorString == '||') {
2948 sendStructure = const LogicalOrStructure();
2949 }
2950 if (sendStructure != null) {
2951 registry.registerSendStructure(node, sendStructure);
2952 }
2953 }
2954
2955 if (!resolvedArguments) {
2956 resolveArguments(node.argumentsNode);
2957 }
2958 3249
2959 // If the selector is null, it means that we will not be generating 3250 // If the selector is null, it means that we will not be generating
2960 // code for this as a send. 3251 // code for this as a send.
2961 Selector selector = registry.getSelector(node); 3252 Selector selector = registry.getSelector(node);
2962 if (selector == null) return null; 3253 if (selector == null) return null;
2963 3254
2964 if (node.isCall) { 3255 if (node.isCall) {
2965 if (Elements.isUnresolved(target) || 3256 if (Elements.isUnresolved(target) ||
2966 target.isGetter || 3257 target.isGetter ||
2967 target.isField || 3258 target.isField ||
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
3117 Selector getterSelector; 3408 Selector getterSelector;
3118 if (selector.isSetter) { 3409 if (selector.isSetter) {
3119 getterSelector = new Selector.getterFrom(selector); 3410 getterSelector = new Selector.getterFrom(selector);
3120 } else { 3411 } else {
3121 assert(selector.isIndexSet); 3412 assert(selector.isIndexSet);
3122 getterSelector = new Selector.index(); 3413 getterSelector = new Selector.index();
3123 } 3414 }
3124 registerSend(getterSelector, getter); 3415 registerSend(getterSelector, getter);
3125 registry.setGetterSelectorInComplexSendSet(node, getterSelector); 3416 registry.setGetterSelectorInComplexSendSet(node, getterSelector);
3126 if (node.isSuperCall) { 3417 if (node.isSuperCall) {
3127 getter = currentClass.lookupSuperSelector(getterSelector); 3418 getter = currentClass.lookupSuperByName(getterSelector.memberName);
3128 if (getter == null) { 3419 if (getter == null) {
3129 target = reportAndCreateErroneousElement( 3420 target = reportAndCreateErroneousElement(
3130 node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER, 3421 node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
3131 {'className': currentClass, 'memberName': selector.name}); 3422 {'className': currentClass.name, 'memberName': selector.name});
3132 registry.registerSuperNoSuchMethod(); 3423 registry.registerSuperNoSuchMethod();
3133 } 3424 }
3134 } 3425 }
3135 registry.useElement(node.selector, getter); 3426 registry.useElement(node.selector, getter);
3136 3427
3137 // Make sure we include the + and - operators if we are using 3428 // Make sure we include the + and - operators if we are using
3138 // the ++ and -- ones. Also, if op= form is used, include op itself. 3429 // the ++ and -- ones. Also, if op= form is used, include op itself.
3139 void registerBinaryOperator(String name) { 3430 void registerBinaryOperator(String name) {
3140 Selector binop = new Selector.binaryOperator(name); 3431 Selector binop = new Selector.binaryOperator(name);
3141 registry.registerDynamicInvocation(binop); 3432 registry.registerDynamicInvocation(binop);
(...skipping 2059 matching lines...) Expand 10 before | Expand all | Expand 10 after
5201 } 5492 }
5202 5493
5203 /// The result for the resolution of the `assert` method. 5494 /// The result for the resolution of the `assert` method.
5204 class AssertResult implements ResolutionResult { 5495 class AssertResult implements ResolutionResult {
5205 const AssertResult(); 5496 const AssertResult();
5206 5497
5207 Element get element => null; 5498 Element get element => null;
5208 5499
5209 String toString() => 'AssertResult()'; 5500 String toString() => 'AssertResult()';
5210 } 5501 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698