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

Unified Diff: pkg/compiler/lib/src/resolution/members.dart

Issue 1293953006: Refactor qualified send sets. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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 side-by-side diff with in-line comments
Download patch
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 142f5e6b46423a804d4d7d73e51d2aac965dce26..24ea86acaaee2387d9165f6bf96055235f8f4d12 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -639,148 +639,6 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
return const NoneResult();
}
- ResolutionResult resolveSend(Send node) {
- Selector selector = resolveSelector(node, null);
- if (node.isSuperCall) registry.registerSuperUse(node);
-
- if (node.receiver == null) {
- // If this send is of the form "assert(expr);", then
- // this is an assertion.
- if (selector.isAssert) {
- internalError(node, "Unexpected assert: $node");
- }
-
- return node.selector.accept(this);
- }
-
- var oldCategory = allowedCategory;
- allowedCategory |= ElementCategory.PREFIX | ElementCategory.SUPER;
-
- bool oldSendIsMemberAccess = sendIsMemberAccess;
- int oldAllowedCategory = allowedCategory;
-
- // Conditional sends like `e?.foo` treat the receiver as an expression. So
- // `C?.foo` needs to be treated like `(C).foo`, not like C.foo. Prefixes and
- // super are not allowed on their own in that context.
- if (node.isConditional) {
- sendIsMemberAccess = false;
- allowedCategory =
- ElementCategory.VARIABLE |
- ElementCategory.FUNCTION |
- ElementCategory.IMPLIES_TYPE;
- }
- ResolutionResult resolvedReceiver = visit(node.receiver);
- if (node.isConditional) {
- sendIsMemberAccess = oldSendIsMemberAccess;
- allowedCategory = oldAllowedCategory;
- }
-
- allowedCategory = oldCategory;
-
- Element target;
- String name = node.selector.asIdentifier().source;
- if (identical(name, 'this')) {
- error(node.selector, MessageKind.THIS_PROPERTY);
- return const NoneResult();
- } else if (node.isSuperCall) {
- if (node.isOperator) {
- if (isUserDefinableOperator(name)) {
- name = selector.name;
- } else {
- error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, {'name': name});
- return const NoneResult();
- }
- }
- if (!inInstanceContext) {
- error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, {'name': name});
- return const NoneResult();
- }
- if (currentClass.supertype == null) {
- // This is just to guard against internal errors, so no need
- // for a real error message.
- error(node.receiver, MessageKind.GENERIC,
- {'text': "Object has no superclass"});
- return const NoneResult();
- }
- // TODO(johnniwinther): Ensure correct behavior if currentClass is a
- // patch.
- target = currentClass.lookupSuperByName(selector.memberName);
- // [target] may be null which means invoking noSuchMethod on
- // super.
- if (target == null) {
- target = reportAndCreateErroneousElement(
- node, name, MessageKind.NO_SUCH_SUPER_MEMBER,
- {'className': currentClass.name, 'memberName': name});
- // We still need to register the invocation, because we might
- // call [:super.noSuchMethod:] which calls
- // [JSInvocationMirror._invokeOn].
- registry.registerDynamicInvocation(
- new UniverseSelector(selector, null));
- registry.registerSuperNoSuchMethod();
- }
- } else if (Elements.isUnresolved(resolvedReceiver.element)) {
- return const NoneResult();
- } else if (resolvedReceiver.element.isClass) {
- ClassElement receiverClass = resolvedReceiver.element;
- receiverClass.ensureResolved(compiler);
- if (node.isOperator) {
- // When the resolved receiver is a class, we can have two cases:
- // 1) a static send: C.foo, or
- // 2) an operator send, where the receiver is a class literal: 'C + 1'.
- // The following code that looks up the selector on the resolved
- // receiver will treat the second as the invocation of a static operator
- // if the resolved receiver is not null.
- return const NoneResult();
- }
- MembersCreator.computeClassMembersByName(
- compiler, receiverClass.declaration, name);
- target = receiverClass.lookupLocalMember(name);
- if (target == null || target.isInstanceMember) {
- registry.registerThrowNoSuchMethod();
- // TODO(johnniwinther): With the simplified [TreeElements] invariant,
- // try to resolve injected elements if [currentClass] is in the patch
- // library of [receiverClass].
-
- // TODO(karlklose): this should be reported by the caller of
- // [resolveSend] to select better warning messages for getters and
- // setters.
- MessageKind kind = (target == null)
- ? MessageKind.MEMBER_NOT_FOUND
- : MessageKind.MEMBER_NOT_STATIC;
- return new ElementResult(reportAndCreateErroneousElement(
- node, name, kind,
- {'className': receiverClass.name, 'memberName': name}));
- } else if (isPrivateName(name) &&
- target.library != enclosingElement.library) {
- registry.registerThrowNoSuchMethod();
- return new ElementResult(reportAndCreateErroneousElement(
- node, name, MessageKind.PRIVATE_ACCESS,
- {'libraryName': target.library.getLibraryOrScriptName(),
- 'name': name}));
- }
- } else if (resolvedReceiver.element.isPrefix) {
- PrefixElement prefix = resolvedReceiver.element;
- target = prefix.lookupLocalMember(name);
- if (Elements.isUnresolved(target)) {
- registry.registerThrowNoSuchMethod();
- return new ElementResult(reportAndCreateErroneousElement(
- node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER,
- {'libraryName': prefix.name, 'memberName': name}));
- } else if (target.isAmbiguous) {
- registry.registerThrowNoSuchMethod();
- AmbiguousElement ambiguous = target;
- target = reportAndCreateErroneousElement(
- node, name, ambiguous.messageKind, ambiguous.messageArguments);
- ambiguous.diagnose(enclosingElement, compiler);
- return new ElementResult(target);
- } else if (target.kind == ElementKind.CLASS) {
- ClassElement classElement = target;
- classElement.ensureResolved(compiler);
- }
- }
- return new ResolutionResult.forElement(target);
- }
-
static Selector computeSendSelector(Send node,
LibraryElement library,
Element element) {
@@ -900,47 +758,6 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
isValidAsConstant: isValidAsConstant);
}
- void registerTypeLiteralAccess(Send node, Element target) {
- // Set the type of the node to [Type] to mark this send as a
- // type literal.
- DartType type;
-
- // TODO(johnniwinther): Remove this hack when we can pass more complex
- // information between methods than resolved elements.
- if (target == compiler.typeClass && node.receiver == null) {
- // Potentially a 'dynamic' type literal.
- type = registry.getType(node.selector);
- }
- if (type == null) {
- if (target.isTypedef || target.isClass) {
- TypeDeclarationElement typeDeclaration = target;
- typeDeclaration.computeType(compiler);
- type = typeDeclaration.rawType;
- } else {
- TypeVariableElement typeVariable = target;
- type = typeVariable.type;
- }
- }
- registry.registerTypeLiteral(node, type);
-
- if (!target.isTypeVariable) {
- // Don't try to make constants of calls and assignments to type literals.
- if (!node.isCall && node.asSendSet() == null) {
- analyzeConstantDeferred(node, enforceConst: false);
- } else {
- // The node itself is not a constant but we register the selector (the
- // identifier that refers to the class/typedef) as a constant.
- if (node.receiver != null) {
- // This is a hack for the case of prefix.Type, we need to store
- // the element on the selector, so [analyzeConstant] can build
- // the type literal from the selector.
- registry.useElement(node.selector, target);
- }
- analyzeConstantDeferred(node.selector, enforceConst: false);
- }
- }
- }
-
/// Check that access to `super` is currently allowed. Returns an
/// [AccessSemantics] in case of an error, `null` otherwise.
AccessSemantics checkSuperAccess(Send node) {
@@ -1947,6 +1764,29 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
node, name, new StaticAccess.unresolved(error));
}
+ /// Handle qualified update to an unresolved static class member, like
+ /// `a.b = c` or `a.b++` where `a` is a class and `b` is unresolved.
+ ResolutionResult handleUnresolvedStaticMemberUpdate(
+ SendSet node, Name name, ClassElement receiverClass) {
+ // TODO(johnniwinther): Share code with [handleStaticInstanceMemberUpdate]
+ // and [handlePrivateStaticMemberUpdate].
+ registry.registerThrowNoSuchMethod();
+ // TODO(johnniwinther): Produce a different error if [name] is resolves to
+ // a constructor.
+
+ // TODO(johnniwinther): With the simplified [TreeElements] invariant,
+ // try to resolve injected elements if [currentClass] is in the patch
+ // library of [receiverClass].
+
+ // TODO(johnniwinther): Produce a different error for complex update.
+ ErroneousElement error = reportAndCreateErroneousElement(
+ node, name.text, MessageKind.MEMBER_NOT_FOUND,
+ {'className': receiverClass.name, 'memberName': name.text});
+ // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
+ // member access.
+ return handleUpdate(node, name, new StaticAccess.unresolved(error));
+ }
+
/// Handle qualified access of an instance member, like `a.b` or `a.b()` where
/// `a` is a class and `b` is a non-static member.
ResolutionResult handleStaticInstanceMemberAccess(
@@ -1970,8 +1810,28 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
node, name, new StaticAccess.unresolved(error));
}
+ /// Handle qualified update of an instance member, like `a.b = c` or `a.b++`
+ /// where `a` is a class and `b` is a non-static member.
+ ResolutionResult handleStaticInstanceMemberUpdate(
+ SendSet node, Name name, ClassElement receiverClass, Element member) {
+
+ registry.registerThrowNoSuchMethod();
+ // TODO(johnniwinther): With the simplified [TreeElements] invariant,
+ // try to resolve injected elements if [currentClass] is in the patch
+ // library of [receiverClass].
+
+ // TODO(johnniwinther): Produce a different error for complex update.
+ ErroneousElement error = reportAndCreateErroneousElement(
+ node, name.text, MessageKind.MEMBER_NOT_STATIC,
+ {'className': receiverClass.name, 'memberName': name});
+
+ // TODO(johnniwinther): Add an [AccessSemantics] for statically accessed
+ // instance members.
+ return handleUpdate(node, name, new StaticAccess.unresolved(error));
+ }
+
/// Handle qualified access of an inaccessible private static class member,
- /// like `a._b` or `a.b()` where `a` is class, `_b` is static member of `a`
+ /// like `a._b` or `a._b()` where `a` is class, `_b` is static member of `a`
/// but `a` is not defined in the current library.
ResolutionResult handlePrivateStaticMemberAccess(
Send node, Name name, ClassElement receiverClass, Element member) {
@@ -1986,6 +1846,21 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
node, name, new StaticAccess.unresolved(error));
}
+ /// Handle qualified update of an inaccessible private static class member,
+ /// like `a._b = c` or `a._b++` where `a` is class, `_b` is static member of
+ /// `a` but `a` is not defined in the current library.
+ ResolutionResult handlePrivateStaticMemberUpdate(
+ SendSet node, Name name, ClassElement receiverClass, Element member) {
+ registry.registerThrowNoSuchMethod();
+ ErroneousElement error = reportAndCreateErroneousElement(
+ node, name.text, MessageKind.PRIVATE_ACCESS,
+ {'libraryName': member.library.getLibraryOrScriptName(),
+ 'name': name});
+ // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
+ // member access.
+ return handleUpdate(node, name, new StaticAccess.unresolved(error));
+ }
+
/// Handle qualified access to a static member, like `a.b` or `a.b()` where
/// `a` is a class and `b` is a static member of `a`.
ResolutionResult handleStaticMemberAccess(
@@ -2020,6 +1895,31 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
}
+ /// Handle qualified update to a static member, like `a.b = c` or `a.b++`
+ /// where `a` is a class and `b` is a static member of `a`.
+ ResolutionResult handleStaticMemberUpdate(
+ Send node, Name memberName, ClassElement receiverClass) {
+ String name = memberName.text;
+ receiverClass.ensureResolved(compiler);
+ MembersCreator.computeClassMembersByName(
+ compiler, receiverClass.declaration, name);
+ Element member = receiverClass.lookupLocalMember(name);
+ if (member == null) {
+ return handleUnresolvedStaticMemberUpdate(
+ node, memberName, receiverClass);
+ } else if (member.isAmbiguous) {
+ return handleAmbiguousUpdate(node, memberName, member);
+ } else if (member.isInstanceMember) {
+ return handleStaticInstanceMemberUpdate(
+ node, memberName, receiverClass, member);
+ } else if (memberName.isPrivate && memberName.library != member.library) {
+ return handlePrivateStaticMemberUpdate(
+ node, memberName, receiverClass, member);
+ } else {
+ return handleStaticOrTopLevelUpdate(node, memberName, member);
+ }
+ }
+
/// 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
@@ -2331,6 +2231,34 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
return result;
}
+ /// Handle qualified [SendSet] where the receiver resolves to a [prefix],
+ /// like `prefix.toplevelField = b` or `prefix.Class.staticField++` where
+ /// `prefix` is a library prefix.
+ ResolutionResult handleLibraryPrefixSendSet(
+ SendSet node, Name name, PrefixElement prefix) {
+ 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});
+ return handleUpdate(node, name, new StaticAccess.unresolved(error));
+ } else {
+ result = handleResolvedSendSet(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
/// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time
/// error.
@@ -2378,6 +2306,27 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
}
+ /// Handle qualified [SendSet] where the receiver resolves to an [Element],
+ /// like `a.b = c` where `a` is a prefix or a class.
+ ResolutionResult handlePrefixSendSet(
+ SendSet node, Name name, PrefixResult prefixResult) {
+ Element element = prefixResult.element;
+ if (element.isPrefix) {
+ if (node.isConditional) {
+ return handleLibraryPrefix(node, name, element);
+ } else {
+ return handleLibraryPrefixSendSet(node, name, element);
+ }
+ } else {
+ assert(element.isClass);
+ ResolutionResult result = handleStaticMemberUpdate(node, name, element);
+ if (prefixResult.isDeferred) {
+ result = handleDeferredAccess(node, prefixResult.prefix, result);
+ }
+ return result;
+ }
+ }
+
/// Handle dynamic access of [semantics].
ResolutionResult handleDynamicAccessSemantics(
Send node, Name name, AccessSemantics semantics) {
@@ -2482,6 +2431,37 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
}
+ /// Handle a qualified [SendSet], that is where the receiver is non-null, like
+ /// `a.b = c`, `a.b++`, and `a.b += c`.
+ ResolutionResult handleQualifiedSendSet(SendSet node) {
+ Identifier selector = node.selector.asIdentifier();
+ String text = selector.source;
+ Name name = new Name(text, enclosingElement.library);
+ if (text == 'this') {
floitsch 2015/08/20 16:28:34 That feels like a weird check. Is it for captured
Johnni Winther 2015/08/21 07:17:36 This is for cases like 'C.this' for which there is
floitsch 2015/08/21 09:27:50 Ah... Didn't realize this was the selector and not
+ return handleQualifiedThisAccess(node, name);
+ } else if (node.receiver.isThis()) {
+ if (checkThisAccess(node)) {
+ return handleThisPropertyUpdate(node, name, null);
+ }
+ // TODO(johnniwinther): Handle invalid this access as an
+ // [AccessSemantics].
+ return const NoneResult();
+ }
+ ResolutionResult result = visitExpressionPrefix(node.receiver);
+ if (result.kind == ResultKind.PREFIX) {
+ return handlePrefixSendSet(node, name, result);
+ } else if (node.isConditional) {
+ return handleDynamicUpdateSemantics(
+ node, name, null, const DynamicAccess.ifNotNullProperty());
+ } else {
+ // Handle dynamic property access, like `a.b = c`, `a.b++` or `a.b += c`
+ // where `a` is not a prefix or class.
+ // TODO(johnniwinther): Use the `element` of [result].
+ return handleDynamicUpdateSemantics(
+ node, name, null, const DynamicAccess.dynamicProperty());
+ }
+ }
+
/// Handle access unresolved access to [name] in a non-instance context.
ResolutionResult handleUnresolvedAccess(
Send node, Name name, Element element) {
@@ -3030,7 +3010,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
} else if (element.isStatic || element.isTopLevel) {
return handleStaticOrTopLevelUpdate(node, name, element);
}
- return oldVisitSendSet(node);
+ return internalError(node, "Unexpected resolved send: $element");
}
/// Handle an unqualified [Send], that is where the `node.receiver` is null,
@@ -3499,150 +3479,23 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
ResolutionResult visitSendSet(SendSet node) {
if (node.isIndex) {
+ // `a[b] = c`
if (node.isSuperCall) {
+ // `super[b] = c`
return handleSuperIndexSendSet(node);
} else {
return handleIndexSendSet(node);
}
} else if (node.isSuperCall) {
+ // `super.a = c`
return handleSuperSendSet(node);
} else if (node.receiver == null) {
+ // `a = c`
return handleUnqualifiedSendSet(node);
+ } else {
+ // `a.b = c`
+ return handleQualifiedSendSet(node);
}
- return oldVisitSendSet(node);
- }
-
- ResolutionResult oldVisitSendSet(SendSet node) {
- bool oldSendIsMemberAccess = sendIsMemberAccess;
- sendIsMemberAccess = node.isPropertyAccess || node.isCall;
- ResolutionResult result = resolveSend(node);
- sendIsMemberAccess = oldSendIsMemberAccess;
- Element target = result.element;
- Element setter = target;
- Element getter = target;
- String operatorName = node.assignmentOperator.source;
- String source = operatorName;
- bool isComplex = !identical(source, '=');
- if (!(result is AssertResult || Elements.isUnresolved(target))) {
- if (target.isAbstractField) {
- AbstractFieldElement field = target;
- setter = field.setter;
- getter = field.getter;
- if (setter == null) {
- if (!inInstanceContext || getter.isTopLevel || getter.isStatic) {
- setter = reportAndCreateErroneousElement(node.selector, field.name,
- MessageKind.CANNOT_RESOLVE_SETTER, const {});
- registry.registerThrowNoSuchMethod();
- }
- }
- if (isComplex && getter == null && !inInstanceContext) {
- getter = reportAndCreateErroneousElement(node.selector, field.name,
- MessageKind.CANNOT_RESOLVE_GETTER, const {});
- registry.registerThrowNoSuchMethod();
- }
- } else if (target.impliesType) {
- if (node.isIfNullAssignment) {
- setter = reportAndCreateErroneousElement(node.selector, target.name,
- MessageKind.IF_NULL_ASSIGNING_TYPE, const {});
- // In this case, no assignment happens, the rest of the compiler can
- // treat the expression `C ??= e` as if it's just reading `C`.
- } else {
- setter = reportAndCreateErroneousElement(node.selector, target.name,
- MessageKind.ASSIGNING_TYPE, const {});
- registry.registerThrowNoSuchMethod();
- }
- registerTypeLiteralAccess(node, target);
- } else if (target.isFinal || target.isConst) {
- if (Elements.isStaticOrTopLevelField(target) || target.isLocal) {
- setter = reportAndCreateErroneousElement(
- node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER,
- const {});
- } else if (node.isSuperCall) {
- setter = reportAndCreateErroneousElement(
- node.selector, target.name, MessageKind.SETTER_NOT_FOUND_IN_SUPER,
- {'name': target.name, 'className': currentClass.name});
- registry.registerSuperNoSuchMethod();
- } else {
- // For instance fields we don't report a warning here because the type
- // checker will detect this as well and report a better error message
- // with the context of the containing class.
- }
- registry.registerThrowNoSuchMethod();
- } else if (target.isFunction && target.name != '[]=') {
- assert(!target.isSetter);
- if (Elements.isStaticOrTopLevelFunction(target) || target.isLocal) {
- setter = reportAndCreateErroneousElement(
- node.selector, target.name, MessageKind.ASSIGNING_METHOD,
- const {});
- } else if (node.isSuperCall) {
- setter = reportAndCreateErroneousElement(
- node.selector, target.name, MessageKind.ASSIGNING_METHOD_IN_SUPER,
- {'name': target.name,
- 'superclassName': target.enclosingClass.name});
- registry.registerSuperNoSuchMethod();
- } else {
- // For instance methods we don't report a warning here because the
- // type checker will detect this as well and report a better error
- // message with the context of the containing class.
- }
- registry.registerThrowNoSuchMethod();
- }
- if (isPotentiallyMutableTarget(target)) {
- registry.registerPotentialMutation(target, node);
- if (enclosingElement != target.enclosingElement) {
- registry.registerPotentialMutationInClosure(target, node);
- }
- for (Node scope in promotionScope) {
- registry.registerPotentialMutationIn(scope, target, node);
- }
- }
- }
-
- resolveArguments(node.argumentsNode);
-
- Selector selector = registry.getSelector(node);
- if (isComplex) {
- Selector getterSelector;
- if (selector.isSetter) {
- getterSelector = new Selector.getterFrom(selector);
- } else {
- assert(selector.isIndexSet);
- getterSelector = new Selector.index();
- }
- registerSend(getterSelector, getter);
- registry.setGetterSelectorInComplexSendSet(node, getterSelector);
- if (node.isSuperCall) {
- getter = currentClass.lookupSuperByName(getterSelector.memberName);
- if (getter == null) {
- target = reportAndCreateErroneousElement(
- node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
- {'className': currentClass.name, 'memberName': selector.name});
- registry.registerSuperNoSuchMethod();
- }
- }
- registry.useElement(node.selector, getter);
-
- // Make sure we include the + and - operators if we are using
- // the ++ and -- ones. Also, if op= form is used, include op itself.
- void registerBinaryOperator(String name) {
- Selector binop = new Selector.binaryOperator(name);
- registry.registerDynamicInvocation(
- new UniverseSelector(binop, null));
- registry.setOperatorSelectorInComplexSendSet(node, binop);
- }
- if (identical(source, '++')) {
- registerBinaryOperator('+');
- registry.registerInstantiatedClass(compiler.intClass);
- } else if (identical(source, '--')) {
- registerBinaryOperator('-');
- registry.registerInstantiatedClass(compiler.intClass);
- } else if (source.endsWith('=')) {
- registerBinaryOperator(Elements.mapToUserOperator(operatorName));
- }
- }
-
- registerSend(selector, setter);
- return new ResolutionResult.forElement(registry.useElement(node, setter));
}
void registerSend(Selector selector, Element target) {

Powered by Google App Engine
This is Rietveld 408576698