| Index: dart/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| diff --git a/dart/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/dart/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| index f9409837c9825d94873af53612bb98c80c2b8ce4..cb5811e80bbe66ab8f6b6e4a5f9e9484c7ee1dcd 100644
|
| --- a/dart/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| +++ b/dart/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| @@ -5,6 +5,12 @@
|
| part of resolution;
|
|
|
| abstract class TreeElements {
|
| + Element get currentElement;
|
| + Set<Node> get superUses;
|
| +
|
| + /// A set of additional dependencies. See [registerDependency] below.
|
| + Set<Element> get otherDependencies;
|
| +
|
| Element operator[](Node node);
|
| Selector getSelector(Send send);
|
| Selector getGetterSelectorInComplexSendSet(SendSet node);
|
| @@ -14,7 +20,10 @@ abstract class TreeElements {
|
| Selector getCurrentSelector(ForIn node);
|
| DartType getType(Node node);
|
| bool isParameterChecked(Element element);
|
| - Set<Node> get superUses;
|
| +
|
| + /// Register additional dependencies required by [currentElement].
|
| + /// For example, elements that are used by a backend.
|
| + void registerDependency(Element element);
|
| }
|
|
|
| class TreeElementMapping implements TreeElements {
|
| @@ -22,8 +31,11 @@ class TreeElementMapping implements TreeElements {
|
| final Map<Spannable, Selector> selectors =
|
| new LinkedHashMap<Spannable, Selector>();
|
| final Map<Node, DartType> types = new LinkedHashMap<Node, DartType>();
|
| - final Set<Element> checkedParameters = new Set<Element>();
|
| - final Set<Node> superUses = new Set<Node>();
|
| + final Set<Element> checkedParameters = new LinkedHashSet<Element>();
|
| + final Set<Node> superUses = new LinkedHashSet<Node>();
|
| + final Set<Element> otherDependencies = new LinkedHashSet<Element>();
|
| + final int hashCode = ++hashCodeCounter;
|
| + static int hashCodeCounter = 0;
|
|
|
| TreeElementMapping(this.currentElement);
|
|
|
| @@ -118,6 +130,12 @@ class TreeElementMapping implements TreeElements {
|
| bool isParameterChecked(Element element) {
|
| return checkedParameters.contains(element);
|
| }
|
| +
|
| + void registerDependency(Element element) {
|
| + otherDependencies.add(element.implementation);
|
| + }
|
| +
|
| + String toString() => 'TreeElementMapping($currentElement)';
|
| }
|
|
|
| class ResolverTask extends CompilerTask {
|
| @@ -444,7 +462,7 @@ class ResolverTask extends CompilerTask {
|
| if (tree.asSendSet() != null) {
|
| // TODO(ngeoffray): We could do better here by using the
|
| // constant handler to figure out if it's a lazy field or not.
|
| - compiler.backend.registerLazyField();
|
| + compiler.backend.registerLazyField(visitor.mapping);
|
| }
|
| }
|
|
|
| @@ -1538,7 +1556,9 @@ class TypeResolver {
|
| }
|
| } else if (element.isTypeVariable()) {
|
| if (enclosingElement.isInStaticMember()) {
|
| - compiler.backend.registerThrowRuntimeError();
|
| + compiler.backend.registerThrowRuntimeError(
|
| + // TODO(ahe): Get the TreeElements for the current element.
|
| + compiler.globalDependencies);
|
| compiler.reportWarning(node,
|
| MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message(
|
| {'typeVariableName': node}));
|
| @@ -1729,7 +1749,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| element = warnAndCreateErroneousElement(node, node.source,
|
| MessageKind.CANNOT_RESOLVE,
|
| {'name': node});
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| }
|
| } else if (element.isErroneous()) {
|
| // Use the erroneous element.
|
| @@ -1752,7 +1772,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| DartType type = resolveTypeAnnotation(node);
|
| if (type != null) {
|
| if (inCheckContext) {
|
| - compiler.enqueuer.resolution.registerIsCheck(type);
|
| + compiler.enqueuer.resolution.registerIsCheck(type, mapping);
|
| }
|
| return type.element;
|
| }
|
| @@ -1943,7 +1963,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| scope = oldScope;
|
| enclosingElement = previousEnclosingElement;
|
|
|
| - world.registerInstantiatedClass(compiler.functionClass);
|
| + world.registerInstantiatedClass(compiler.functionClass, mapping);
|
| }
|
|
|
| visitIf(If node) {
|
| @@ -2021,7 +2041,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| // call [:super.noSuchMethod:] that does a
|
| // [:InvocationMirror.invokeOn:].
|
| world.registerDynamicInvocation(selector.name, selector);
|
| - compiler.backend.registerSuperNoSuchMethod();
|
| + compiler.backend.registerSuperNoSuchMethod(mapping);
|
| }
|
| } else if (Elements.isUnresolved(resolvedReceiver)) {
|
| return null;
|
| @@ -2039,7 +2059,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
| target = receiverClass.lookupLocalMember(name);
|
| if (target == null || target.isInstanceMember()) {
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| // TODO(johnniwinther): With the simplified [TreeElements] invariant,
|
| // try to resolve injected elements if [currentClass] is in the patch
|
| // library of [receiverClass].
|
| @@ -2058,7 +2078,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| PrefixElement prefix = resolvedReceiver;
|
| target = prefix.lookupLocalMember(name);
|
| if (Elements.isUnresolved(target)) {
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| return warnAndCreateErroneousElement(
|
| node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER,
|
| {'libraryName': prefix.name, 'memberName': name});
|
| @@ -2173,13 +2193,13 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| AbstractFieldElement field = target;
|
| target = field.getter;
|
| if (target == null && !inInstanceContext) {
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| target =
|
| warnAndCreateErroneousElement(node.selector, field.name,
|
| MessageKind.CANNOT_RESOLVE_GETTER);
|
| }
|
| } else if (target.impliesType() && !sendIsMemberAccess) {
|
| - compiler.backend.registerTypeLiteral();
|
| + compiler.backend.registerTypeLiteral(mapping);
|
| }
|
| }
|
|
|
| @@ -2191,9 +2211,9 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| DartType type = resolveTypeTest(node.arguments.head);
|
| if (type != null) {
|
| if (operatorString == 'as') {
|
| - compiler.enqueuer.resolution.registerAsCheck(type);
|
| + compiler.enqueuer.resolution.registerAsCheck(type, mapping);
|
| } else {
|
| - compiler.enqueuer.resolution.registerIsCheck(type);
|
| + compiler.enqueuer.resolution.registerIsCheck(type, mapping);
|
| }
|
| }
|
| resolvedArguments = true;
|
| @@ -2247,13 +2267,13 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| registerSend(selector, target);
|
| if (node.isPropertyAccess) {
|
| // It might be the closurization of a method.
|
| - world.registerInstantiatedClass(compiler.functionClass);
|
| + world.registerInstantiatedClass(compiler.functionClass, mapping);
|
| }
|
| return node.isPropertyAccess ? target : null;
|
| }
|
|
|
| void warnArgumentMismatch(Send node, Element target) {
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| // TODO(karlklose): we can be more precise about the reason of the
|
| // mismatch.
|
| warning(node.argumentsNode, MessageKind.INVALID_ARGUMENTS,
|
| @@ -2284,19 +2304,19 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| if (setter == null && !inInstanceContext) {
|
| setter = warnAndCreateErroneousElement(
|
| node.selector, field.name, MessageKind.CANNOT_RESOLVE_SETTER);
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| }
|
| if (isComplex && getter == null && !inInstanceContext) {
|
| getter = warnAndCreateErroneousElement(
|
| node.selector, field.name, MessageKind.CANNOT_RESOLVE_GETTER);
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| }
|
| } else if (target.impliesType()) {
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| } else if (target.modifiers.isFinal() || target.modifiers.isConst()) {
|
| setter = warnAndCreateErroneousElement(
|
| node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER);
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| }
|
| }
|
|
|
| @@ -2323,7 +2343,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| target = warnAndCreateErroneousElement(
|
| node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
|
| {'className': currentClass, 'memberName': selector.name});
|
| - compiler.backend.registerSuperNoSuchMethod();
|
| + compiler.backend.registerSuperNoSuchMethod(mapping);
|
| }
|
| }
|
| useElement(node.selector, getter);
|
| @@ -2369,27 +2389,27 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| visitLiteralInt(LiteralInt node) {
|
| - world.registerInstantiatedClass(compiler.intClass);
|
| + world.registerInstantiatedClass(compiler.intClass, mapping);
|
| }
|
|
|
| visitLiteralDouble(LiteralDouble node) {
|
| - world.registerInstantiatedClass(compiler.doubleClass);
|
| + world.registerInstantiatedClass(compiler.doubleClass, mapping);
|
| }
|
|
|
| visitLiteralBool(LiteralBool node) {
|
| - world.registerInstantiatedClass(compiler.boolClass);
|
| + world.registerInstantiatedClass(compiler.boolClass, mapping);
|
| }
|
|
|
| visitLiteralString(LiteralString node) {
|
| - world.registerInstantiatedClass(compiler.stringClass);
|
| + world.registerInstantiatedClass(compiler.stringClass, mapping);
|
| }
|
|
|
| visitLiteralNull(LiteralNull node) {
|
| - world.registerInstantiatedClass(compiler.nullClass);
|
| + world.registerInstantiatedClass(compiler.nullClass, mapping);
|
| }
|
|
|
| visitStringJuxtaposition(StringJuxtaposition node) {
|
| - world.registerInstantiatedClass(compiler.stringClass);
|
| + world.registerInstantiatedClass(compiler.stringClass, mapping);
|
| node.visitChildren(this);
|
| }
|
|
|
| @@ -2445,14 +2465,14 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
| world.registerStaticUse(redirectionTarget);
|
| world.registerInstantiatedClass(
|
| - redirectionTarget.enclosingElement.declaration);
|
| + redirectionTarget.enclosingElement.declaration, mapping);
|
| }
|
|
|
| visitThrow(Throw node) {
|
| if (!inCatchBlock && node.expression == null) {
|
| error(node, MessageKind.THROW_WITHOUT_EXPRESSION);
|
| }
|
| - compiler.backend.registerThrow();
|
| + compiler.backend.registerThrow(mapping);
|
| visit(node.expression);
|
| }
|
|
|
| @@ -2494,7 +2514,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| Selector callSelector = mapping.getSelector(node.send);
|
| if (!callSelector.applies(constructor, compiler)) {
|
| warnArgumentMismatch(node.send, constructor);
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(mapping);
|
| }
|
| compiler.withCurrentElement(constructor, () {
|
| FunctionExpression tree = constructor.parseNode(compiler);
|
| @@ -2506,7 +2526,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| // TODO(ngeoffray): Remove once we remove such support.
|
| world.registerStaticUse(constructor.declaration);
|
| world.registerInstantiatedClass(
|
| - constructor.getEnclosingClass().declaration);
|
| + constructor.getEnclosingClass().declaration, mapping);
|
| constructor = constructor.defaultImplementation;
|
| }
|
| // [constructor.defaultImplementation] might be the implementation element
|
| @@ -2515,9 +2535,9 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| ClassElement cls = constructor.getEnclosingClass();
|
| // [cls] might be the implementation element and only declaration elements
|
| // may be registered.
|
| - world.registerInstantiatedType(mapping.getType(node));
|
| + world.registerInstantiatedType(mapping.getType(node), mapping);
|
| if (cls.isAbstract(compiler)) {
|
| - compiler.backend.registerAbstractClassInstantiation();
|
| + compiler.backend.registerAbstractClassInstantiation(mapping);
|
| }
|
| // [cls] might be the declaration element and we want to include injected
|
| // members.
|
| @@ -2576,7 +2596,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| onFailure: report, whenResolved: useType);
|
| if (type == null) return null;
|
| if (inCheckContext) {
|
| - compiler.enqueuer.resolution.registerIsCheck(type);
|
| + compiler.enqueuer.resolution.registerIsCheck(type, mapping);
|
| }
|
| if (typeRequired || inCheckContext) {
|
| if (type is InterfaceType) {
|
| @@ -2617,7 +2637,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| } else {
|
| listType = compiler.listClass.rawType;
|
| }
|
| - world.registerInstantiatedType(listType);
|
| + world.registerInstantiatedType(listType, mapping);
|
| visit(node.elements);
|
| }
|
|
|
| @@ -2626,8 +2646,8 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| visitStringInterpolation(StringInterpolation node) {
|
| - world.registerInstantiatedClass(compiler.stringClass);
|
| - compiler.backend.registerStringInterpolation();
|
| + world.registerInstantiatedClass(compiler.stringClass, mapping);
|
| + compiler.backend.registerStringInterpolation(mapping);
|
| node.visitChildren(this);
|
| }
|
|
|
| @@ -2772,9 +2792,9 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| visitLiteralMap(LiteralMap node) {
|
| - world.registerInstantiatedClass(compiler.mapClass);
|
| + world.registerInstantiatedClass(compiler.mapClass, mapping);
|
| if (node.isConst()) {
|
| - compiler.backend.registerConstantMap();
|
| + compiler.backend.registerConstantMap(mapping);
|
| }
|
| node.visitChildren(this);
|
| }
|
| @@ -2855,7 +2875,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| });
|
| // TODO(ngeoffray): We should check here instead of the SSA backend if
|
| // there might be an error.
|
| - compiler.backend.registerFallThroughError();
|
| + compiler.backend.registerFallThroughError(mapping);
|
| }
|
|
|
| visitSwitchCase(SwitchCase node) {
|
| @@ -2879,7 +2899,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| visitCatchBlock(CatchBlock node) {
|
| - compiler.backend.registerCatchStatement();
|
| + compiler.backend.registerCatchStatement(mapping);
|
| // Check that if catch part is present, then
|
| // it has one or two formal parameters.
|
| if (node.formals != null) {
|
| @@ -2892,7 +2912,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| error(extra, MessageKind.EXTRA_CATCH_DECLARATION);
|
| }
|
| }
|
| - compiler.backend.registerStackTraceInCatch();
|
| + compiler.backend.registerStackTraceInCatch(mapping);
|
| }
|
|
|
| // Check that the formals aren't optional and that they have no
|
| @@ -3437,7 +3457,8 @@ class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
|
|
|
| SourceString visitIdentifier(Identifier node) {
|
| // The variable is initialized to null.
|
| - resolver.world.registerInstantiatedClass(compiler.nullClass);
|
| + resolver.world.registerInstantiatedClass(compiler.nullClass,
|
| + resolver.mapping);
|
| return node.source;
|
| }
|
|
|
| @@ -3676,9 +3697,9 @@ class ConstructorResolver extends CommonResolverVisitor<Element> {
|
| SourceString targetName, MessageKind kind,
|
| Map arguments) {
|
| if (kind == MessageKind.CANNOT_FIND_CONSTRUCTOR) {
|
| - compiler.backend.registerThrowNoSuchMethod();
|
| + compiler.backend.registerThrowNoSuchMethod(resolver.mapping);
|
| } else {
|
| - compiler.backend.registerThrowRuntimeError();
|
| + compiler.backend.registerThrowRuntimeError(resolver.mapping);
|
| }
|
| if (inConstContext) {
|
| error(diagnosticNode, kind, arguments);
|
|
|