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

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') | pkg/compiler/lib/src/warnings.dart » ('J')
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(Node node, String name,
2266 String name, 2269 MessageKind kind, Map arguments, {bool isError: false}) {
Johnni Winther 2015/04/12 11:10:45 Nit: We would normally format this as: ErroneousE
Siggi Cherem (dart-lang) 2015/04/13 16:40:24 Done. BTW - It might be worth to start using the
2267 MessageKind kind, 2270 if (isError) {
2268 [Map arguments = const {}]) { 2271 compiler.reportError(node, kind, arguments);
2269 compiler.reportWarning(node, kind, arguments); 2272 } else {
2273 compiler.reportWarning(node, kind, arguments);
2274 }
2270 // TODO(ahe): Use [allowedCategory] to synthesize a more precise subclass 2275 // TODO(ahe): Use [allowedCategory] to synthesize a more precise subclass
2271 // of [ErroneousElementX]. For example, [ErroneousFieldElementX], 2276 // of [ErroneousElementX]. For example, [ErroneousFieldElementX],
2272 // [ErroneousConstructorElementX], etc. 2277 // [ErroneousConstructorElementX], etc.
2273 return new ErroneousElementX(kind, arguments, name, enclosingElement); 2278 return new ErroneousElementX(kind, arguments, name, enclosingElement);
2274 } 2279 }
2275 2280
2276 ResolutionResult visitIdentifier(Identifier node) { 2281 ResolutionResult visitIdentifier(Identifier node) {
2277 if (node.isThis()) { 2282 if (node.isThis()) {
2278 if (!inInstanceContext) { 2283 if (!inInstanceContext) {
2279 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node}); 2284 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node});
(...skipping 13 matching lines...) Expand all
2293 if (Elements.isUnresolved(element) && name == 'dynamic') { 2298 if (Elements.isUnresolved(element) && name == 'dynamic') {
2294 // TODO(johnniwinther): Remove this hack when we can return more complex 2299 // TODO(johnniwinther): Remove this hack when we can return more complex
2295 // objects than [Element] from this method. 2300 // objects than [Element] from this method.
2296 element = compiler.typeClass; 2301 element = compiler.typeClass;
2297 // Set the type to be `dynamic` to mark that this is a type literal. 2302 // Set the type to be `dynamic` to mark that this is a type literal.
2298 registry.setType(node, const DynamicType()); 2303 registry.setType(node, const DynamicType());
2299 } 2304 }
2300 element = reportLookupErrorIfAny(element, node, node.source); 2305 element = reportLookupErrorIfAny(element, node, node.source);
2301 if (element == null) { 2306 if (element == null) {
2302 if (!inInstanceContext) { 2307 if (!inInstanceContext) {
2303 element = warnAndCreateErroneousElement( 2308 // We report an error within initializers because `this` is implicitly
2304 node, node.source, MessageKind.CANNOT_RESOLVE, 2309 // accessed when unqualified identifiers are not resolved. For
2305 {'name': node}); 2310 // details, see section 16.14.3 of the spec (2nd edition):
2311 // An unqualified invocation `i` of the form `id(a1, ...)`
2312 // ...
2313 // If `i` does not occur inside a top level or static function, `i`
2314 // is equivalent to `this.id(a1 , ...)`.
2315 bool inInitializer = enclosingElement.isGenerativeConstructor ||
2316 (enclosingElement.isInstanceMember && enclosingElement.isField);
2317 MessageKind kind = inInitializer
2318 ? MessageKind.CANNOT_RESOLVE_IN_INITIALIZER
2319 : MessageKind.CANNOT_RESOLVE;
2320 element = reportAndCreateErroneousElement(node, node.source, kind,
2321 {'name': node.source}, isError: inInitializer);
2306 registry.registerThrowNoSuchMethod(); 2322 registry.registerThrowNoSuchMethod();
2307 } 2323 }
2308 } else if (element.isErroneous) { 2324 } else if (element.isErroneous) {
2309 // Use the erroneous element. 2325 // Use the erroneous element.
2310 } else { 2326 } else {
2311 if ((element.kind.category & allowedCategory) == 0) { 2327 if ((element.kind.category & allowedCategory) == 0) {
2312 element = warnAndCreateErroneousElement( 2328 element = reportAndCreateErroneousElement(
2313 node, name, 2329 node, name, MessageKind.GENERIC,
2314 MessageKind.GENERIC,
2315 // TODO(ahe): Improve error message. Need UX input. 2330 // TODO(ahe): Improve error message. Need UX input.
2316 {'text': "is not an expression $element"}); 2331 {'text': "is not an expression $element"});
2317 } 2332 }
2318 } 2333 }
2319 if (!Elements.isUnresolved(element) && element.isClass) { 2334 if (!Elements.isUnresolved(element) && element.isClass) {
2320 ClassElement classElement = element; 2335 ClassElement classElement = element;
2321 classElement.ensureResolved(compiler); 2336 classElement.ensureResolved(compiler);
2322 } 2337 }
2323 return new ElementResult(registry.useElement(node, element)); 2338 return new ElementResult(registry.useElement(node, element));
2324 } 2339 }
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
2594 error(node.receiver, MessageKind.GENERIC, 2609 error(node.receiver, MessageKind.GENERIC,
2595 {'text': "Object has no superclass"}); 2610 {'text': "Object has no superclass"});
2596 return null; 2611 return null;
2597 } 2612 }
2598 // TODO(johnniwinther): Ensure correct behavior if currentClass is a 2613 // TODO(johnniwinther): Ensure correct behavior if currentClass is a
2599 // patch. 2614 // patch.
2600 target = currentClass.lookupSuperSelector(selector); 2615 target = currentClass.lookupSuperSelector(selector);
2601 // [target] may be null which means invoking noSuchMethod on 2616 // [target] may be null which means invoking noSuchMethod on
2602 // super. 2617 // super.
2603 if (target == null) { 2618 if (target == null) {
2604 target = warnAndCreateErroneousElement( 2619 target = reportAndCreateErroneousElement(
2605 node, name, MessageKind.NO_SUCH_SUPER_MEMBER, 2620 node, name, MessageKind.NO_SUCH_SUPER_MEMBER,
2606 {'className': currentClass, 'memberName': name}); 2621 {'className': currentClass, 'memberName': name});
2607 // We still need to register the invocation, because we might 2622 // We still need to register the invocation, because we might
2608 // call [:super.noSuchMethod:] which calls 2623 // call [:super.noSuchMethod:] which calls
2609 // [JSInvocationMirror._invokeOn]. 2624 // [JSInvocationMirror._invokeOn].
2610 registry.registerDynamicInvocation(selector); 2625 registry.registerDynamicInvocation(selector);
2611 registry.registerSuperNoSuchMethod(); 2626 registry.registerSuperNoSuchMethod();
2612 } 2627 }
2613 } else if (resolvedReceiver == null || 2628 } else if (resolvedReceiver == null ||
2614 Elements.isUnresolved(resolvedReceiver.element)) { 2629 Elements.isUnresolved(resolvedReceiver.element)) {
(...skipping 18 matching lines...) Expand all
2633 // TODO(johnniwinther): With the simplified [TreeElements] invariant, 2648 // TODO(johnniwinther): With the simplified [TreeElements] invariant,
2634 // try to resolve injected elements if [currentClass] is in the patch 2649 // try to resolve injected elements if [currentClass] is in the patch
2635 // library of [receiverClass]. 2650 // library of [receiverClass].
2636 2651
2637 // TODO(karlklose): this should be reported by the caller of 2652 // TODO(karlklose): this should be reported by the caller of
2638 // [resolveSend] to select better warning messages for getters and 2653 // [resolveSend] to select better warning messages for getters and
2639 // setters. 2654 // setters.
2640 MessageKind kind = (target == null) 2655 MessageKind kind = (target == null)
2641 ? MessageKind.MEMBER_NOT_FOUND 2656 ? MessageKind.MEMBER_NOT_FOUND
2642 : MessageKind.MEMBER_NOT_STATIC; 2657 : MessageKind.MEMBER_NOT_STATIC;
2643 return new ElementResult(warnAndCreateErroneousElement( 2658 return new ElementResult(reportAndCreateErroneousElement(
2644 node, name, kind, 2659 node, name, kind,
2645 {'className': receiverClass.name, 'memberName': name})); 2660 {'className': receiverClass.name, 'memberName': name}));
2646 } else if (isPrivateName(name) && 2661 } else if (isPrivateName(name) &&
2647 target.library != enclosingElement.library) { 2662 target.library != enclosingElement.library) {
2648 registry.registerThrowNoSuchMethod(); 2663 registry.registerThrowNoSuchMethod();
2649 return new ElementResult(warnAndCreateErroneousElement( 2664 return new ElementResult(reportAndCreateErroneousElement(
2650 node, name, MessageKind.PRIVATE_ACCESS, 2665 node, name, MessageKind.PRIVATE_ACCESS,
2651 {'libraryName': target.library.getLibraryOrScriptName(), 2666 {'libraryName': target.library.getLibraryOrScriptName(),
2652 'name': name})); 2667 'name': name}));
2653 } 2668 }
2654 } else if (resolvedReceiver.element.isPrefix) { 2669 } else if (resolvedReceiver.element.isPrefix) {
2655 PrefixElement prefix = resolvedReceiver.element; 2670 PrefixElement prefix = resolvedReceiver.element;
2656 target = prefix.lookupLocalMember(name); 2671 target = prefix.lookupLocalMember(name);
2657 if (Elements.isUnresolved(target)) { 2672 if (Elements.isUnresolved(target)) {
2658 registry.registerThrowNoSuchMethod(); 2673 registry.registerThrowNoSuchMethod();
2659 return new ElementResult(warnAndCreateErroneousElement( 2674 return new ElementResult(reportAndCreateErroneousElement(
2660 node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER, 2675 node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER,
2661 {'libraryName': prefix.name, 'memberName': name})); 2676 {'libraryName': prefix.name, 'memberName': name}));
2662 } else if (target.isAmbiguous) { 2677 } else if (target.isAmbiguous) {
2663 registry.registerThrowNoSuchMethod(); 2678 registry.registerThrowNoSuchMethod();
2664 AmbiguousElement ambiguous = target; 2679 AmbiguousElement ambiguous = target;
2665 target = warnAndCreateErroneousElement(node, name, 2680 target = reportAndCreateErroneousElement(
2666 ambiguous.messageKind, 2681 node, name, ambiguous.messageKind, ambiguous.messageArguments);
2667 ambiguous.messageArguments);
2668 ambiguous.diagnose(enclosingElement, compiler); 2682 ambiguous.diagnose(enclosingElement, compiler);
2669 return new ElementResult(target); 2683 return new ElementResult(target);
2670 } else if (target.kind == ElementKind.CLASS) { 2684 } else if (target.kind == ElementKind.CLASS) {
2671 ClassElement classElement = target; 2685 ClassElement classElement = target;
2672 classElement.ensureResolved(compiler); 2686 classElement.ensureResolved(compiler);
2673 } 2687 }
2674 } 2688 }
2675 return new ElementResult(target); 2689 return new ElementResult(target);
2676 } 2690 }
2677 2691
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2798 } 2812 }
2799 2813
2800 if (target != null) { 2814 if (target != null) {
2801 if (target.isErroneous) { 2815 if (target.isErroneous) {
2802 registry.registerThrowNoSuchMethod(); 2816 registry.registerThrowNoSuchMethod();
2803 } else if (target.isAbstractField) { 2817 } else if (target.isAbstractField) {
2804 AbstractFieldElement field = target; 2818 AbstractFieldElement field = target;
2805 target = field.getter; 2819 target = field.getter;
2806 if (target == null && !inInstanceContext) { 2820 if (target == null && !inInstanceContext) {
2807 registry.registerThrowNoSuchMethod(); 2821 registry.registerThrowNoSuchMethod();
2808 target = 2822 target = reportAndCreateErroneousElement(node.selector, field.name,
2809 warnAndCreateErroneousElement(node.selector, field.name, 2823 MessageKind.CANNOT_RESOLVE_GETTER, const {});
2810 MessageKind.CANNOT_RESOLVE_GETTER);
2811 } 2824 }
2812 } else if (target.isTypeVariable) { 2825 } else if (target.isTypeVariable) {
2813 ClassElement cls = target.enclosingClass; 2826 ClassElement cls = target.enclosingClass;
2814 assert(enclosingElement.enclosingClass == cls); 2827 assert(enclosingElement.enclosingClass == cls);
2815 if (Elements.isInStaticContext(enclosingElement)) { 2828 if (Elements.isInStaticContext(enclosingElement)) {
2816 compiler.reportError(node, 2829 compiler.reportError(node,
2817 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, 2830 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
2818 {'typeVariableName': node.selector}); 2831 {'typeVariableName': node.selector});
2819 } 2832 }
2820 registry.registerClassUsingVariableExpression(cls); 2833 registry.registerClassUsingVariableExpression(cls);
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
2974 Element getter = target; 2987 Element getter = target;
2975 String operatorName = node.assignmentOperator.source; 2988 String operatorName = node.assignmentOperator.source;
2976 String source = operatorName; 2989 String source = operatorName;
2977 bool isComplex = !identical(source, '='); 2990 bool isComplex = !identical(source, '=');
2978 if (!(result is AssertResult || Elements.isUnresolved(target))) { 2991 if (!(result is AssertResult || Elements.isUnresolved(target))) {
2979 if (target.isAbstractField) { 2992 if (target.isAbstractField) {
2980 AbstractFieldElement field = target; 2993 AbstractFieldElement field = target;
2981 setter = field.setter; 2994 setter = field.setter;
2982 getter = field.getter; 2995 getter = field.getter;
2983 if (setter == null && !inInstanceContext) { 2996 if (setter == null && !inInstanceContext) {
2984 setter = warnAndCreateErroneousElement( 2997 setter = reportAndCreateErroneousElement(node.selector, field.name,
2985 node.selector, field.name, MessageKind.CANNOT_RESOLVE_SETTER); 2998 MessageKind.CANNOT_RESOLVE_SETTER, const {});
2986 registry.registerThrowNoSuchMethod(); 2999 registry.registerThrowNoSuchMethod();
2987 } 3000 }
2988 if (isComplex && getter == null && !inInstanceContext) { 3001 if (isComplex && getter == null && !inInstanceContext) {
2989 getter = warnAndCreateErroneousElement( 3002 getter = reportAndCreateErroneousElement(node.selector, field.name,
2990 node.selector, field.name, MessageKind.CANNOT_RESOLVE_GETTER); 3003 MessageKind.CANNOT_RESOLVE_GETTER, const {});
2991 registry.registerThrowNoSuchMethod(); 3004 registry.registerThrowNoSuchMethod();
2992 } 3005 }
2993 } else if (target.impliesType) { 3006 } else if (target.impliesType) {
2994 setter = warnAndCreateErroneousElement( 3007 setter = reportAndCreateErroneousElement(node.selector, target.name,
2995 node.selector, target.name, MessageKind.ASSIGNING_TYPE); 3008 MessageKind.ASSIGNING_TYPE, const {});
2996 registry.registerThrowNoSuchMethod(); 3009 registry.registerThrowNoSuchMethod();
2997 } else if (target.isFinal || 3010 } else if (target.isFinal ||
2998 target.isConst || 3011 target.isConst ||
2999 (target.isFunction && 3012 (target.isFunction &&
3000 Elements.isStaticOrTopLevelFunction(target) && 3013 Elements.isStaticOrTopLevelFunction(target) &&
3001 !target.isSetter)) { 3014 !target.isSetter)) {
3002 if (target.isFunction) { 3015 if (target.isFunction) {
3003 setter = warnAndCreateErroneousElement( 3016 setter = reportAndCreateErroneousElement(node.selector, target.name,
3004 node.selector, target.name, MessageKind.ASSIGNING_METHOD); 3017 MessageKind.ASSIGNING_METHOD, const {});
3005 } else { 3018 } else {
3006 setter = warnAndCreateErroneousElement( 3019 setter = reportAndCreateErroneousElement(node.selector, target.name,
3007 node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER); 3020 MessageKind.CANNOT_RESOLVE_SETTER, const {});
3008 } 3021 }
3009 registry.registerThrowNoSuchMethod(); 3022 registry.registerThrowNoSuchMethod();
3010 } 3023 }
3011 if (isPotentiallyMutableTarget(target)) { 3024 if (isPotentiallyMutableTarget(target)) {
3012 registry.registerPotentialMutation(target, node); 3025 registry.registerPotentialMutation(target, node);
3013 if (enclosingElement != target.enclosingElement) { 3026 if (enclosingElement != target.enclosingElement) {
3014 registry.registerPotentialMutationInClosure(target, node); 3027 registry.registerPotentialMutationInClosure(target, node);
3015 } 3028 }
3016 for (Node scope in promotionScope) { 3029 for (Node scope in promotionScope) {
3017 registry.registerPotentialMutationIn(scope, target, node); 3030 registry.registerPotentialMutationIn(scope, target, node);
(...skipping 10 matching lines...) Expand all
3028 getterSelector = new Selector.getterFrom(selector); 3041 getterSelector = new Selector.getterFrom(selector);
3029 } else { 3042 } else {
3030 assert(selector.isIndexSet); 3043 assert(selector.isIndexSet);
3031 getterSelector = new Selector.index(); 3044 getterSelector = new Selector.index();
3032 } 3045 }
3033 registerSend(getterSelector, getter); 3046 registerSend(getterSelector, getter);
3034 registry.setGetterSelectorInComplexSendSet(node, getterSelector); 3047 registry.setGetterSelectorInComplexSendSet(node, getterSelector);
3035 if (node.isSuperCall) { 3048 if (node.isSuperCall) {
3036 getter = currentClass.lookupSuperSelector(getterSelector); 3049 getter = currentClass.lookupSuperSelector(getterSelector);
3037 if (getter == null) { 3050 if (getter == null) {
3038 target = warnAndCreateErroneousElement( 3051 target = reportAndCreateErroneousElement(
3039 node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER, 3052 node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
3040 {'className': currentClass, 'memberName': selector.name}); 3053 {'className': currentClass, 'memberName': selector.name});
3041 registry.registerSuperNoSuchMethod(); 3054 registry.registerSuperNoSuchMethod();
3042 } 3055 }
3043 } 3056 }
3044 registry.useElement(node.selector, getter); 3057 registry.useElement(node.selector, getter);
3045 3058
3046 // Make sure we include the + and - operators if we are using 3059 // Make sure we include the + and - operators if we are using
3047 // the ++ and -- ones. Also, if op= form is used, include op itself. 3060 // the ++ and -- ones. Also, if op= form is used, include op itself.
3048 void registerBinaryOperator(String name) { 3061 void registerBinaryOperator(String name) {
(...skipping 2047 matching lines...) Expand 10 before | Expand all | Expand 10 after
5096 } 5109 }
5097 5110
5098 /// The result for the resolution of the `assert` method. 5111 /// The result for the resolution of the `assert` method.
5099 class AssertResult implements ResolutionResult { 5112 class AssertResult implements ResolutionResult {
5100 const AssertResult(); 5113 const AssertResult();
5101 5114
5102 Element get element => null; 5115 Element get element => null;
5103 5116
5104 String toString() => 'AssertResult()'; 5117 String toString() => 'AssertResult()';
5105 } 5118 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/warnings.dart » ('j') | pkg/compiler/lib/src/warnings.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698