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

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

Issue 1078873003: Report compile-time error if using `this` implicitly in initializers (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/compiler/lib/src/warnings.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2094 matching lines...) Expand 10 before | Expand all | Expand 10 after
2105 * Do not subclass or instantiate this class outside this library 2105 * Do not subclass or instantiate this class outside this library
2106 * except for testing. 2106 * except for testing.
2107 */ 2107 */
2108 class ResolverVisitor extends MappingVisitor<ResolutionResult> { 2108 class ResolverVisitor extends MappingVisitor<ResolutionResult> {
2109 /** 2109 /**
2110 * The current enclosing element for the visited AST nodes. 2110 * The current enclosing element for the visited AST nodes.
2111 * 2111 *
2112 * This field is updated when nested closures are visited. 2112 * This field is updated when nested closures are visited.
2113 */ 2113 */
2114 Element enclosingElement; 2114 Element enclosingElement;
2115
2116 /// Whether we are in a context where `this` is accessible (this will be false
2117 /// in static contexts, factory methods, and field initializers).
2115 bool inInstanceContext; 2118 bool inInstanceContext;
2116 bool inCheckContext; 2119 bool inCheckContext;
2117 bool inCatchBlock; 2120 bool inCatchBlock;
2118 2121
2119 Scope scope; 2122 Scope scope;
2120 ClassElement currentClass; 2123 ClassElement currentClass;
2121 ExpressionStatement currentExpressionStatement; 2124 ExpressionStatement currentExpressionStatement;
2122 bool sendIsMemberAccess = false; 2125 bool sendIsMemberAccess = false;
2123 StatementScope statementScope; 2126 StatementScope statementScope;
2124 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION 2127 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
2255 promotionScope = promotionScope.prepend(node); 2258 promotionScope = promotionScope.prepend(node);
2256 var result = action(); 2259 var result = action();
2257 promotionScope = promotionScope.tail; 2260 promotionScope = promotionScope.tail;
2258 return result; 2261 return result;
2259 } 2262 }
2260 2263
2261 visitInStaticContext(Node node) { 2264 visitInStaticContext(Node node) {
2262 inStaticContext(() => visit(node)); 2265 inStaticContext(() => visit(node));
2263 } 2266 }
2264 2267
2265 ErroneousElement warnAndCreateErroneousElement(Node node, 2268 ErroneousElement reportAndCreateErroneousElement(
2266 String name, 2269 Node node,
2267 MessageKind kind, 2270 String name,
2268 [Map arguments = const {}]) { 2271 MessageKind kind,
2269 compiler.reportWarning(node, kind, arguments); 2272 Map arguments,
2273 {bool isError: false}) {
2274 if (isError) {
2275 compiler.reportError(node, kind, arguments);
2276 } else {
2277 compiler.reportWarning(node, kind, arguments);
2278 }
2270 // TODO(ahe): Use [allowedCategory] to synthesize a more precise subclass 2279 // TODO(ahe): Use [allowedCategory] to synthesize a more precise subclass
2271 // of [ErroneousElementX]. For example, [ErroneousFieldElementX], 2280 // of [ErroneousElementX]. For example, [ErroneousFieldElementX],
2272 // [ErroneousConstructorElementX], etc. 2281 // [ErroneousConstructorElementX], etc.
2273 return new ErroneousElementX(kind, arguments, name, enclosingElement); 2282 return new ErroneousElementX(kind, arguments, name, enclosingElement);
2274 } 2283 }
2275 2284
2276 ResolutionResult visitIdentifier(Identifier node) { 2285 ResolutionResult visitIdentifier(Identifier node) {
2277 if (node.isThis()) { 2286 if (node.isThis()) {
2278 if (!inInstanceContext) { 2287 if (!inInstanceContext) {
2279 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node}); 2288 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node});
(...skipping 13 matching lines...) Expand all
2293 if (Elements.isUnresolved(element) && name == 'dynamic') { 2302 if (Elements.isUnresolved(element) && name == 'dynamic') {
2294 // TODO(johnniwinther): Remove this hack when we can return more complex 2303 // TODO(johnniwinther): Remove this hack when we can return more complex
2295 // objects than [Element] from this method. 2304 // objects than [Element] from this method.
2296 element = compiler.typeClass; 2305 element = compiler.typeClass;
2297 // Set the type to be `dynamic` to mark that this is a type literal. 2306 // Set the type to be `dynamic` to mark that this is a type literal.
2298 registry.setType(node, const DynamicType()); 2307 registry.setType(node, const DynamicType());
2299 } 2308 }
2300 element = reportLookupErrorIfAny(element, node, node.source); 2309 element = reportLookupErrorIfAny(element, node, node.source);
2301 if (element == null) { 2310 if (element == null) {
2302 if (!inInstanceContext) { 2311 if (!inInstanceContext) {
2303 element = warnAndCreateErroneousElement( 2312 // We report an error within initializers because `this` is implicitly
2304 node, node.source, MessageKind.CANNOT_RESOLVE, 2313 // accessed when unqualified identifiers are not resolved. For
2305 {'name': node}); 2314 // details, see section 16.14.3 of the spec (2nd edition):
2315 // An unqualified invocation `i` of the form `id(a1, ...)`
2316 // ...
2317 // If `i` does not occur inside a top level or static function, `i`
2318 // is equivalent to `this.id(a1 , ...)`.
2319 bool inInitializer = enclosingElement.isGenerativeConstructor ||
2320 (enclosingElement.isInstanceMember && enclosingElement.isField);
2321 MessageKind kind = inInitializer
2322 ? MessageKind.CANNOT_RESOLVE_IN_INITIALIZER
2323 : MessageKind.CANNOT_RESOLVE;
2324 element = reportAndCreateErroneousElement(node, node.source, kind,
2325 {'name': node.source}, isError: inInitializer);
2306 registry.registerThrowNoSuchMethod(); 2326 registry.registerThrowNoSuchMethod();
2307 } 2327 }
2308 } else if (element.isErroneous) { 2328 } else if (element.isErroneous) {
2309 // Use the erroneous element. 2329 // Use the erroneous element.
2310 } else { 2330 } else {
2311 if ((element.kind.category & allowedCategory) == 0) { 2331 if ((element.kind.category & allowedCategory) == 0) {
2312 element = warnAndCreateErroneousElement( 2332 element = reportAndCreateErroneousElement(
2313 node, name, 2333 node, name, MessageKind.GENERIC,
2314 MessageKind.GENERIC,
2315 // TODO(ahe): Improve error message. Need UX input. 2334 // TODO(ahe): Improve error message. Need UX input.
2316 {'text': "is not an expression $element"}); 2335 {'text': "is not an expression $element"});
2317 } 2336 }
2318 } 2337 }
2319 if (!Elements.isUnresolved(element) && element.isClass) { 2338 if (!Elements.isUnresolved(element) && element.isClass) {
2320 ClassElement classElement = element; 2339 ClassElement classElement = element;
2321 classElement.ensureResolved(compiler); 2340 classElement.ensureResolved(compiler);
2322 } 2341 }
2323 return new ElementResult(registry.useElement(node, element)); 2342 return new ElementResult(registry.useElement(node, element));
2324 } 2343 }
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
2594 error(node.receiver, MessageKind.GENERIC, 2613 error(node.receiver, MessageKind.GENERIC,
2595 {'text': "Object has no superclass"}); 2614 {'text': "Object has no superclass"});
2596 return null; 2615 return null;
2597 } 2616 }
2598 // TODO(johnniwinther): Ensure correct behavior if currentClass is a 2617 // TODO(johnniwinther): Ensure correct behavior if currentClass is a
2599 // patch. 2618 // patch.
2600 target = currentClass.lookupSuperSelector(selector); 2619 target = currentClass.lookupSuperSelector(selector);
2601 // [target] may be null which means invoking noSuchMethod on 2620 // [target] may be null which means invoking noSuchMethod on
2602 // super. 2621 // super.
2603 if (target == null) { 2622 if (target == null) {
2604 target = warnAndCreateErroneousElement( 2623 target = reportAndCreateErroneousElement(
2605 node, name, MessageKind.NO_SUCH_SUPER_MEMBER, 2624 node, name, MessageKind.NO_SUCH_SUPER_MEMBER,
2606 {'className': currentClass, 'memberName': name}); 2625 {'className': currentClass, 'memberName': name});
2607 // We still need to register the invocation, because we might 2626 // We still need to register the invocation, because we might
2608 // call [:super.noSuchMethod:] which calls 2627 // call [:super.noSuchMethod:] which calls
2609 // [JSInvocationMirror._invokeOn]. 2628 // [JSInvocationMirror._invokeOn].
2610 registry.registerDynamicInvocation(selector); 2629 registry.registerDynamicInvocation(selector);
2611 registry.registerSuperNoSuchMethod(); 2630 registry.registerSuperNoSuchMethod();
2612 } 2631 }
2613 } else if (resolvedReceiver == null || 2632 } else if (resolvedReceiver == null ||
2614 Elements.isUnresolved(resolvedReceiver.element)) { 2633 Elements.isUnresolved(resolvedReceiver.element)) {
(...skipping 18 matching lines...) Expand all
2633 // TODO(johnniwinther): With the simplified [TreeElements] invariant, 2652 // TODO(johnniwinther): With the simplified [TreeElements] invariant,
2634 // try to resolve injected elements if [currentClass] is in the patch 2653 // try to resolve injected elements if [currentClass] is in the patch
2635 // library of [receiverClass]. 2654 // library of [receiverClass].
2636 2655
2637 // TODO(karlklose): this should be reported by the caller of 2656 // TODO(karlklose): this should be reported by the caller of
2638 // [resolveSend] to select better warning messages for getters and 2657 // [resolveSend] to select better warning messages for getters and
2639 // setters. 2658 // setters.
2640 MessageKind kind = (target == null) 2659 MessageKind kind = (target == null)
2641 ? MessageKind.MEMBER_NOT_FOUND 2660 ? MessageKind.MEMBER_NOT_FOUND
2642 : MessageKind.MEMBER_NOT_STATIC; 2661 : MessageKind.MEMBER_NOT_STATIC;
2643 return new ElementResult(warnAndCreateErroneousElement( 2662 return new ElementResult(reportAndCreateErroneousElement(
2644 node, name, kind, 2663 node, name, kind,
2645 {'className': receiverClass.name, 'memberName': name})); 2664 {'className': receiverClass.name, 'memberName': name}));
2646 } else if (isPrivateName(name) && 2665 } else if (isPrivateName(name) &&
2647 target.library != enclosingElement.library) { 2666 target.library != enclosingElement.library) {
2648 registry.registerThrowNoSuchMethod(); 2667 registry.registerThrowNoSuchMethod();
2649 return new ElementResult(warnAndCreateErroneousElement( 2668 return new ElementResult(reportAndCreateErroneousElement(
2650 node, name, MessageKind.PRIVATE_ACCESS, 2669 node, name, MessageKind.PRIVATE_ACCESS,
2651 {'libraryName': target.library.getLibraryOrScriptName(), 2670 {'libraryName': target.library.getLibraryOrScriptName(),
2652 'name': name})); 2671 'name': name}));
2653 } 2672 }
2654 } else if (resolvedReceiver.element.isPrefix) { 2673 } else if (resolvedReceiver.element.isPrefix) {
2655 PrefixElement prefix = resolvedReceiver.element; 2674 PrefixElement prefix = resolvedReceiver.element;
2656 target = prefix.lookupLocalMember(name); 2675 target = prefix.lookupLocalMember(name);
2657 if (Elements.isUnresolved(target)) { 2676 if (Elements.isUnresolved(target)) {
2658 registry.registerThrowNoSuchMethod(); 2677 registry.registerThrowNoSuchMethod();
2659 return new ElementResult(warnAndCreateErroneousElement( 2678 return new ElementResult(reportAndCreateErroneousElement(
2660 node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER, 2679 node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER,
2661 {'libraryName': prefix.name, 'memberName': name})); 2680 {'libraryName': prefix.name, 'memberName': name}));
2662 } else if (target.isAmbiguous) { 2681 } else if (target.isAmbiguous) {
2663 registry.registerThrowNoSuchMethod(); 2682 registry.registerThrowNoSuchMethod();
2664 AmbiguousElement ambiguous = target; 2683 AmbiguousElement ambiguous = target;
2665 target = warnAndCreateErroneousElement(node, name, 2684 target = reportAndCreateErroneousElement(
2666 ambiguous.messageKind, 2685 node, name, ambiguous.messageKind, ambiguous.messageArguments);
2667 ambiguous.messageArguments);
2668 ambiguous.diagnose(enclosingElement, compiler); 2686 ambiguous.diagnose(enclosingElement, compiler);
2669 return new ElementResult(target); 2687 return new ElementResult(target);
2670 } else if (target.kind == ElementKind.CLASS) { 2688 } else if (target.kind == ElementKind.CLASS) {
2671 ClassElement classElement = target; 2689 ClassElement classElement = target;
2672 classElement.ensureResolved(compiler); 2690 classElement.ensureResolved(compiler);
2673 } 2691 }
2674 } 2692 }
2675 return new ElementResult(target); 2693 return new ElementResult(target);
2676 } 2694 }
2677 2695
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2798 } 2816 }
2799 2817
2800 if (target != null) { 2818 if (target != null) {
2801 if (target.isErroneous) { 2819 if (target.isErroneous) {
2802 registry.registerThrowNoSuchMethod(); 2820 registry.registerThrowNoSuchMethod();
2803 } else if (target.isAbstractField) { 2821 } else if (target.isAbstractField) {
2804 AbstractFieldElement field = target; 2822 AbstractFieldElement field = target;
2805 target = field.getter; 2823 target = field.getter;
2806 if (target == null && !inInstanceContext) { 2824 if (target == null && !inInstanceContext) {
2807 registry.registerThrowNoSuchMethod(); 2825 registry.registerThrowNoSuchMethod();
2808 target = 2826 target = reportAndCreateErroneousElement(node.selector, field.name,
2809 warnAndCreateErroneousElement(node.selector, field.name, 2827 MessageKind.CANNOT_RESOLVE_GETTER, const {});
2810 MessageKind.CANNOT_RESOLVE_GETTER);
2811 } 2828 }
2812 } else if (target.isTypeVariable) { 2829 } else if (target.isTypeVariable) {
2813 ClassElement cls = target.enclosingClass; 2830 ClassElement cls = target.enclosingClass;
2814 assert(enclosingElement.enclosingClass == cls); 2831 assert(enclosingElement.enclosingClass == cls);
2815 if (Elements.isInStaticContext(enclosingElement)) { 2832 if (Elements.isInStaticContext(enclosingElement)) {
2816 compiler.reportError(node, 2833 compiler.reportError(node,
2817 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, 2834 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
2818 {'typeVariableName': node.selector}); 2835 {'typeVariableName': node.selector});
2819 } 2836 }
2820 registry.registerClassUsingVariableExpression(cls); 2837 registry.registerClassUsingVariableExpression(cls);
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
2974 Element getter = target; 2991 Element getter = target;
2975 String operatorName = node.assignmentOperator.source; 2992 String operatorName = node.assignmentOperator.source;
2976 String source = operatorName; 2993 String source = operatorName;
2977 bool isComplex = !identical(source, '='); 2994 bool isComplex = !identical(source, '=');
2978 if (!(result is AssertResult || Elements.isUnresolved(target))) { 2995 if (!(result is AssertResult || Elements.isUnresolved(target))) {
2979 if (target.isAbstractField) { 2996 if (target.isAbstractField) {
2980 AbstractFieldElement field = target; 2997 AbstractFieldElement field = target;
2981 setter = field.setter; 2998 setter = field.setter;
2982 getter = field.getter; 2999 getter = field.getter;
2983 if (setter == null && !inInstanceContext) { 3000 if (setter == null && !inInstanceContext) {
2984 setter = warnAndCreateErroneousElement( 3001 setter = reportAndCreateErroneousElement(node.selector, field.name,
2985 node.selector, field.name, MessageKind.CANNOT_RESOLVE_SETTER); 3002 MessageKind.CANNOT_RESOLVE_SETTER, const {});
2986 registry.registerThrowNoSuchMethod(); 3003 registry.registerThrowNoSuchMethod();
2987 } 3004 }
2988 if (isComplex && getter == null && !inInstanceContext) { 3005 if (isComplex && getter == null && !inInstanceContext) {
2989 getter = warnAndCreateErroneousElement( 3006 getter = reportAndCreateErroneousElement(node.selector, field.name,
2990 node.selector, field.name, MessageKind.CANNOT_RESOLVE_GETTER); 3007 MessageKind.CANNOT_RESOLVE_GETTER, const {});
2991 registry.registerThrowNoSuchMethod(); 3008 registry.registerThrowNoSuchMethod();
2992 } 3009 }
2993 } else if (target.impliesType) { 3010 } else if (target.impliesType) {
2994 setter = warnAndCreateErroneousElement( 3011 setter = reportAndCreateErroneousElement(node.selector, target.name,
2995 node.selector, target.name, MessageKind.ASSIGNING_TYPE); 3012 MessageKind.ASSIGNING_TYPE, const {});
2996 registry.registerThrowNoSuchMethod(); 3013 registry.registerThrowNoSuchMethod();
2997 } else if (target.isFinal || 3014 } else if (target.isFinal ||
2998 target.isConst || 3015 target.isConst ||
2999 (target.isFunction && 3016 (target.isFunction &&
3000 Elements.isStaticOrTopLevelFunction(target) && 3017 Elements.isStaticOrTopLevelFunction(target) &&
3001 !target.isSetter)) { 3018 !target.isSetter)) {
3002 if (target.isFunction) { 3019 if (target.isFunction) {
3003 setter = warnAndCreateErroneousElement( 3020 setter = reportAndCreateErroneousElement(node.selector, target.name,
3004 node.selector, target.name, MessageKind.ASSIGNING_METHOD); 3021 MessageKind.ASSIGNING_METHOD, const {});
3005 } else { 3022 } else {
3006 setter = warnAndCreateErroneousElement( 3023 setter = reportAndCreateErroneousElement(node.selector, target.name,
3007 node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER); 3024 MessageKind.CANNOT_RESOLVE_SETTER, const {});
3008 } 3025 }
3009 registry.registerThrowNoSuchMethod(); 3026 registry.registerThrowNoSuchMethod();
3010 } 3027 }
3011 if (isPotentiallyMutableTarget(target)) { 3028 if (isPotentiallyMutableTarget(target)) {
3012 registry.registerPotentialMutation(target, node); 3029 registry.registerPotentialMutation(target, node);
3013 if (enclosingElement != target.enclosingElement) { 3030 if (enclosingElement != target.enclosingElement) {
3014 registry.registerPotentialMutationInClosure(target, node); 3031 registry.registerPotentialMutationInClosure(target, node);
3015 } 3032 }
3016 for (Node scope in promotionScope) { 3033 for (Node scope in promotionScope) {
3017 registry.registerPotentialMutationIn(scope, target, node); 3034 registry.registerPotentialMutationIn(scope, target, node);
(...skipping 10 matching lines...) Expand all
3028 getterSelector = new Selector.getterFrom(selector); 3045 getterSelector = new Selector.getterFrom(selector);
3029 } else { 3046 } else {
3030 assert(selector.isIndexSet); 3047 assert(selector.isIndexSet);
3031 getterSelector = new Selector.index(); 3048 getterSelector = new Selector.index();
3032 } 3049 }
3033 registerSend(getterSelector, getter); 3050 registerSend(getterSelector, getter);
3034 registry.setGetterSelectorInComplexSendSet(node, getterSelector); 3051 registry.setGetterSelectorInComplexSendSet(node, getterSelector);
3035 if (node.isSuperCall) { 3052 if (node.isSuperCall) {
3036 getter = currentClass.lookupSuperSelector(getterSelector); 3053 getter = currentClass.lookupSuperSelector(getterSelector);
3037 if (getter == null) { 3054 if (getter == null) {
3038 target = warnAndCreateErroneousElement( 3055 target = reportAndCreateErroneousElement(
3039 node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER, 3056 node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
3040 {'className': currentClass, 'memberName': selector.name}); 3057 {'className': currentClass, 'memberName': selector.name});
3041 registry.registerSuperNoSuchMethod(); 3058 registry.registerSuperNoSuchMethod();
3042 } 3059 }
3043 } 3060 }
3044 registry.useElement(node.selector, getter); 3061 registry.useElement(node.selector, getter);
3045 3062
3046 // Make sure we include the + and - operators if we are using 3063 // Make sure we include the + and - operators if we are using
3047 // the ++ and -- ones. Also, if op= form is used, include op itself. 3064 // the ++ and -- ones. Also, if op= form is used, include op itself.
3048 void registerBinaryOperator(String name) { 3065 void registerBinaryOperator(String name) {
(...skipping 2047 matching lines...) Expand 10 before | Expand all | Expand 10 after
5096 } 5113 }
5097 5114
5098 /// The result for the resolution of the `assert` method. 5115 /// The result for the resolution of the `assert` method.
5099 class AssertResult implements ResolutionResult { 5116 class AssertResult implements ResolutionResult {
5100 const AssertResult(); 5117 const AssertResult();
5101 5118
5102 Element get element => null; 5119 Element get element => null;
5103 5120
5104 String toString() => 'AssertResult()'; 5121 String toString() => 'AssertResult()';
5105 } 5122 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/warnings.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698