| 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 cf1f65ce2b2ce0dd4beeb6f7adb01f52c40deffa..96961f3d213ceb3e8fb10c8b5a040cf6468dc1dc 100644
|
| --- a/pkg/compiler/lib/src/resolution/members.dart
|
| +++ b/pkg/compiler/lib/src/resolution/members.dart
|
| @@ -1775,6 +1775,145 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| }
|
|
|
| + /// Handle access to a type literal of type variable [element]. Like `T` or
|
| + /// `T()` where 'T' is type variable.
|
| + // TODO(johnniwinther): Remove [name] when [Selector] is not required for the
|
| + // the [GetStructure].
|
| + // TODO(johnniwinther): Remove [element] when it is no longer needed for
|
| + // evaluating constants.
|
| + ResolutionResult handleTypeVariableTypeLiteralAccess(
|
| + Send node,
|
| + Name name,
|
| + TypeVariableElement element) {
|
| + if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
|
| + compiler.reportError(node,
|
| + MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
|
| + {'typeVariableName': node.selector});
|
| + // TODO(johnniwinther): Add another access semantics for this.
|
| + }
|
| + registry.registerClassUsingVariableExpression(element.enclosingClass);
|
| + registry.registerTypeVariableExpression();
|
| +
|
| + AccessSemantics semantics =
|
| + new StaticAccess.typeParameterTypeLiteral(element);
|
| + registry.useElement(node, element);
|
| + registry.registerTypeLiteral(node, element.type);
|
| +
|
| + if (node.isCall) {
|
| + CallStructure callStructure =
|
| + resolveArguments(node.argumentsNode).callStructure;
|
| + Selector selector = callStructure.callSelector;
|
| + // TODO(johnniwinther): Remove this when all information goes through
|
| + // the [SendStructure].
|
| + registry.setSelector(node, selector);
|
| +
|
| + registry.registerSendStructure(node,
|
| + new InvokeStructure(semantics, selector));
|
| + } else {
|
| + // TODO(johnniwinther): Avoid the need for a [Selector] here.
|
| + registry.registerSendStructure(node,
|
| + new GetStructure(semantics,
|
| + new Selector(SelectorKind.GETTER, name, CallStructure.NO_ARGS)));
|
| + }
|
| + return const NoneResult();
|
| + }
|
| +
|
| + /// Handle access to a constant type literal of [type].
|
| + // TODO(johnniwinther): Remove [name] when [Selector] is not required for the
|
| + // the [GetStructure].
|
| + // TODO(johnniwinther): Remove [element] when it is no longer needed for
|
| + // evaluating constants.
|
| + ResolutionResult handleConstantTypeLiteralAccess(
|
| + Send node,
|
| + Name name,
|
| + TypeDeclarationElement element,
|
| + DartType type,
|
| + ConstantAccess semantics) {
|
| + registry.useElement(node, element);
|
| + registry.registerTypeLiteral(node, type);
|
| +
|
| + if (node.isCall) {
|
| + CallStructure callStructure =
|
| + resolveArguments(node.argumentsNode).callStructure;
|
| + Selector selector = callStructure.callSelector;
|
| + // TODO(johnniwinther): Remove this when all information goes through
|
| + // the [SendStructure].
|
| + registry.setSelector(node, selector);
|
| +
|
| + // The node itself is not a constant but we register the selector (the
|
| + // identifier that refers to the class/typedef) as a constant.
|
| + registry.useElement(node.selector, element);
|
| + analyzeConstantDeferred(node.selector, enforceConst: false);
|
| +
|
| + registry.registerSendStructure(node,
|
| + new InvokeStructure(semantics, selector));
|
| + return const NoneResult();
|
| + } else {
|
| + analyzeConstantDeferred(node, enforceConst: false);
|
| +
|
| + // TODO(johnniwinther): Avoid the need for a [Selector] here.
|
| + registry.registerSendStructure(node,
|
| + new GetStructure(semantics,
|
| + new Selector(SelectorKind.GETTER, name, CallStructure.NO_ARGS)));
|
| + return new ConstantResult(node, semantics.constant);
|
| + }
|
| + }
|
| +
|
| + /// Handle access to a type literal of a typedef. Like `F` or
|
| + /// `F()` where 'F' is typedef.
|
| + ResolutionResult handleTypedefTypeLiteralAccess(
|
| + Send node,
|
| + Name name,
|
| + TypedefElement typdef) {
|
| + typdef.ensureResolved(compiler);
|
| + DartType type = typdef.rawType;
|
| + ConstantExpression constant = new TypeConstantExpression(type);
|
| + AccessSemantics semantics = new ConstantAccess.typedefTypeLiteral(constant);
|
| + return handleConstantTypeLiteralAccess(node, name, typdef, type, semantics);
|
| + }
|
| +
|
| + /// Handle access to a type literal of the type 'dynamic'. Like `dynamic` or
|
| + /// `dynamic()`.
|
| + ResolutionResult handleDynamicTypeLiteralAccess(Send node) {
|
| + DartType type = const DynamicType();
|
| + ConstantExpression constant = new TypeConstantExpression(
|
| + // TODO(johnniwinther): Use [type] when evaluation of constants is done
|
| + // directly on the constant expressions.
|
| + node.isCall ? coreTypes.typeType : type);
|
| + AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant);
|
| + return handleConstantTypeLiteralAccess(
|
| + node, const PublicName('dynamic'), compiler.typeClass, type, semantics);
|
| + }
|
| +
|
| + /// Handle access to a type literal of a class. Like `C` or
|
| + /// `C()` where 'C' is class.
|
| + ResolutionResult handleClassTypeLiteralAccess(
|
| + Send node,
|
| + Name name,
|
| + ClassElement cls) {
|
| + DartType type = cls.rawType;
|
| + ConstantExpression constant = new TypeConstantExpression(type);
|
| + AccessSemantics semantics = new ConstantAccess.classTypeLiteral(constant);
|
| + return handleConstantTypeLiteralAccess(node, name, cls, type, semantics);
|
| + }
|
| +
|
| + /// Handle a [Send] that resolves to a [prefix]. Like `prefix` in
|
| + /// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time
|
| + /// error.
|
| + ResolutionResult handleClassSend(
|
| + Send node,
|
| + Name name,
|
| + ClassElement cls) {
|
| + cls.ensureResolved(compiler);
|
| + if (sendIsMemberAccess) {
|
| + registry.useElement(node, cls);
|
| + return new ElementResult(cls);
|
| + } else {
|
| + // `C` or `C()` where 'C' is a class.
|
| + return handleClassTypeLiteralAccess(node, name, cls);
|
| + }
|
| + }
|
| +
|
| /// Handle qualified [Send] where the receiver resolves to a [prefix],
|
| /// like `prefix.toplevelFunction()` or `prefix.Class.staticField` where
|
| /// `prefix` is a library prefix.
|
| @@ -1816,7 +1955,6 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| return new ElementResult(prefix);
|
| }
|
|
|
| -
|
| /// 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(
|
| @@ -1826,7 +1964,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| } else if (element.isClass) {
|
| return handleStaticMemberAccess(node, name, element);
|
| }
|
| - return oldVisitSend(node);
|
| + // TODO(johnniwinther): Use the [element].
|
| + return handleDynamicPropertyAccess(node, name);
|
| }
|
|
|
| /// Handle dynamic access of [semantics].
|
| @@ -2100,6 +2239,15 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // of parse errors to make [element] erroneous. Fix this!
|
| member.computeType(compiler);
|
|
|
| +
|
| + if (member == compiler.mirrorSystemGetNameFunction &&
|
| + !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
|
| + compiler.reportHint(
|
| + node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
|
| + {'class': compiler.mirrorSystemClass.name,
|
| + 'name': compiler.mirrorSystemGetNameFunction.name});
|
| + }
|
| +
|
| Selector selector;
|
| AccessSemantics semantics =
|
| computeStaticOrTopLevelAccessSemantics(node, member);
|
| @@ -2232,10 +2380,14 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| return handleStaticInstanceSend(node, name, element);
|
| }
|
| }
|
| - if (element.isClass || element.isTypedef) {
|
| - return oldVisitSend(node);
|
| + if (element.isClass) {
|
| + // `C`, `C()`, or 'C.b` where 'C' is a class.
|
| + return handleClassSend(node, name, element);
|
| + } else if (element.isTypedef) {
|
| + // `F` or `F()` where 'F' is a typedef.
|
| + return handleTypedefTypeLiteralAccess(node, name, element);
|
| } else if (element.isTypeVariable) {
|
| - return oldVisitSend(node);
|
| + return handleTypeVariableTypeLiteralAccess(node, name, element);
|
| } else if (element.isPrefix) {
|
| return handleLibraryPrefix(node, name, element);
|
| } else if (element.isLocal) {
|
| @@ -2261,16 +2413,16 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| } else if (text == 'this') {
|
| // `this()`.
|
| return handleThisAccess(node);
|
| - } else if (text == 'dynamic') {
|
| - // `dynamic` || `dynamic()`.
|
| - // TODO(johnniwinther): Handle dynamic type literal access.
|
| - return oldVisitSend(node);
|
| }
|
| // `name` or `name()`
|
| Name name = new Name(text, enclosingElement.library);
|
| Element element = lookupInScope(compiler, node, scope, text);
|
| if (element == null) {
|
| - if (inInstanceContext) {
|
| + if (text == 'dynamic') {
|
| + // `dynamic` or `dynamic()` where 'dynamic' is not declared in the
|
| + // current scope.
|
| + return handleDynamicTypeLiteralAccess(node);
|
| + } else if (inInstanceContext) {
|
| // Implicitly `this.name`.
|
| return handleThisPropertyAccess(node, name);
|
| } else {
|
| @@ -2307,101 +2459,6 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| }
|
|
|
| - ResolutionResult oldVisitSend(Send node) {
|
| - bool oldSendIsMemberAccess = sendIsMemberAccess;
|
| - sendIsMemberAccess = node.isPropertyAccess || node.isCall;
|
| -
|
| - ResolutionResult result = resolveSend(node);
|
| - sendIsMemberAccess = oldSendIsMemberAccess;
|
| -
|
| - Element target = result.element;
|
| -
|
| - if (target != null
|
| - && target == compiler.mirrorSystemGetNameFunction
|
| - && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
|
| - compiler.reportHint(
|
| - node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
|
| - {'class': compiler.mirrorSystemClass.name,
|
| - 'name': compiler.mirrorSystemGetNameFunction.name});
|
| - }
|
| -
|
| - if (target != null) {
|
| - if (target.isErroneous) {
|
| - registry.registerThrowNoSuchMethod();
|
| - } else if (target.isAbstractField) {
|
| - AbstractFieldElement field = target;
|
| - target = field.getter;
|
| - if (target == null) {
|
| - if (!inInstanceContext || field.isTopLevel || field.isStatic) {
|
| - registry.registerThrowNoSuchMethod();
|
| - target = reportAndCreateErroneousElement(node.selector, field.name,
|
| - MessageKind.CANNOT_RESOLVE_GETTER, const {});
|
| - }
|
| - }
|
| - } else if (target.isTypeVariable) {
|
| - ClassElement cls = target.enclosingClass;
|
| - assert(enclosingElement.enclosingClass == cls);
|
| - if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
|
| - compiler.reportError(node,
|
| - MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
|
| - {'typeVariableName': node.selector});
|
| - }
|
| - registry.registerClassUsingVariableExpression(cls);
|
| - registry.registerTypeVariableExpression();
|
| - registerTypeLiteralAccess(node, target);
|
| - } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) {
|
| - registerTypeLiteralAccess(node, target);
|
| - }
|
| - registerPotentialAccessInClosure(node, target);
|
| - }
|
| -
|
| - resolveArguments(node.argumentsNode);
|
| -
|
| - // If the selector is null, it means that we will not be generating
|
| - // code for this as a send.
|
| - Selector selector = registry.getSelector(node);
|
| - if (selector == null) return const NoneResult();
|
| -
|
| - if (node.isCall) {
|
| - if (Elements.isUnresolved(target) ||
|
| - target.isGetter ||
|
| - target.isField ||
|
| - Elements.isClosureSend(node, target)) {
|
| - // If we don't know what we're calling or if we are calling a getter,
|
| - // we need to register that fact that we may be calling a closure
|
| - // with the same arguments.
|
| - Selector call = new Selector.callClosureFrom(selector);
|
| - registry.registerDynamicInvocation(
|
| - new UniverseSelector(selector, null));
|
| - } else if (target.impliesType) {
|
| - // We call 'call()' on a Type instance returned from the reference to a
|
| - // class or typedef literal. We do not need to register this call as a
|
| - // dynamic invocation, because we statically know what the target is.
|
| - } else {
|
| - if (target is FunctionElement) {
|
| - FunctionElement function = target;
|
| - function.computeType(compiler);
|
| - }
|
| - if (!selector.applies(target, compiler.world)) {
|
| - registry.registerThrowNoSuchMethod();
|
| - if (node.isSuperCall) {
|
| - internalError(node, "Unexpected super call $node");
|
| - }
|
| - }
|
| - }
|
| -
|
| - handleForeignCall(node, target, selector);
|
| - }
|
| -
|
| - registry.useElement(node, target);
|
| - registerSend(selector, target);
|
| - if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) {
|
| - registry.registerGetOfStaticFunction(target.declaration);
|
| - }
|
| - return node.isPropertyAccess
|
| - ? new ResolutionResult.forElement(target) : const NoneResult();
|
| - }
|
| -
|
| // TODO(johnniwinther): Move this to the backend resolution callbacks.
|
| void handleForeignCall(Send node, Element target, Selector selector) {
|
| if (target != null && compiler.backend.isForeign(target)) {
|
|
|