Index: pkg/compiler/lib/src/resolution/members.dart |
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart |
index 96961f3d213ceb3e8fb10c8b5a040cf6468dc1dc..ea44ed2ca41fcd3f3e2761ab40d116fec0303f8c 100644 |
--- a/pkg/compiler/lib/src/resolution/members.dart |
+++ b/pkg/compiler/lib/src/resolution/members.dart |
@@ -327,7 +327,16 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> { |
ClassElement classElement = element; |
classElement.ensureResolved(compiler); |
} |
- return new ElementResult(registry.useElement(node, element)); |
+ if (element != null) { |
+ registry.useElement(node, element); |
+ if (element.isPrefix) { |
+ return new PrefixResult(element, null); |
+ } else if (element.isClass && sendIsMemberAccess) { |
+ return new PrefixResult(null, element); |
+ } |
+ return new ElementResult(element); |
+ } |
+ return const NoneResult(); |
} |
} |
@@ -1638,7 +1647,6 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> { |
message: "Unexpected unary operator '${operator}'.")); |
return handleUserDefinableUnary(node, operator); |
} |
- return handleUserDefinableUnary(node, operator); |
} |
} else { |
BinaryOperator operator = BinaryOperator.parse(operatorText); |
@@ -1907,29 +1915,60 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> { |
cls.ensureResolved(compiler); |
if (sendIsMemberAccess) { |
registry.useElement(node, cls); |
- return new ElementResult(cls); |
+ return new PrefixResult(null, cls); |
} else { |
// `C` or `C()` where 'C' is a class. |
return handleClassTypeLiteralAccess(node, name, cls); |
} |
} |
+ /// Compute a [DeferredPrefixStructure] for [node]. |
+ ResolutionResult handleDeferredAccess( |
+ Send node, |
+ PrefixElement prefix, |
+ ResolutionResult result) { |
+ assert(invariant(node, prefix.isDeferred, |
+ message: "Prefix $prefix is not deferred.")); |
+ SendStructure sendStructure = registry.getSendStructure(node); |
+ assert(invariant(node, sendStructure != null, |
+ message: "No SendStructure for $node.")); |
+ registry.registerSendStructure(node, |
+ new DeferredPrefixStructure(prefix, sendStructure)); |
+ if (result.isConstant) { |
+ ConstantExpression constant = |
+ new DeferredConstantExpression(result.constant, prefix); |
+ registry.setConstant(node, constant); |
+ result = new ConstantResult(node, constant); |
+ } |
+ return result; |
+ } |
+ |
/// Handle qualified [Send] where the receiver resolves to a [prefix], |
/// like `prefix.toplevelFunction()` or `prefix.Class.staticField` where |
/// `prefix` is a library prefix. |
ResolutionResult handleLibraryPrefixSend( |
Send node, PrefixElement prefix, Name name) { |
+ ResolutionResult result; |
Element member = prefix.lookupLocalMember(name.text); |
if (member == null) { |
registry.registerThrowNoSuchMethod(); |
Element error = reportAndCreateErroneousElement( |
node, name.text, MessageKind.NO_SUCH_LIBRARY_MEMBER, |
{'libraryName': prefix.name, 'memberName': name}); |
- registry.useElement(node, error); |
- return new ElementResult(error); |
+ result = handleUnresolvedAccess(node, name, error); |
} else { |
- return handleResolvedSend(node, name, member); |
+ result = handleResolvedSend(node, name, member); |
+ } |
+ if (result.kind == ResultKind.PREFIX) { |
+ // [member] is a class prefix of a static access like `prefix.Class` of |
+ // `prefix.Class.foo`. No need to call [handleDeferredAccess]; it will |
+ // called on the parent `prefix.Class.foo` node. |
+ result = new PrefixResult(prefix, result.element); |
+ } else if (prefix.isDeferred && |
+ (member == null || !member.isDeferredLoaderGetter)) { |
+ result = handleDeferredAccess(node, prefix, result); |
} |
+ return result; |
} |
/// Handle a [Send] that resolves to a [prefix]. Like `prefix` in |
@@ -1952,20 +1991,24 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> { |
registry.useElement(node.selector, prefix); |
} |
registry.useElement(node, prefix); |
- return new ElementResult(prefix); |
+ return new PrefixResult(prefix, null); |
} |
/// Handle qualified [Send] where the receiver resolves to an [Element], like |
- /// `a.b` where `a` is a local, field, class, or prefix, etc. |
- ResolutionResult handleResolvedQualifiedSend( |
- Send node, Name name, Element element) { |
+ /// `a.b` where `a` is a prefix or a class. |
+ ResolutionResult handlePrefixSend( |
+ Send node, Name name, PrefixResult prefixResult) { |
+ Element element = prefixResult.element; |
if (element.isPrefix) { |
return handleLibraryPrefixSend(node, element, name); |
- } else if (element.isClass) { |
- return handleStaticMemberAccess(node, name, element); |
+ } else { |
+ assert(element.isClass); |
+ ResolutionResult result = handleStaticMemberAccess(node, name, element); |
+ if (prefixResult.isDeferred) { |
+ result = handleDeferredAccess(node, prefixResult.prefix, result); |
+ } |
+ return result; |
} |
- // TODO(johnniwinther): Use the [element]. |
- return handleDynamicPropertyAccess(node, name); |
} |
/// Handle dynamic access of [semantics]. |
@@ -2045,9 +2088,10 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> { |
return handleConditionalAccess(node, name); |
} |
ResolutionResult result = visitExpressionPrefix(node.receiver); |
- if (result.element != null) { |
- return handleResolvedQualifiedSend(node, name, result.element); |
+ if (result.kind == ResultKind.PREFIX) { |
+ return handlePrefixSend(node, name, result); |
} else { |
+ // TODO(johnniwinther): Use the `element` of [result]. |
return handleDynamicPropertyAccess(node, name); |
} |
} |
@@ -2448,7 +2492,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> { |
} |
} |
- /// Regigster read access of [target] inside a closure. |
+ /// Register read access of [target] inside a closure. |
void registerPotentialAccessInClosure(Send node, Element target) { |
if (isPotentiallyMutableTarget(target)) { |
if (enclosingElement != target.enclosingElement) { |