| Index: lib/compiler/implementation/resolver.dart
|
| diff --git a/lib/compiler/implementation/resolver.dart b/lib/compiler/implementation/resolver.dart
|
| index 13b6dd37e105e09a7127a838f7b5ce34f2e45b08..387f0e3dd5365fb1775731ce247807e380477f12 100644
|
| --- a/lib/compiler/implementation/resolver.dart
|
| +++ b/lib/compiler/implementation/resolver.dart
|
| @@ -955,6 +955,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| bool inCheckContext;
|
| Scope scope;
|
| ClassElement currentClass;
|
| + ExpressionStatement currentExpressionStatement;
|
| bool typeRequired = false;
|
| StatementScope statementScope;
|
| int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION;
|
| @@ -1163,7 +1164,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| visitEmptyStatement(EmptyStatement node) { }
|
|
|
| visitExpressionStatement(ExpressionStatement node) {
|
| + ExpressionStatement oldExpressionStatement = currentExpressionStatement;
|
| + currentExpressionStatement = node;
|
| visit(node.expression);
|
| + currentExpressionStatement = oldExpressionStatement;
|
| }
|
|
|
| visitFor(For node) {
|
| @@ -1217,10 +1221,35 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| return (str === '&&' || str == '||' || str == '!');
|
| }
|
|
|
| + /**
|
| + * Check the lexical scope chain for a declaration with the name "assert".
|
| + *
|
| + * This is used to detect whether "assert(x)" is actually an assertion or
|
| + * just a call expression.
|
| + * It does not check fields inherited from a superclass.
|
| + */
|
| + bool isAssertInLexicalScope() {
|
| + return scope.lexicalLookup(const SourceString("assert")) !== null;
|
| + }
|
| +
|
| + /** Check if [node] is the expression of the current expression statement. */
|
| + bool isExpressionStatementExpression(Node node) {
|
| + return currentExpressionStatement !== null &&
|
| + currentExpressionStatement.expression === node;
|
| + }
|
| +
|
| Element resolveSend(Send node) {
|
| Selector selector = resolveSelector(node);
|
|
|
| if (node.receiver === null) {
|
| + // If this send is the expression of an expression statement, and is on
|
| + // the form "assert(expr);", and there is no declaration with name
|
| + // "assert" in the lexical scope, then this is actually an assertion.
|
| + if (isExpressionStatementExpression(node) &&
|
| + selector.isAssertSyntax() &&
|
| + !isAssertInLexicalScope()) {
|
| + return compiler.assertMethod;
|
| + }
|
| return node.selector.accept(this);
|
| }
|
|
|
| @@ -1408,16 +1437,6 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| world.registerDynamicInvocation(call.name, call);
|
| }
|
|
|
| - // TODO(ngeoffray): We should do the check in
|
| - // visitExpressionStatement instead.
|
| - if (target === compiler.assertMethod && !node.isCall) {
|
| - // We can only use assert by calling it.
|
| - if (!inInstanceContext) {
|
| - error(node, MessageKind.MISSING_ARGUMENTS_TO_ASSERT, [node]);
|
| - }
|
| - target = null;
|
| - }
|
| -
|
| // TODO(ngeoffray): Warn if target is null and the send is
|
| // unqualified.
|
| useElement(node, target);
|
| @@ -1917,7 +1936,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| Scope blockScope = new BlockScope(scope);
|
| - doInCheckContext(() => visitIn(node.type, blockScope));
|
| + doInCheckContext(() => visitIn(node.type, blockScope));
|
| visitIn(node.formals, blockScope);
|
| visitIn(node.block, blockScope);
|
| }
|
| @@ -2593,7 +2612,20 @@ class Scope {
|
|
|
| Scope(this.parent, this.element);
|
| abstract Element add(Element element);
|
| - abstract Element lookup(SourceString name);
|
| +
|
| + Element lookup(SourceString name) {
|
| + Element result = localLookup(name);
|
| + if (result != null) return result;
|
| + return parent.lookup(name);
|
| + }
|
| +
|
| + Element lexicalLookup(SourceString name) {
|
| + Element result = localLookup(name);
|
| + if (result != null) return result;
|
| + return parent.lexicalLookup(name);
|
| + }
|
| +
|
| + abstract Element localLookup(SourceString name);
|
| }
|
|
|
| class VariableScope extends Scope {
|
| @@ -2627,7 +2659,7 @@ class TypeDeclarationScope extends Scope {
|
| throw "Cannot add element to TypeDeclarationScope";
|
| }
|
|
|
| - Element lookup(SourceString name) {
|
| + Element localLookup(SourceString name) {
|
| Link<DartType> typeVariableLink = element.typeVariables;
|
| while (!typeVariableLink.isEmpty()) {
|
| TypeVariableType typeVariable = typeVariableLink.head;
|
| @@ -2636,8 +2668,7 @@ class TypeDeclarationScope extends Scope {
|
| }
|
| typeVariableLink = typeVariableLink.tail;
|
| }
|
| -
|
| - return parent.lookup(name);
|
| + return null;
|
| }
|
|
|
| String toString() =>
|
| @@ -2653,11 +2684,7 @@ class MethodScope extends Scope {
|
| assert(parent !== null);
|
| }
|
|
|
| - Element lookup(SourceString name) {
|
| - Element found = elements[name];
|
| - if (found !== null) return found;
|
| - return parent.lookup(name);
|
| - }
|
| + Element localLookup(SourceString name) => elements[name];
|
|
|
| Element add(Element newElement) {
|
| if (elements.containsKey(newElement.name)) {
|
| @@ -2687,7 +2714,7 @@ class ClassScope extends TypeDeclarationScope {
|
| ClassScope(Scope parentScope, ClassElement element)
|
| : super(parentScope, element);
|
|
|
| - Element lookup(SourceString name) {
|
| + Element localLookup(SourceString name) {
|
| ClassElement cls = element;
|
| Element result = cls.lookupLocalMember(name);
|
| if (result !== null) return result;
|
| @@ -2695,11 +2722,15 @@ class ClassScope extends TypeDeclarationScope {
|
| // If not in a static context, we can lookup in the
|
| // TypeDeclaration scope, which contains the type variables of
|
| // the class.
|
| - result = super.lookup(name);
|
| - } else {
|
| - result = parent.lookup(name);
|
| + return super.localLookup(name);
|
| }
|
| - if (result != null) return result;
|
| + return null;
|
| + }
|
| +
|
| + Element lookup(SourceString name) {
|
| + Element result = super.lookup(name);
|
| + if (result !== null) return result;
|
| + ClassElement cls = element;
|
| return cls.lookupSuperMember(name);
|
| }
|
|
|
| @@ -2714,9 +2745,10 @@ class TopScope extends Scope {
|
| LibraryElement get library => element;
|
|
|
| TopScope(LibraryElement library) : super(null, library);
|
| - Element lookup(SourceString name) {
|
| - return library.find(name);
|
| - }
|
| +
|
| + Element localLookup(SourceString name) => library.find(name);
|
| + Element lookup(SourceString name) => localLookup(name);
|
| + Element lexicalLookup(SourceString name) => localLookup(name);
|
|
|
| Element add(Element newElement) {
|
| throw "Cannot add an element in the top scope";
|
|
|