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 Setlet<Node> get superUses; | 9 Setlet<Node> get superUses; |
10 | 10 |
(...skipping 1935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1946 MessageKind.EXISTING_DEFINITION, {'name': name}); | 1946 MessageKind.EXISTING_DEFINITION, {'name': name}); |
1947 } | 1947 } |
1948 } | 1948 } |
1949 | 1949 |
1950 /** | 1950 /** |
1951 * Core implementation of resolution. | 1951 * Core implementation of resolution. |
1952 * | 1952 * |
1953 * Do not subclass or instantiate this class outside this library | 1953 * Do not subclass or instantiate this class outside this library |
1954 * except for testing. | 1954 * except for testing. |
1955 */ | 1955 */ |
1956 class ResolverVisitor extends MappingVisitor<Element> { | 1956 class ResolverVisitor extends MappingVisitor<ResolutionResult> { |
1957 /** | 1957 /** |
1958 * The current enclosing element for the visited AST nodes. | 1958 * The current enclosing element for the visited AST nodes. |
1959 * | 1959 * |
1960 * This field is updated when nested closures are visited. | 1960 * This field is updated when nested closures are visited. |
1961 */ | 1961 */ |
1962 Element enclosingElement; | 1962 Element enclosingElement; |
1963 bool inInstanceContext; | 1963 bool inInstanceContext; |
1964 bool inCheckContext; | 1964 bool inCheckContext; |
1965 bool inCatchBlock; | 1965 bool inCatchBlock; |
1966 Scope scope; | 1966 Scope scope; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2102 } | 2102 } |
2103 | 2103 |
2104 ErroneousElement warnAndCreateErroneousElement(Node node, | 2104 ErroneousElement warnAndCreateErroneousElement(Node node, |
2105 String name, | 2105 String name, |
2106 MessageKind kind, | 2106 MessageKind kind, |
2107 [Map arguments = const {}]) { | 2107 [Map arguments = const {}]) { |
2108 compiler.reportWarning(node, kind, arguments); | 2108 compiler.reportWarning(node, kind, arguments); |
2109 return new ErroneousElementX(kind, arguments, name, enclosingElement); | 2109 return new ErroneousElementX(kind, arguments, name, enclosingElement); |
2110 } | 2110 } |
2111 | 2111 |
2112 Element visitIdentifier(Identifier node) { | 2112 ResolutionResult visitIdentifier(Identifier node) { |
2113 if (node.isThis()) { | 2113 if (node.isThis()) { |
2114 if (!inInstanceContext) { | 2114 if (!inInstanceContext) { |
2115 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node}); | 2115 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node}); |
2116 } | 2116 } |
2117 return null; | 2117 return null; |
2118 } else if (node.isSuper()) { | 2118 } else if (node.isSuper()) { |
2119 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); | 2119 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); |
2120 if ((ElementCategory.SUPER & allowedCategory) == 0) { | 2120 if ((ElementCategory.SUPER & allowedCategory) == 0) { |
2121 error(node, MessageKind.INVALID_USE_OF_SUPER); | 2121 error(node, MessageKind.INVALID_USE_OF_SUPER); |
2122 } | 2122 } |
(...skipping 22 matching lines...) Expand all Loading... | |
2145 if ((element.kind.category & allowedCategory) == 0) { | 2145 if ((element.kind.category & allowedCategory) == 0) { |
2146 // TODO(ahe): Improve error message. Need UX input. | 2146 // TODO(ahe): Improve error message. Need UX input. |
2147 error(node, MessageKind.GENERIC, | 2147 error(node, MessageKind.GENERIC, |
2148 {'text': "is not an expression $element"}); | 2148 {'text': "is not an expression $element"}); |
2149 } | 2149 } |
2150 } | 2150 } |
2151 if (!Elements.isUnresolved(element) && element.isClass) { | 2151 if (!Elements.isUnresolved(element) && element.isClass) { |
2152 ClassElement classElement = element; | 2152 ClassElement classElement = element; |
2153 classElement.ensureResolved(compiler); | 2153 classElement.ensureResolved(compiler); |
2154 } | 2154 } |
2155 return registry.useElement(node, element); | 2155 return new ElementResult(registry.useElement(node, element)); |
2156 } | 2156 } |
2157 } | 2157 } |
2158 | 2158 |
2159 Element visitTypeAnnotation(TypeAnnotation node) { | 2159 ResolutionResult visitTypeAnnotation(TypeAnnotation node) { |
2160 DartType type = resolveTypeAnnotation(node); | 2160 DartType type = resolveTypeAnnotation(node); |
2161 if (type != null) { | 2161 if (inCheckContext) { |
2162 if (inCheckContext) { | 2162 registry.registerIsCheck(type); |
2163 registry.registerIsCheck(type); | |
2164 } | |
2165 return type.element; | |
2166 } | 2163 } |
2167 return null; | 2164 return new TypeResult(type); |
2168 } | 2165 } |
2169 | 2166 |
2170 bool isNamedConstructor(Send node) => node.receiver != null; | 2167 bool isNamedConstructor(Send node) => node.receiver != null; |
2171 | 2168 |
2172 Selector getRedirectingThisOrSuperConstructorSelector(Send node) { | 2169 Selector getRedirectingThisOrSuperConstructorSelector(Send node) { |
2173 if (isNamedConstructor(node)) { | 2170 if (isNamedConstructor(node)) { |
2174 String constructorName = node.selector.asIdentifier().source; | 2171 String constructorName = node.selector.asIdentifier().source; |
2175 return new Selector.callConstructor( | 2172 return new Selector.callConstructor( |
2176 constructorName, | 2173 constructorName, |
2177 enclosingElement.library); | 2174 enclosingElement.library); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2247 visit(node.expression); | 2244 visit(node.expression); |
2248 } | 2245 } |
2249 | 2246 |
2250 visitClassNode(ClassNode node) { | 2247 visitClassNode(ClassNode node) { |
2251 internalError(node, "shouldn't be called"); | 2248 internalError(node, "shouldn't be called"); |
2252 } | 2249 } |
2253 | 2250 |
2254 visitIn(Node node, Scope nestedScope) { | 2251 visitIn(Node node, Scope nestedScope) { |
2255 Scope oldScope = scope; | 2252 Scope oldScope = scope; |
2256 scope = nestedScope; | 2253 scope = nestedScope; |
2257 Element element = visit(node); | 2254 ResolutionResult result = visit(node); |
2258 scope = oldScope; | 2255 scope = oldScope; |
2259 return element; | 2256 return result; |
2260 } | 2257 } |
2261 | 2258 |
2262 /** | 2259 /** |
2263 * Introduces new default targets for break and continue | 2260 * Introduces new default targets for break and continue |
2264 * before visiting the body of the loop | 2261 * before visiting the body of the loop |
2265 */ | 2262 */ |
2266 visitLoopBodyIn(Loop loop, Node body, Scope bodyScope) { | 2263 visitLoopBodyIn(Loop loop, Node body, Scope bodyScope) { |
2267 TargetElement element = getOrDefineTarget(loop); | 2264 TargetElement element = getOrDefineTarget(loop); |
2268 statementScope.enterLoop(element); | 2265 statementScope.enterLoop(element); |
2269 visitIn(body, bodyScope); | 2266 visitIn(body, bodyScope); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2341 registry.registerInstantiatedClass(compiler.functionClass); | 2338 registry.registerInstantiatedClass(compiler.functionClass); |
2342 } | 2339 } |
2343 | 2340 |
2344 visitIf(If node) { | 2341 visitIf(If node) { |
2345 doInPromotionScope(node.condition.expression, () => visit(node.condition)); | 2342 doInPromotionScope(node.condition.expression, () => visit(node.condition)); |
2346 doInPromotionScope(node.thenPart, | 2343 doInPromotionScope(node.thenPart, |
2347 () => visitIn(node.thenPart, new BlockScope(scope))); | 2344 () => visitIn(node.thenPart, new BlockScope(scope))); |
2348 visitIn(node.elsePart, new BlockScope(scope)); | 2345 visitIn(node.elsePart, new BlockScope(scope)); |
2349 } | 2346 } |
2350 | 2347 |
2351 Element resolveSend(Send node) { | 2348 ResolutionResult resolveSend(Send node) { |
2352 Selector selector = resolveSelector(node, null); | 2349 Selector selector = resolveSelector(node, null); |
2353 if (node.isSuperCall) registry.registerSuperUse(node); | 2350 if (node.isSuperCall) registry.registerSuperUse(node); |
2354 | 2351 |
2355 if (node.receiver == null) { | 2352 if (node.receiver == null) { |
2356 // If this send is of the form "assert(expr);", then | 2353 // If this send is of the form "assert(expr);", then |
2357 // this is an assertion. | 2354 // this is an assertion. |
2358 if (selector.isAssert) { | 2355 if (selector.isAssert) { |
2359 if (selector.argumentCount != 1) { | 2356 if (selector.argumentCount != 1) { |
2360 error(node.selector, | 2357 error(node.selector, |
2361 MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT, | 2358 MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT, |
2362 {'argumentCount': selector.argumentCount}); | 2359 {'argumentCount': selector.argumentCount}); |
2363 } else if (selector.namedArgumentCount != 0) { | 2360 } else if (selector.namedArgumentCount != 0) { |
2364 error(node.selector, | 2361 error(node.selector, |
2365 MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS, | 2362 MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS, |
2366 {'argumentCount': selector.namedArgumentCount}); | 2363 {'argumentCount': selector.namedArgumentCount}); |
2367 } | 2364 } |
2368 registry.registerAssert(node); | 2365 registry.registerAssert(node); |
2369 // TODO(johnniwinther): Return a marker to indicated that this is | 2366 return const AssertResult(); |
2370 // a call to assert. | |
2371 return null; | |
2372 } | 2367 } |
2373 | 2368 |
2374 return node.selector.accept(this); | 2369 return node.selector.accept(this); |
2375 } | 2370 } |
2376 | 2371 |
2377 var oldCategory = allowedCategory; | 2372 var oldCategory = allowedCategory; |
2378 allowedCategory |= ElementCategory.PREFIX | ElementCategory.SUPER; | 2373 allowedCategory |= ElementCategory.PREFIX | ElementCategory.SUPER; |
2379 Element resolvedReceiver = visit(node.receiver); | 2374 ResolutionResult resolvedReceiver = visit(node.receiver); |
2380 allowedCategory = oldCategory; | 2375 allowedCategory = oldCategory; |
2381 | 2376 |
2382 Element target; | 2377 Element target; |
karlklose
2014/07/03 08:36:04
Target could be a ResolutionResult.
Johnni Winther
2014/07/03 12:11:35
Not as easy as it looks. Will do it in a later CL.
| |
2383 String name = node.selector.asIdentifier().source; | 2378 String name = node.selector.asIdentifier().source; |
2384 if (identical(name, 'this')) { | 2379 if (identical(name, 'this')) { |
2385 // TODO(ahe): Why is this using GENERIC? | 2380 // TODO(ahe): Why is this using GENERIC? |
2386 error(node.selector, MessageKind.GENERIC, | 2381 error(node.selector, MessageKind.GENERIC, |
2387 {'text': "expected an identifier"}); | 2382 {'text': "expected an identifier"}); |
2388 } else if (node.isSuperCall) { | 2383 } else if (node.isSuperCall) { |
2389 if (node.isOperator) { | 2384 if (node.isOperator) { |
2390 if (isUserDefinableOperator(name)) { | 2385 if (isUserDefinableOperator(name)) { |
2391 name = selector.name; | 2386 name = selector.name; |
2392 } else { | 2387 } else { |
(...skipping 18 matching lines...) Expand all Loading... | |
2411 if (target == null) { | 2406 if (target == null) { |
2412 target = warnAndCreateErroneousElement( | 2407 target = warnAndCreateErroneousElement( |
2413 node, name, MessageKind.NO_SUCH_SUPER_MEMBER, | 2408 node, name, MessageKind.NO_SUCH_SUPER_MEMBER, |
2414 {'className': currentClass, 'memberName': name}); | 2409 {'className': currentClass, 'memberName': name}); |
2415 // We still need to register the invocation, because we might | 2410 // We still need to register the invocation, because we might |
2416 // call [:super.noSuchMethod:] which calls | 2411 // call [:super.noSuchMethod:] which calls |
2417 // [JSInvocationMirror._invokeOn]. | 2412 // [JSInvocationMirror._invokeOn]. |
2418 registry.registerDynamicInvocation(selector); | 2413 registry.registerDynamicInvocation(selector); |
2419 registry.registerSuperNoSuchMethod(); | 2414 registry.registerSuperNoSuchMethod(); |
2420 } | 2415 } |
2421 } else if (Elements.isUnresolved(resolvedReceiver)) { | 2416 } else if (resolvedReceiver == null || |
2417 Elements.isUnresolved(resolvedReceiver.element)) { | |
2422 return null; | 2418 return null; |
2423 } else if (resolvedReceiver.isClass) { | 2419 } else if (resolvedReceiver.element.isClass) { |
2424 ClassElement receiverClass = resolvedReceiver; | 2420 ClassElement receiverClass = resolvedReceiver.element; |
2425 receiverClass.ensureResolved(compiler); | 2421 receiverClass.ensureResolved(compiler); |
2426 if (node.isOperator) { | 2422 if (node.isOperator) { |
2427 // When the resolved receiver is a class, we can have two cases: | 2423 // When the resolved receiver is a class, we can have two cases: |
2428 // 1) a static send: C.foo, or | 2424 // 1) a static send: C.foo, or |
2429 // 2) an operator send, where the receiver is a class literal: 'C + 1'. | 2425 // 2) an operator send, where the receiver is a class literal: 'C + 1'. |
2430 // The following code that looks up the selector on the resolved | 2426 // The following code that looks up the selector on the resolved |
2431 // receiver will treat the second as the invocation of a static operator | 2427 // receiver will treat the second as the invocation of a static operator |
2432 // if the resolved receiver is not null. | 2428 // if the resolved receiver is not null. |
2433 return null; | 2429 return null; |
2434 } | 2430 } |
2435 MembersCreator.computeClassMembersByName( | 2431 MembersCreator.computeClassMembersByName( |
2436 compiler, receiverClass.declaration, name); | 2432 compiler, receiverClass.declaration, name); |
2437 target = receiverClass.lookupLocalMember(name); | 2433 target = receiverClass.lookupLocalMember(name); |
2438 if (target == null || target.isInstanceMember) { | 2434 if (target == null || target.isInstanceMember) { |
2439 registry.registerThrowNoSuchMethod(); | 2435 registry.registerThrowNoSuchMethod(); |
2440 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | 2436 // TODO(johnniwinther): With the simplified [TreeElements] invariant, |
2441 // try to resolve injected elements if [currentClass] is in the patch | 2437 // try to resolve injected elements if [currentClass] is in the patch |
2442 // library of [receiverClass]. | 2438 // library of [receiverClass]. |
2443 | 2439 |
2444 // TODO(karlklose): this should be reported by the caller of | 2440 // TODO(karlklose): this should be reported by the caller of |
2445 // [resolveSend] to select better warning messages for getters and | 2441 // [resolveSend] to select better warning messages for getters and |
2446 // setters. | 2442 // setters. |
2447 MessageKind kind = (target == null) | 2443 MessageKind kind = (target == null) |
2448 ? MessageKind.MEMBER_NOT_FOUND | 2444 ? MessageKind.MEMBER_NOT_FOUND |
2449 : MessageKind.MEMBER_NOT_STATIC; | 2445 : MessageKind.MEMBER_NOT_STATIC; |
2450 return warnAndCreateErroneousElement(node, name, kind, | 2446 return new ElementResult(warnAndCreateErroneousElement( |
karlklose
2014/07/03 08:36:04
Change warnAndCreateErroneousElement to return the
Johnni Winther
2014/07/03 12:11:35
Not as easy as it looks. Will do it in a later CL.
| |
2451 {'className': receiverClass.name, | 2447 node, name, kind, |
2452 'memberName': name}); | 2448 {'className': receiverClass.name, 'memberName': name})); |
2453 } | 2449 } |
2454 } else if (identical(resolvedReceiver.kind, ElementKind.PREFIX)) { | 2450 } else if (resolvedReceiver.element.isPrefix) { |
2455 PrefixElement prefix = resolvedReceiver; | 2451 PrefixElement prefix = resolvedReceiver.element; |
2456 target = prefix.lookupLocalMember(name); | 2452 target = prefix.lookupLocalMember(name); |
2457 if (Elements.isUnresolved(target)) { | 2453 if (Elements.isUnresolved(target)) { |
2458 registry.registerThrowNoSuchMethod(); | 2454 registry.registerThrowNoSuchMethod(); |
2459 return warnAndCreateErroneousElement( | 2455 return new ElementResult(warnAndCreateErroneousElement( |
2460 node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER, | 2456 node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER, |
2461 {'libraryName': prefix.name, 'memberName': name}); | 2457 {'libraryName': prefix.name, 'memberName': name})); |
2462 } else if (target.isAmbiguous) { | 2458 } else if (target.isAmbiguous) { |
2463 registry.registerThrowNoSuchMethod(); | 2459 registry.registerThrowNoSuchMethod(); |
2464 AmbiguousElement ambiguous = target; | 2460 AmbiguousElement ambiguous = target; |
2465 target = warnAndCreateErroneousElement(node, name, | 2461 target = warnAndCreateErroneousElement(node, name, |
2466 ambiguous.messageKind, | 2462 ambiguous.messageKind, |
2467 ambiguous.messageArguments); | 2463 ambiguous.messageArguments); |
2468 ambiguous.diagnose(enclosingElement, compiler); | 2464 ambiguous.diagnose(enclosingElement, compiler); |
2469 return target; | 2465 return new ElementResult(target); |
2470 } else if (target.kind == ElementKind.CLASS) { | 2466 } else if (target.kind == ElementKind.CLASS) { |
2471 ClassElement classElement = target; | 2467 ClassElement classElement = target; |
2472 classElement.ensureResolved(compiler); | 2468 classElement.ensureResolved(compiler); |
2473 } | 2469 } |
2474 } | 2470 } |
2475 return target; | 2471 return new ElementResult(target); |
2476 } | 2472 } |
2477 | 2473 |
2478 static Selector computeSendSelector(Send node, | 2474 static Selector computeSendSelector(Send node, |
2479 LibraryElement library, | 2475 LibraryElement library, |
2480 Element element) { | 2476 Element element) { |
2481 // First determine if this is part of an assignment. | 2477 // First determine if this is part of an assignment. |
2482 bool isSet = node.asSendSet() != null; | 2478 bool isSet = node.asSendSet() != null; |
2483 | 2479 |
2484 if (node.isIndex) { | 2480 if (node.isIndex) { |
2485 return isSet ? new Selector.indexSet() : new Selector.index(); | 2481 return isSet ? new Selector.indexSet() : new Selector.index(); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2568 } else { | 2564 } else { |
2569 seenNamedArguments[source] = namedArgument; | 2565 seenNamedArguments[source] = namedArgument; |
2570 } | 2566 } |
2571 } else if (!seenNamedArguments.isEmpty) { | 2567 } else if (!seenNamedArguments.isEmpty) { |
2572 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); | 2568 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); |
2573 } | 2569 } |
2574 } | 2570 } |
2575 sendIsMemberAccess = oldSendIsMemberAccess; | 2571 sendIsMemberAccess = oldSendIsMemberAccess; |
2576 } | 2572 } |
2577 | 2573 |
2578 visitSend(Send node) { | 2574 ResolutionResult visitSend(Send node) { |
2579 bool oldSendIsMemberAccess = sendIsMemberAccess; | 2575 bool oldSendIsMemberAccess = sendIsMemberAccess; |
2580 sendIsMemberAccess = node.isPropertyAccess || node.isCall; | 2576 sendIsMemberAccess = node.isPropertyAccess || node.isCall; |
2581 Element target; | 2577 ResolutionResult result; |
2582 if (node.isLogicalAnd) { | 2578 if (node.isLogicalAnd) { |
2583 target = doInPromotionScope(node.receiver, () => resolveSend(node)); | 2579 result = doInPromotionScope(node.receiver, () => resolveSend(node)); |
2584 } else { | 2580 } else { |
2585 target = resolveSend(node); | 2581 result = resolveSend(node); |
2586 } | 2582 } |
2587 sendIsMemberAccess = oldSendIsMemberAccess; | 2583 sendIsMemberAccess = oldSendIsMemberAccess; |
2588 | 2584 |
2585 Element target = result != null ? result.element : null; | |
2586 | |
2589 if (target != null | 2587 if (target != null |
2590 && target == compiler.mirrorSystemGetNameFunction | 2588 && target == compiler.mirrorSystemGetNameFunction |
2591 && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) { | 2589 && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) { |
2592 compiler.reportHint( | 2590 compiler.reportHint( |
2593 node.selector, MessageKind.STATIC_FUNCTION_BLOAT, | 2591 node.selector, MessageKind.STATIC_FUNCTION_BLOAT, |
2594 {'class': compiler.mirrorSystemClass.name, | 2592 {'class': compiler.mirrorSystemClass.name, |
2595 'name': compiler.mirrorSystemGetNameFunction.name}); | 2593 'name': compiler.mirrorSystemGetNameFunction.name}); |
2596 } | 2594 } |
2597 | 2595 |
2598 if (!Elements.isUnresolved(target)) { | 2596 if (!Elements.isUnresolved(target)) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2720 } | 2718 } |
2721 } | 2719 } |
2722 } | 2720 } |
2723 } | 2721 } |
2724 | 2722 |
2725 registry.useElement(node, target); | 2723 registry.useElement(node, target); |
2726 registerSend(selector, target); | 2724 registerSend(selector, target); |
2727 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { | 2725 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { |
2728 registry.registerGetOfStaticFunction(target.declaration); | 2726 registry.registerGetOfStaticFunction(target.declaration); |
2729 } | 2727 } |
2730 return node.isPropertyAccess ? target : null; | 2728 return node.isPropertyAccess ? new ElementResult(target) : null; |
2731 } | 2729 } |
2732 | 2730 |
2733 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. | 2731 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. |
2734 DartType resolveTypeFromString(Node node, String typeName) { | 2732 DartType resolveTypeFromString(Node node, String typeName) { |
2735 Element element = lookupInScope(compiler, node, | 2733 Element element = lookupInScope(compiler, node, |
2736 scope, typeName); | 2734 scope, typeName); |
2737 if (element == null) return null; | 2735 if (element == null) return null; |
2738 if (element is! ClassElement) return null; | 2736 if (element is! ClassElement) return null; |
2739 ClassElement cls = element; | 2737 ClassElement cls = element; |
2740 cls.ensureResolved(compiler); | 2738 cls.ensureResolved(compiler); |
2741 return cls.computeType(compiler); | 2739 return cls.computeType(compiler); |
2742 } | 2740 } |
2743 | 2741 |
2744 visitSendSet(SendSet node) { | 2742 ResolutionResult visitSendSet(SendSet node) { |
2745 bool oldSendIsMemberAccess = sendIsMemberAccess; | 2743 bool oldSendIsMemberAccess = sendIsMemberAccess; |
2746 sendIsMemberAccess = node.isPropertyAccess || node.isCall; | 2744 sendIsMemberAccess = node.isPropertyAccess || node.isCall; |
2747 Element target = resolveSend(node); | 2745 ResolutionResult result = resolveSend(node); |
2748 sendIsMemberAccess = oldSendIsMemberAccess; | 2746 sendIsMemberAccess = oldSendIsMemberAccess; |
2747 Element target = result != null ? result.element : null; | |
2749 Element setter = target; | 2748 Element setter = target; |
2750 Element getter = target; | 2749 Element getter = target; |
2751 String operatorName = node.assignmentOperator.source; | 2750 String operatorName = node.assignmentOperator.source; |
2752 String source = operatorName; | 2751 String source = operatorName; |
2753 bool isComplex = !identical(source, '='); | 2752 bool isComplex = !identical(source, '='); |
2754 if (!(registry.isAssert(node) || Elements.isUnresolved(target))) { | 2753 if (!(result is AssertResult || Elements.isUnresolved(target))) { |
2755 if (target.isAbstractField) { | 2754 if (target.isAbstractField) { |
2756 AbstractFieldElement field = target; | 2755 AbstractFieldElement field = target; |
2757 setter = field.setter; | 2756 setter = field.setter; |
2758 getter = field.getter; | 2757 getter = field.getter; |
2759 if (setter == null && !inInstanceContext) { | 2758 if (setter == null && !inInstanceContext) { |
2760 setter = warnAndCreateErroneousElement( | 2759 setter = warnAndCreateErroneousElement( |
2761 node.selector, field.name, MessageKind.CANNOT_RESOLVE_SETTER); | 2760 node.selector, field.name, MessageKind.CANNOT_RESOLVE_SETTER); |
2762 registry.registerThrowNoSuchMethod(); | 2761 registry.registerThrowNoSuchMethod(); |
2763 } | 2762 } |
2764 if (isComplex && getter == null && !inInstanceContext) { | 2763 if (isComplex && getter == null && !inInstanceContext) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2831 registry.registerInstantiatedClass(compiler.intClass); | 2830 registry.registerInstantiatedClass(compiler.intClass); |
2832 } else if (identical(source, '--')) { | 2831 } else if (identical(source, '--')) { |
2833 registerBinaryOperator('-'); | 2832 registerBinaryOperator('-'); |
2834 registry.registerInstantiatedClass(compiler.intClass); | 2833 registry.registerInstantiatedClass(compiler.intClass); |
2835 } else if (source.endsWith('=')) { | 2834 } else if (source.endsWith('=')) { |
2836 registerBinaryOperator(Elements.mapToUserOperator(operatorName)); | 2835 registerBinaryOperator(Elements.mapToUserOperator(operatorName)); |
2837 } | 2836 } |
2838 } | 2837 } |
2839 | 2838 |
2840 registerSend(selector, setter); | 2839 registerSend(selector, setter); |
2841 return registry.useElement(node, setter); | 2840 return new ElementResult(registry.useElement(node, setter)); |
2842 } | 2841 } |
2843 | 2842 |
2844 void registerSend(Selector selector, Element target) { | 2843 void registerSend(Selector selector, Element target) { |
2845 if (target == null || target.isInstanceMember) { | 2844 if (target == null || target.isInstanceMember) { |
2846 if (selector.isGetter) { | 2845 if (selector.isGetter) { |
2847 registry.registerDynamicGetter(selector); | 2846 registry.registerDynamicGetter(selector); |
2848 } else if (selector.isSetter) { | 2847 } else if (selector.isSetter) { |
2849 registry.registerDynamicSetter(selector); | 2848 registry.registerDynamicSetter(selector); |
2850 } else { | 2849 } else { |
2851 registry.registerDynamicInvocation(selector); | 2850 registry.registerDynamicInvocation(selector); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3052 visitLoopBodyIn(node, node.body, new BlockScope(scope)); | 3051 visitLoopBodyIn(node, node.body, new BlockScope(scope)); |
3053 } | 3052 } |
3054 | 3053 |
3055 visitParenthesizedExpression(ParenthesizedExpression node) { | 3054 visitParenthesizedExpression(ParenthesizedExpression node) { |
3056 bool oldSendIsMemberAccess = sendIsMemberAccess; | 3055 bool oldSendIsMemberAccess = sendIsMemberAccess; |
3057 sendIsMemberAccess = false; | 3056 sendIsMemberAccess = false; |
3058 visit(node.expression); | 3057 visit(node.expression); |
3059 sendIsMemberAccess = oldSendIsMemberAccess; | 3058 sendIsMemberAccess = oldSendIsMemberAccess; |
3060 } | 3059 } |
3061 | 3060 |
3062 visitNewExpression(NewExpression node) { | 3061 ResolutionResult visitNewExpression(NewExpression node) { |
3063 Node selector = node.send.selector; | 3062 Node selector = node.send.selector; |
3064 FunctionElement constructor = resolveConstructor(node); | 3063 FunctionElement constructor = resolveConstructor(node); |
3065 final bool isSymbolConstructor = constructor == compiler.symbolConstructor; | 3064 final bool isSymbolConstructor = constructor == compiler.symbolConstructor; |
3066 final bool isMirrorsUsedConstant = | 3065 final bool isMirrorsUsedConstant = |
3067 node.isConst && (constructor == compiler.mirrorsUsedConstructor); | 3066 node.isConst && (constructor == compiler.mirrorsUsedConstructor); |
3068 Selector callSelector = resolveSelector(node.send, constructor); | 3067 Selector callSelector = resolveSelector(node.send, constructor); |
3069 resolveArguments(node.send.argumentsNode); | 3068 resolveArguments(node.send.argumentsNode); |
3070 registry.useElement(node.send, constructor); | 3069 registry.useElement(node.send, constructor); |
3071 if (Elements.isUnresolved(constructor)) return constructor; | 3070 if (Elements.isUnresolved(constructor)) { |
3071 return new ElementResult(constructor); | |
3072 } | |
3072 if (!callSelector.applies(constructor, compiler)) { | 3073 if (!callSelector.applies(constructor, compiler)) { |
3073 registry.registerThrowNoSuchMethod(); | 3074 registry.registerThrowNoSuchMethod(); |
3074 } | 3075 } |
3075 | 3076 |
3076 // [constructor] might be the implementation element | 3077 // [constructor] might be the implementation element |
3077 // and only declaration elements may be registered. | 3078 // and only declaration elements may be registered. |
3078 registry.registerStaticUse(constructor.declaration); | 3079 registry.registerStaticUse(constructor.declaration); |
3079 ClassElement cls = constructor.enclosingClass; | 3080 ClassElement cls = constructor.enclosingClass; |
3080 InterfaceType type = registry.getType(node); | 3081 InterfaceType type = registry.getType(node); |
3081 if (node.isConst && type.containsTypeVariables) { | 3082 if (node.isConst && type.containsTypeVariables) { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3195 /** | 3196 /** |
3196 * Try to resolve the constructor that is referred to by [node]. | 3197 * Try to resolve the constructor that is referred to by [node]. |
3197 * Note: this function may return an ErroneousFunctionElement instead of | 3198 * Note: this function may return an ErroneousFunctionElement instead of |
3198 * [:null:], if there is no corresponding constructor, class or library. | 3199 * [:null:], if there is no corresponding constructor, class or library. |
3199 */ | 3200 */ |
3200 ConstructorElement resolveConstructor(NewExpression node) { | 3201 ConstructorElement resolveConstructor(NewExpression node) { |
3201 return node.accept(new ConstructorResolver(compiler, this)); | 3202 return node.accept(new ConstructorResolver(compiler, this)); |
3202 } | 3203 } |
3203 | 3204 |
3204 ConstructorElement resolveRedirectingFactory(Return node, | 3205 ConstructorElement resolveRedirectingFactory(Return node, |
3205 {bool inConstContext: false}) { | 3206 {bool inConstContext: false}) { |
3206 return node.accept(new ConstructorResolver(compiler, this, | 3207 return node.accept(new ConstructorResolver(compiler, this, |
3207 inConstContext: inConstContext)); | 3208 inConstContext: inConstContext)); |
3208 } | 3209 } |
3209 | 3210 |
3210 DartType resolveTypeAnnotation(TypeAnnotation node, | 3211 DartType resolveTypeAnnotation(TypeAnnotation node, |
3211 {bool malformedIsError: false, | 3212 {bool malformedIsError: false, |
3212 bool deferredIsMalformed: true}) { | 3213 bool deferredIsMalformed: true}) { |
3213 DartType type = typeResolver.resolveTypeAnnotation( | 3214 DartType type = typeResolver.resolveTypeAnnotation( |
3214 this, node, malformedIsError: malformedIsError, | 3215 this, node, malformedIsError: malformedIsError, |
3215 deferredIsMalformed: deferredIsMalformed); | 3216 deferredIsMalformed: deferredIsMalformed); |
3216 if (type == null) return null; | |
3217 if (inCheckContext) { | 3217 if (inCheckContext) { |
3218 registry.registerIsCheck(type); | 3218 registry.registerIsCheck(type); |
3219 registry.registerRequiredType(type, enclosingElement); | 3219 registry.registerRequiredType(type, enclosingElement); |
3220 } | 3220 } |
3221 return type; | 3221 return type; |
3222 } | 3222 } |
3223 | 3223 |
3224 visitModifiers(Modifiers node) { | 3224 visitModifiers(Modifiers node) { |
3225 internalError(node, 'modifiers'); | 3225 internalError(node, 'modifiers'); |
3226 } | 3226 } |
(...skipping 1473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4700 TreeElements _treeElements; | 4700 TreeElements _treeElements; |
4701 | 4701 |
4702 bool get hasTreeElements => _treeElements != null; | 4702 bool get hasTreeElements => _treeElements != null; |
4703 | 4703 |
4704 TreeElements get treeElements { | 4704 TreeElements get treeElements { |
4705 assert(invariant(this, _treeElements !=null, | 4705 assert(invariant(this, _treeElements !=null, |
4706 message: "TreeElements have not been computed for $this.")); | 4706 message: "TreeElements have not been computed for $this.")); |
4707 return _treeElements; | 4707 return _treeElements; |
4708 } | 4708 } |
4709 } | 4709 } |
4710 | |
4711 /// The result of resolving a node. | |
4712 abstract class ResolutionResult { | |
4713 Element get element; | |
4714 } | |
4715 | |
4716 /// The result for the resolution of a node that points to an [Element]. | |
4717 class ElementResult implements ResolutionResult { | |
4718 final Element element; | |
4719 | |
4720 // TODO(johnniwinther): Remove this factory constructor when `null` is never | |
4721 // passed as an element result. | |
4722 factory ElementResult(Element element) { | |
4723 return element != null ? new ElementResult.internal(element) : null; | |
4724 } | |
4725 | |
4726 ElementResult.internal(this.element); | |
4727 | |
4728 String toString() => 'ElementResult($element)'; | |
4729 } | |
4730 | |
4731 /// The result for the resolution of a node that points to an [DartType]. | |
4732 class TypeResult implements ResolutionResult { | |
4733 final DartType type; | |
4734 | |
4735 TypeResult(this.type) { | |
4736 assert(type != null); | |
4737 } | |
4738 | |
4739 Element get element => type.element; | |
4740 | |
4741 String toString() => 'TypeResult($type)'; | |
4742 } | |
4743 | |
4744 /// The result for the resolution of the `assert` method. | |
4745 class AssertResult implements ResolutionResult { | |
4746 const AssertResult(); | |
4747 | |
4748 Element get element => null; | |
4749 | |
4750 String toString() => 'AssertResult()'; | |
4751 } | |
OLD | NEW |