Version 1.9.0-dev.10.7

svn merge -c 44423 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44431 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44432 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44434 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44438 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44441 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44444 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44449 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44456 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44473 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44479 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44481 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44487 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44490 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44491 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

Merge cl from:
https://codereview.chromium.org/1008443002/
Merge cl from:
https://codereview.chromium.org/1002893002/
Merge patch from:
https://code.google.com/p/dart/issues/detail?id=22823

git-svn-id: http://dart.googlecode.com/svn/trunk@44500 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 8168764..f699bdc 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -393,6 +393,25 @@
   }
 
   /**
+   * Return the [AnalysisContext] that contains the given [path].
+   * Return `null` if no context contains the [path].
+   */
+  AnalysisContext getContainingContext(String path) {
+    Folder containingFolder = null;
+    AnalysisContext containingContext = null;
+    folderMap.forEach((Folder folder, AnalysisContext context) {
+      if (folder.isOrContains(path)) {
+        if (containingFolder == null ||
+            containingFolder.path.length < folder.path.length) {
+          containingFolder = folder;
+          containingContext = context;
+        }
+      }
+    });
+    return containingContext;
+  }
+
+  /**
    * Return the primary [ContextSourcePair] representing the given [path].
    *
    * The [AnalysisContext] of this pair will be the context that explicitly
@@ -420,17 +439,7 @@
     Resource resource = resourceProvider.getResource(path);
     File file = resource is File ? resource : null;
     {
-      Folder containingFolder = null;
-      AnalysisContext containingContext = null;
-      folderMap.forEach((Folder folder, AnalysisContext context) {
-        if (folder.isOrContains(path)) {
-          if (containingFolder == null ||
-              containingFolder.path.length < folder.path.length) {
-            containingFolder = folder;
-            containingContext = context;
-          }
-        }
-      });
+      AnalysisContext containingContext = getContainingContext(path);
       if (containingContext != null) {
         Source source = file != null
             ? ContextManager.createSourceInContext(containingContext, file)
@@ -1242,6 +1251,11 @@
     if (context != null) {
       context.applyChanges(changeSet);
       analysisServer.schedulePerformAnalysisOperation(context);
+      List<String> flushedFiles = new List<String>();
+      for (Source source in changeSet.removedSources) {
+        flushedFiles.add(source.fullName);
+      }
+      sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
     }
   }
 
@@ -1258,9 +1272,17 @@
   @override
   void removeContext(Folder folder) {
     AnalysisContext context = analysisServer.folderMap.remove(folder);
+
+    // See dartbug.com/22689, the AnalysisContext is computed in
+    // computeFlushedFiles instead of using the referenced context above, this
+    // is an attempt to be careful concerning the referenced issue.
+    List<String> flushedFiles = computeFlushedFiles(folder);
+    sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
+
     if (analysisServer.index != null) {
       analysisServer.index.removeContext(context);
     }
+    analysisServer.operationQueue.contextRemoved(context);
     _onContextsChangedController
         .add(new ContextsChangedEvent(removed: [context]));
     analysisServer.sendContextAnalysisDoneNotifications(
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index ec26ccb..d715b6b 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -115,6 +115,29 @@
   }
 
   /**
+   * Compute the set of files that are being flushed, this is defined as
+   * the set of sources in the removed context (context.sources), that are
+   * orphaned by this context being removed (no other context includes this
+   * file.)
+   */
+  List<String> computeFlushedFiles(Folder folder) {
+    AnalysisContext context = _contexts[folder].context;
+    HashSet<String> flushedFiles = new HashSet<String>();
+    for (Source source in context.sources) {
+      flushedFiles.add(source.fullName);
+    }
+    for (_ContextInfo contextInfo in _contexts.values) {
+      AnalysisContext contextN = contextInfo.context;
+      if (context != contextN) {
+        for (Source source in contextN.sources) {
+          flushedFiles.remove(source.fullName);
+        }
+      }
+    }
+    return flushedFiles.toList(growable:false);
+  }
+
+  /**
    * We have finished computing the package map.
    */
   void endComputePackageMap() {
diff --git a/pkg/analysis_server/lib/src/operation/operation.dart b/pkg/analysis_server/lib/src/operation/operation.dart
index 1433c90..6c5732d 100644
--- a/pkg/analysis_server/lib/src/operation/operation.dart
+++ b/pkg/analysis_server/lib/src/operation/operation.dart
@@ -5,6 +5,7 @@
 library operation;
 
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
@@ -13,6 +14,14 @@
  */
 abstract class ServerOperation {
   /**
+   * The context for this operation.  Operations will be automatically
+   * de-queued when their context is destroyed.
+   */
+  final AnalysisContext context;
+
+  ServerOperation(this.context);
+
+  /**
    * Returns the priority of this operation.
    */
   ServerOperationPriority get priority;
@@ -63,6 +72,8 @@
  * before a change is applied to a [Source].
  */
 abstract class SourceSensitiveOperation extends ServerOperation {
+  SourceSensitiveOperation(AnalysisContext context) : super(context);
+
   /**
    * The given [source] is about to be changed.
    * Check if this [SourceSensitiveOperation] should be discarded.
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index ecbb97c..243384f 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -36,6 +36,11 @@
 void scheduleNotificationOperations(AnalysisServer server, String file,
     LineInfo lineInfo, AnalysisContext context, CompilationUnit parsedDartUnit,
     CompilationUnit resolvedDartUnit, List<AnalysisError> errors) {
+  // If the file belongs to any analysis root, check whether we're in it now.
+  AnalysisContext containingContext = server.getContainingContext(file);
+  if (containingContext != null && context != containingContext) {
+    return;
+  }
   // Dart
   CompilationUnit dartUnit =
       resolvedDartUnit != null ? resolvedDartUnit : parsedDartUnit;
@@ -43,35 +48,35 @@
     if (server.hasAnalysisSubscription(
         protocol.AnalysisService.HIGHLIGHTS, file)) {
       server.scheduleOperation(
-          new _DartHighlightsOperation(file, resolvedDartUnit));
+          new _DartHighlightsOperation(context, file, resolvedDartUnit));
     }
     if (server.hasAnalysisSubscription(
         protocol.AnalysisService.NAVIGATION, file)) {
       server.scheduleOperation(
-          new _DartNavigationOperation(file, resolvedDartUnit));
+          new _DartNavigationOperation(context, file, resolvedDartUnit));
     }
     if (server.hasAnalysisSubscription(
         protocol.AnalysisService.OCCURRENCES, file)) {
       server.scheduleOperation(
-          new _DartOccurrencesOperation(file, resolvedDartUnit));
+          new _DartOccurrencesOperation(context, file, resolvedDartUnit));
     }
     if (server.hasAnalysisSubscription(
         protocol.AnalysisService.OVERRIDES, file)) {
       server.scheduleOperation(
-          new _DartOverridesOperation(file, resolvedDartUnit));
+          new _DartOverridesOperation(context, file, resolvedDartUnit));
     }
   }
   if (dartUnit != null) {
     if (server.hasAnalysisSubscription(
         protocol.AnalysisService.OUTLINE, file)) {
       server.scheduleOperation(
-          new _DartOutlineOperation(file, lineInfo, dartUnit));
+          new _DartOutlineOperation(context, file, lineInfo, dartUnit));
     }
   }
   // errors
   if (server.shouldSendErrorsNotificationFor(file)) {
     server.scheduleOperation(
-        new _NotificationErrorsOperation(file, lineInfo, errors));
+        new _NotificationErrorsOperation(context, file, lineInfo, errors));
   }
 }
 
@@ -88,6 +93,16 @@
   });
 }
 
+void sendAnalysisNotificationFlushResults(
+    AnalysisServer server, List<String> files) {
+  _sendNotification(server, () {
+    if (files != null && files.isNotEmpty) {
+      var params = new protocol.AnalysisFlushResultsParams(files);
+      server.sendNotification(params.toNotification());
+    }
+  });
+}
+
 void sendAnalysisNotificationHighlights(
     AnalysisServer server, String file, CompilationUnit dartUnit) {
   _sendNotification(server, () {
@@ -156,10 +171,10 @@
   static const int IDLE_CACHE_SIZE = AnalysisOptionsImpl.DEFAULT_CACHE_SIZE;
   static const int WORKING_CACHE_SIZE = 512;
 
-  final AnalysisContext context;
   final bool isContinue;
 
-  PerformAnalysisOperation(this.context, this.isContinue);
+  PerformAnalysisOperation(AnalysisContext context, this.isContinue)
+      : super(context);
 
   @override
   ServerOperationPriority get priority {
@@ -266,8 +281,9 @@
 }
 
 class _DartHighlightsOperation extends _DartNotificationOperation {
-  _DartHighlightsOperation(String file, CompilationUnit unit)
-      : super(file, unit);
+  _DartHighlightsOperation(
+      AnalysisContext context, String file, CompilationUnit unit)
+      : super(context, file, unit);
 
   @override
   void perform(AnalysisServer server) {
@@ -276,10 +292,10 @@
 }
 
 class _DartIndexOperation extends _SingleFileOperation {
-  final AnalysisContext context;
   final CompilationUnit unit;
 
-  _DartIndexOperation(this.context, String file, this.unit) : super(file);
+  _DartIndexOperation(AnalysisContext context, String file, this.unit)
+      : super(context, file);
 
   @override
   ServerOperationPriority get priority {
@@ -296,8 +312,9 @@
 }
 
 class _DartNavigationOperation extends _DartNotificationOperation {
-  _DartNavigationOperation(String file, CompilationUnit unit)
-      : super(file, unit);
+  _DartNavigationOperation(
+      AnalysisContext context, String file, CompilationUnit unit)
+      : super(context, file, unit);
 
   @override
   void perform(AnalysisServer server) {
@@ -308,7 +325,8 @@
 abstract class _DartNotificationOperation extends _SingleFileOperation {
   final CompilationUnit unit;
 
-  _DartNotificationOperation(String file, this.unit) : super(file);
+  _DartNotificationOperation(AnalysisContext context, String file, this.unit)
+      : super(context, file);
 
   @override
   ServerOperationPriority get priority {
@@ -317,8 +335,9 @@
 }
 
 class _DartOccurrencesOperation extends _DartNotificationOperation {
-  _DartOccurrencesOperation(String file, CompilationUnit unit)
-      : super(file, unit);
+  _DartOccurrencesOperation(
+      AnalysisContext context, String file, CompilationUnit unit)
+      : super(context, file, unit);
 
   @override
   void perform(AnalysisServer server) {
@@ -329,8 +348,9 @@
 class _DartOutlineOperation extends _DartNotificationOperation {
   final LineInfo lineInfo;
 
-  _DartOutlineOperation(String file, this.lineInfo, CompilationUnit unit)
-      : super(file, unit);
+  _DartOutlineOperation(
+      AnalysisContext context, String file, this.lineInfo, CompilationUnit unit)
+      : super(context, file, unit);
 
   @override
   void perform(AnalysisServer server) {
@@ -339,8 +359,9 @@
 }
 
 class _DartOverridesOperation extends _DartNotificationOperation {
-  _DartOverridesOperation(String file, CompilationUnit unit)
-      : super(file, unit);
+  _DartOverridesOperation(
+      AnalysisContext context, String file, CompilationUnit unit)
+      : super(context, file, unit);
 
   @override
   void perform(AnalysisServer server) {
@@ -349,10 +370,10 @@
 }
 
 class _HtmlIndexOperation extends _SingleFileOperation {
-  final AnalysisContext context;
   final HtmlUnit unit;
 
-  _HtmlIndexOperation(this.context, String file, this.unit) : super(file);
+  _HtmlIndexOperation(AnalysisContext context, String file, this.unit)
+      : super(context, file);
 
   @override
   ServerOperationPriority get priority {
@@ -370,8 +391,9 @@
   final LineInfo lineInfo;
   final List<AnalysisError> errors;
 
-  _NotificationErrorsOperation(String file, this.lineInfo, this.errors)
-      : super(file);
+  _NotificationErrorsOperation(
+      AnalysisContext context, String file, this.lineInfo, this.errors)
+      : super(context, file);
 
   @override
   ServerOperationPriority get priority {
@@ -387,7 +409,7 @@
 abstract class _SingleFileOperation extends SourceSensitiveOperation {
   final String file;
 
-  _SingleFileOperation(this.file);
+  _SingleFileOperation(AnalysisContext context, this.file) : super(context);
 
   @override
   bool shouldBeDiscardedOnSourceChange(Source source) {
diff --git a/pkg/analysis_server/lib/src/operation/operation_queue.dart b/pkg/analysis_server/lib/src/operation/operation_queue.dart
index 7ea8257..ced4a8c 100644
--- a/pkg/analysis_server/lib/src/operation/operation_queue.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_queue.dart
@@ -8,6 +8,7 @@
 
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/operation/operation.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
@@ -51,6 +52,16 @@
   }
 
   /**
+   * The given [context] has been removed, so all pending operations that refer
+   * to it should be removed from the queue.
+   */
+  void contextRemoved(AnalysisContext context) {
+    for (Queue<ServerOperation> queue in _queues) {
+      queue.removeWhere((operation) => operation.context == context);
+    }
+  }
+
+  /**
    * Return the next operation to perform, or `null` if the queue is empty.
    * This method does not change the queue.
    */
diff --git a/pkg/analysis_server/lib/src/services/completion/arglist_computer.dart b/pkg/analysis_server/lib/src/services/completion/arglist_computer.dart
index a5e4418..55b342a 100644
--- a/pkg/analysis_server/lib/src/services/completion/arglist_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/arglist_computer.dart
@@ -179,7 +179,7 @@
         completion.toString(), completion.length, 0, false, false);
     suggestion.parameterNames = paramNames;
     suggestion.parameterTypes = paramTypes;
-    request.suggestions.add(suggestion);
+    request.addSuggestion(suggestion);
   }
 
   String _getParamType(FormalParameter param) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart
index ca9c75a..17127f7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart
@@ -198,6 +198,11 @@
   void _addDartCoreSuggestions() {
     Source coreUri = context.sourceFactory.forUri('dart:core');
     LibraryElement coreLib = context.getLibraryElement(coreUri);
+    if (coreLib == null) {
+      // If the core library has not been analyzed yet, then we cannot add any
+      // suggestions from it.
+      return;
+    }
     Namespace coreNamespace =
         new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib);
     coreNamespace.definedNames.forEach((String name, Element elem) {
@@ -272,10 +277,11 @@
    */
   void _addNonImportedElementSuggestions(
       List<SearchMatch> matches, Set<LibraryElement> excludedLibs) {
+    AnalysisContext sdkContext = context.sourceFactory.dartSdk.context;
     matches.forEach((SearchMatch match) {
       if (match.kind == MatchKind.DECLARATION) {
         Element element = match.element;
-        if (element.context == context &&
+        if ((element.context == context || element.context == sdkContext) &&
             element.isPublic &&
             !excludedLibs.contains(element.library) &&
             !_importedCompletions.contains(element.displayName)) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
index 15f26b2..0f77b19 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
@@ -78,11 +78,13 @@
       : super(context, source) {
     if (computers == null) {
       computers = [
-        new KeywordComputer(),
+        // LocalComputer before ImportedComputer
+        // because local suggestions take precedence
         new LocalComputer(),
+        new ImportedComputer(),
+        new KeywordComputer(),
         new ArgListComputer(),
         new CombinatorComputer(),
-        new ImportedComputer(),
         new InvocationComputer()
       ];
     }
@@ -315,7 +317,12 @@
   /**
    * The list of suggestions to be sent to the client.
    */
-  final List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
+  final List<CompletionSuggestion> _suggestions = <CompletionSuggestion>[];
+
+  /**
+   * The set of completions used to prevent duplicates
+   */
+  final Set<String> _completions = new Set<String>();
 
   DartCompletionRequest(this.context, this.searchEngine, this.source,
       int offset, this.cache, CompletionPerformance performance)
@@ -342,17 +349,32 @@
   }
 
   /**
+   * The list of suggestions to be sent to the client.
+   */
+  Iterable<CompletionSuggestion> get suggestions => _suggestions;
+
+  /**
+   * Add the given suggestion to the list that is returned to the client as long
+   * as a suggestion with an identical completion has not already been added.
+   */
+  void addSuggestion(CompletionSuggestion suggestion) {
+    if (_completions.add(suggestion.completion)) {
+      _suggestions.add(suggestion);
+    }
+  }
+
+  /**
    * Convert all [CompletionSuggestionKind.INVOCATION] suggestions
    * to [CompletionSuggestionKind.IDENTIFIER] suggestions.
    */
   void convertInvocationsToIdentifiers() {
-    for (int index = suggestions.length - 1; index >= 0; --index) {
-      CompletionSuggestion suggestion = suggestions[index];
+    for (int index = _suggestions.length - 1; index >= 0; --index) {
+      CompletionSuggestion suggestion = _suggestions[index];
       if (suggestion.kind == CompletionSuggestionKind.INVOCATION) {
         // Create a copy rather than just modifying the existing suggestion
         // because [DartCompletionCache] may be caching that suggestion
         // for future completion requests
-        suggestions[index] = new CompletionSuggestion(
+        _suggestions[index] = new CompletionSuggestion(
             CompletionSuggestionKind.IDENTIFIER, suggestion.relevance,
             suggestion.completion, suggestion.selectionOffset,
             suggestion.selectionLength, suggestion.isDeprecated,
diff --git a/pkg/analysis_server/lib/src/services/completion/imported_computer.dart b/pkg/analysis_server/lib/src/services/completion/imported_computer.dart
index 5a06b21..2031557 100644
--- a/pkg/analysis_server/lib/src/services/completion/imported_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/imported_computer.dart
@@ -170,11 +170,11 @@
     unfiltered.forEach((CompletionSuggestion suggestion) {
       if (filterText.length > 0) {
         if (suggestion.completion.startsWith(filterText)) {
-          request.suggestions.add(suggestion);
+          request.addSuggestion(suggestion);
         }
       } else {
         if (suggestion.relevance != DART_RELEVANCE_LOW) {
-          request.suggestions.add(suggestion);
+          request.addSuggestion(suggestion);
         }
       }
     });
diff --git a/pkg/analysis_server/lib/src/services/completion/invocation_computer.dart b/pkg/analysis_server/lib/src/services/completion/invocation_computer.dart
index 494a57d..9d154ec 100644
--- a/pkg/analysis_server/lib/src/services/completion/invocation_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/invocation_computer.dart
@@ -64,10 +64,12 @@
     } else if (node is PropertyAccess) {
       node = (node as PropertyAccess).realTarget;
     }
-    if (node is Identifier && node.bestElement is ClassElement) {
-      node.bestElement
-          .accept(new _PrefixedIdentifierSuggestionBuilder(request));
-      return new Future.value(true);
+    if (node is Identifier) {
+      Element elem = node.bestElement;
+      if (elem is ClassElement || elem is PrefixElement) {
+        elem.accept(new _PrefixedIdentifierSuggestionBuilder(request));
+        return new Future.value(true);
+      }
     }
     if (node is Expression) {
       InterfaceTypeSuggestionBuilder.suggestionsFor(request, node.bestType);
@@ -328,7 +330,6 @@
         }
       }
     }
-    ;
     return new Future.value(modified);
   }
 
diff --git a/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart b/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart
index db65d77..36d403b 100644
--- a/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart
@@ -219,7 +219,7 @@
   void _addSuggestion(Keyword keyword,
       [int relevance = DART_RELEVANCE_DEFAULT]) {
     String completion = keyword.syntax;
-    request.suggestions.add(new CompletionSuggestion(
+    request.addSuggestion(new CompletionSuggestion(
         CompletionSuggestionKind.KEYWORD,
         relevance, completion, completion.length, 0, false, false));
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/local_computer.dart b/pkg/analysis_server/lib/src/services/completion/local_computer.dart
index 4f6b138..028b116 100644
--- a/pkg/analysis_server/lib/src/services/completion/local_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/local_computer.dart
@@ -272,7 +272,7 @@
         parameterTypes: parameterTypes,
         requiredParameterCount: requiredParameterCount,
         hasNamedParameters: hasNamedParameters);
-    request.suggestions.add(suggestion);
+    request.addSuggestion(suggestion);
     return suggestion;
   }
 
@@ -402,7 +402,7 @@
         CompletionSuggestion suggestion = new CompletionSuggestion(
             CompletionSuggestionKind.IDENTIFIER, DART_RELEVANCE_DEFAULT,
             completion, completion.length, 0, false, false);
-        request.suggestions.add(suggestion);
+        request.addSuggestion(suggestion);
         return suggestion;
       }
     }
@@ -681,7 +681,7 @@
             }
           }
         }
-        request.suggestions.add(suggestion);
+        request.addSuggestion(suggestion);
         return suggestion;
       }
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/local_declaration_visitor.dart b/pkg/analysis_server/lib/src/services/completion/local_declaration_visitor.dart
index 31d59fc..ef36304 100644
--- a/pkg/analysis_server/lib/src/services/completion/local_declaration_visitor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/local_declaration_visitor.dart
@@ -144,6 +144,12 @@
   }
 
   @override
+  visitConstructorDeclaration(ConstructorDeclaration node) {
+    _visitParamList(node.parameters);
+    visitNode(node);
+  }
+
+  @override
   void visitForEachStatement(ForEachStatement node) {
     SimpleIdentifier id;
     TypeName type;
diff --git a/pkg/analysis_server/lib/src/services/completion/optype.dart b/pkg/analysis_server/lib/src/services/completion/optype.dart
index cba5695..72c6e22 100644
--- a/pkg/analysis_server/lib/src/services/completion/optype.dart
+++ b/pkg/analysis_server/lib/src/services/completion/optype.dart
@@ -139,6 +139,22 @@
   @override
   void visitBinaryExpression(BinaryExpression node) {
     if (identical(entity, node.rightOperand)) {
+      // An empty type argument list is parsed as a binary expression
+      // `C<>` is parsed as `C < `
+      Object entity = this.entity;
+      if (entity is SimpleIdentifier && entity.isSynthetic) {
+        Token operator = node.operator;
+        if (operator != null && operator.lexeme == '<') {
+          Token next = entity.token.next;
+          if (next is StringToken && next.lexeme.length == 0) {
+            next = next.next;
+          }
+          if (next != null && next.lexeme == '>') {
+            optype.includeTypeNameSuggestions = true;
+            return;
+          }
+        }
+      }
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -384,7 +400,7 @@
   }
 
   @override
-  void visitListLiteral(ListLiteral node) {
+  void visitMapLiteralEntry(MapLiteralEntry node) {
     optype.includeReturnValueSuggestions = true;
     optype.includeTypeNameSuggestions = true;
   }
@@ -496,6 +512,23 @@
   }
 
   @override
+  void visitTypeArgumentList(TypeArgumentList node) {
+    NodeList<TypeName> arguments = node.arguments;
+    for (TypeName typeName in arguments) {
+      if (identical(entity, typeName)) {
+        optype.includeTypeNameSuggestions = true;
+        break;
+      }
+    }
+  }
+
+  @override
+  void visitTypedLiteral(TypedLiteral node) {
+    optype.includeReturnValueSuggestions = true;
+    optype.includeTypeNameSuggestions = true;
+  }
+
+  @override
   void visitTypeName(TypeName node) {
     // The entity won't be the first child entity (node.name), since
     // CompletionTarget would have chosen an edge higher in the parse tree.  So
diff --git a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
index c226403..e882474 100644
--- a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
@@ -165,11 +165,6 @@
 abstract class ElementSuggestionBuilder {
 
   /**
-   * Internal collection of completions to prevent duplicate completions.
-   */
-  final Set<String> _completions = new Set<String>();
-
-  /**
    * Return the kind of suggestions that should be built.
    */
   CompletionSuggestionKind get kind;
@@ -196,15 +191,13 @@
       }
     }
     String completion = element.displayName;
-    if (completion == null ||
-        completion.length <= 0 ||
-        !_completions.add(completion)) {
+    if (completion == null || completion.length <= 0) {
       return;
     }
     CompletionSuggestion suggestion =
         createSuggestion(element, kind: kind, relevance: relevance);
     if (suggestion != null) {
-      request.suggestions.add(suggestion);
+      request.addSuggestion(suggestion);
     }
   }
 }
@@ -307,7 +300,7 @@
     }
     CompletionSuggestion suggestion = createSuggestion(element, kind: kind);
     if (suggestion != null) {
-      request.suggestions.add(suggestion);
+      request.addSuggestion(suggestion);
     }
   }
 
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index bd78f9f..5913930 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -191,6 +191,34 @@
     });
   }
 
+  test_getAnalysisContext_nested() {
+    String dir1Path = '/dir1';
+    String dir2Path = dir1Path + '/dir2';
+    String filePath = dir2Path + '/file.dart';
+    Folder dir1 = resourceProvider.newFolder(dir1Path);
+    Folder dir2 = resourceProvider.newFolder(dir2Path);
+    resourceProvider.newFile(filePath, 'library lib;');
+
+    AnalysisContext context1 = AnalysisEngine.instance.createAnalysisContext();
+    AnalysisContext context2 = AnalysisEngine.instance.createAnalysisContext();
+    server.folderMap[dir1] = context1;
+    server.folderMap[dir2] = context2;
+
+    expect(server.getAnalysisContext(filePath), context2);
+  }
+
+  test_getAnalysisContext_simple() {
+    String dirPath = '/dir';
+    String filePath = dirPath + '/file.dart';
+    Folder dir = resourceProvider.newFolder(dirPath);
+    resourceProvider.newFile(filePath, 'library lib;');
+
+    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+    server.folderMap[dir] = context;
+
+    expect(server.getAnalysisContext(filePath), context);
+  }
+
   Future test_getAnalysisContextForSource() {
     // Subscribe to STATUS so we'll know when analysis is done.
     server.serverServices = [ServerService.STATUS].toSet();
@@ -283,6 +311,72 @@
     expect(source.fullName, filePath);
   }
 
+  test_operationsRemovedOnContextDisposal() async {
+    resourceProvider.newFolder('/foo');
+    resourceProvider.newFile('/foo/baz.dart', 'library lib;');
+    resourceProvider.newFolder('/bar');
+    resourceProvider.newFile('/bar/baz.dart', 'library lib;');
+    server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
+    await pumpEventQueue();
+    AnalysisContext contextFoo = server.getAnalysisContext('/foo/baz.dart');
+    AnalysisContext contextBar = server.getAnalysisContext('/bar/baz.dart');
+    _MockServerOperation operationFoo = new _MockServerOperation(contextFoo);
+    _MockServerOperation operationBar = new _MockServerOperation(contextBar);
+    server.scheduleOperation(operationFoo);
+    server.scheduleOperation(operationBar);
+    server.setAnalysisRoots('1', ['/foo'], [], {});
+    await pumpEventQueue();
+    expect(operationFoo.isComplete, isTrue);
+    expect(operationBar.isComplete, isFalse);
+  }
+
+  /**
+   * Test that having multiple analysis contexts analyze the same file doesn't
+   * cause that file to receive duplicate notifications when it's modified.
+   */
+  Future test_no_duplicate_notifications() async {
+    // Subscribe to STATUS so we'll know when analysis is done.
+    server.serverServices = [ServerService.STATUS].toSet();
+    resourceProvider.newFolder('/foo');
+    resourceProvider.newFolder('/bar');
+    resourceProvider.newFile('/foo/foo.dart', 'import "../bar/bar.dart";');
+    File bar = resourceProvider.newFile('/bar/bar.dart', 'library bar;');
+    server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
+    Map<AnalysisService, Set<String>> subscriptions =
+        <AnalysisService, Set<String>>{};
+    for (AnalysisService service in AnalysisService.VALUES) {
+      subscriptions[service] = <String>[bar.path].toSet();
+    }
+    server.setAnalysisSubscriptions(subscriptions);
+    await pumpEventQueue(100);
+    expect(server.statusAnalyzing, isFalse);
+    channel.notificationsReceived.clear();
+    server.updateContent(
+        '0', {bar.path: new AddContentOverlay('library bar; void f() {}')});
+    await pumpEventQueue(100);
+    expect(server.statusAnalyzing, isFalse);
+    expect(channel.notificationsReceived, isNotEmpty);
+    Set<String> notificationTypesReceived = new Set<String>();
+    for (Notification notification in channel.notificationsReceived) {
+      String notificationType = notification.event;
+      switch (notificationType) {
+        case 'server.status':
+        case 'analysis.errors':
+          // It's normal for these notifications to be sent multiple times.
+          break;
+        case 'analysis.outline':
+          // It's normal for this notification to be sent twice.
+          // TODO(paulberry): why?
+          break;
+        default:
+          if (!notificationTypesReceived.add(notificationType)) {
+            fail('Notification type $notificationType received more than once');
+          }
+          break;
+      }
+    }
+  }
+
   Future test_prioritySourcesChangedEvent() {
     resourceProvider.newFolder('/foo');
 
@@ -403,3 +497,22 @@
     return null;
   }
 }
+
+/**
+ * A [ServerOperation] that does nothing but keep track of whether or not it
+ * has been performed.
+ */
+class _MockServerOperation implements ServerOperation {
+  final AnalysisContext context;
+  bool isComplete = false;
+
+  _MockServerOperation(this.context);
+
+  @override
+  ServerOperationPriority get priority => ServerOperationPriority.ANALYSIS;
+
+  @override
+  void perform(AnalysisServer server) {
+    isComplete = true;
+  }
+}
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index eec4109..cc43193 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -71,7 +71,7 @@
 
     buildTests('testCommentSnippets007', '''
 class C {mth(Map x, !1) {}mtf(!2, Map x) {}m() {for (in!3t i=0; i<5; i++); A!4 x;}}class int{}class Arrays{}''',
-        <String>["1+bool", "2+bool", "3+int", "4+Arrays"], failingTests: '3');
+        <String>["1+bool", "2+bool", "3+int", "4+Arrays"]);
 
     buildTests('testCommentSnippets008', '''
 class Date{}final num M = Dat!1''', <String>["1+Date"]);
@@ -118,14 +118,8 @@
 class F {var x = !1false;}''', <String>["1+true"], failingTests: '1');
 
     buildTests('testCommentSnippets018', '''
-class Map{}class Arrays{}class C{ m(!1){} n(!2 x, q)''', <String>[
-      "1+Map",
-      "1-void",
-      "1-null",
-      "2+Arrays",
-      "2-void",
-      "2-null"
-    ], failingTests: '1');
+class Map{}class Arrays{}class C{ m(!1){} n(!2 x, q)''',
+        <String>["1+Map", "1-void", "1-null", "2+Arrays", "2-void", "2-null"]);
 
     buildTests('testCommentSnippets019', '''
 class A{m(){Object x;x.!1/**/clear()''', <String>["1+toString"]);
@@ -136,13 +130,13 @@
 
     buildTests('testCommentSnippets021', '''
 class Map{}class tst {var newt;void newf(){}test() {var newz;new !1/**/;}}''',
-        <String>["1+Map", "1-newt"], failingTests: '1');
+        <String>["1+Map", "1-newt"]);
 
     buildTests('testCommentSnippets022', '''
-class Map{}class F{m(){new !1;}}''', <String>["1+Map"], failingTests: '1');
+class Map{}class F{m(){new !1;}}''', <String>["1+Map"]);
 
     buildTests('testCommentSnippets022a', '''
-class Map{}class F{m(){new !1''', <String>["1+Map"], failingTests: '1');
+class Map{}class F{m(){new !1''', <String>["1+Map"]);
 
     buildTests('testCommentSnippets022b', '''
 class Map{factory Map.qq(){return null;}}class F{m(){new Map.!1qq();}}''',
@@ -157,18 +151,18 @@
 
     buildTests('testCommentSnippets025', '''
 class q {num m() {var q; num x=!1 q!3 + !2/**/;}}''',
-        <String>["1+q", "2+q", "3+q"], failingTests: '123');
+        <String>["1+q", "2+q", "3+q"]);
 
     buildTests('testCommentSnippets026', '''
-class List{}class a implements !1{}''', <String>["1+List"], failingTests: '1');
+class List{}class a implements !1{}''', <String>["1+List"]);
 
     buildTests('testCommentSnippets027', '''
 class String{}class List{}class test <X extends !1String!2> {}''',
-        <String>["1+List", "2+String", "2-List"], failingTests: '12');
+        <String>["1+List", "2+String", "2-List"]);
 
     buildTests('testCommentSnippets028', '''
 class String{}class List{}class DateTime{}typedef T Y<T extends !1>(List input);''',
-        <String>["1+DateTime", "1+String"], failingTests: '1');
+        <String>["1+DateTime", "1+String"]);
 
     buildTests('testCommentSnippets029', '''
 interface A<X> default B<X extends !1List!2> {}''',
@@ -198,7 +192,7 @@
         <String>["1+length", "2+clear"]);
 
     buildTests('testCommentSnippets036', '''
-class List{}t3() {var x=new List!1}''', <String>["1+List"], failingTests: '1');
+class List{}t3() {var x=new List!1}''', <String>["1+List"]);
 
     buildTests('testCommentSnippets037', '''
 class List{factory List.from(){}}t3() {var x=new List.!1}''',
@@ -233,7 +227,7 @@
 
     buildTests('testCommentSnippets044', '''
 class List{}class XXX {XXX.fisk();}main() {main(); new !1}}''',
-        <String>["1+List", "1+XXX.fisk"], failingTests: '1');
+        <String>["1+List", "1+XXX.fisk"]);
 
     buildTests('testCommentSnippets047', '''
 f(){int x;int y=!1;}''', <String>["1+x"]);
@@ -599,11 +593,11 @@
 
     buildTests('testCommentSnippets076', '''
 class Map<K,V>{}class List<E>{}class int{}main() {var m=new Map<Lis!1t<Map<int,in!2t>>,List<!3int>>();}''',
-        <String>["1+List", "2+int", "3+int"], failingTests: '123');
+        <String>["1+List", "2+int", "3+int"]);
 
     buildTests('testCommentSnippets076a', '''
 class Map<K,V>{}class List<E>{}class int{}main() {var m=new Map<Lis!1t<Map<int,in!2t>>,List<!3>>();}''',
-        <String>["1+List", "2+int", "3+int"], failingTests: '123');
+        <String>["1+List", "2+int", "3+int"]);
 
     buildTests('testCommentSnippets077', '''
 class FileMode {
@@ -903,8 +897,7 @@
    */
   A.named(aaa, bbb) {}
   methodA() {}
-}''', <String>["1+aaa", "1-bbb", "2+int", "2-double", "3+methodA"],
-        failingTests: '1');
+}''', <String>["1+aaa", "1-bbb", "2+int", "2-double", "3+methodA"]);
 
     buildTests('testCompletion_dartDoc_reference_forFunction', '''
 /**
@@ -1028,7 +1021,7 @@
 
     buildTests('testCompletion_forStmt_vars', '''
 class int{}class Foo { mth() { for (in!1t i = 0; i!2 < 5; i!3++); }}''',
-        <String>["1+int", "2+i", "3+i"], failingTests: '1');
+        <String>["1+int", "2+i", "3+i"]);
 
     buildTests('testCompletion_function', '''
 class Foo { int boo = 7; mth() { PNGS.sort((String a, Str!1) => a.compareTo(b)); }}''',
@@ -1292,15 +1285,15 @@
 
     buildTests('testCompletion_newMemberType1', '''
 class Collection{}class List extends Collection{}class Foo { !1 }''',
-        <String>["1+Collection", "1+List"], failingTests: '1');
+        <String>["1+Collection", "1+List"]);
 
     buildTests('testCompletion_newMemberType2', '''
 class Collection{}class List extends Collection{}class Foo {!1}''',
-        <String>["1+Collection", "1+List"], failingTests: '1');
+        <String>["1+Collection", "1+List"]);
 
     buildTests('testCompletion_newMemberType3', '''
 class Collection{}class List extends Collection{}class Foo {L!1}''',
-        <String>["1-Collection", "1+List"], failingTests: '1');
+        <String>["1-Collection", "1+List"]);
 
     buildTests('testCompletion_newMemberType4', '''
 class Collection{}class List extends Collection{}class Foo {C!1}''',
@@ -1416,7 +1409,7 @@
     buildTests('testCompletion_staticField1', '''
 class num{}class Sunflower {static final n!2um MAX_D = 300;nu!3m xc, yc;Sun!4flower() {x!Xc = y!Yc = MA!1 }}''',
         <String>["1+MAX_D", "X+xc", "Y+yc", "2+num", "3+num", "4+Sunflower"],
-        failingTests: '23');
+        failingTests: '2');
 
     buildTests('testCompletion_super_superType', '''
 class A {
@@ -1501,7 +1494,7 @@
 
     buildTests('testCompletion_topLevelField_init2', '''
 class DateTime{static var JUN;}final num M = Dat!1eTime.JUN;''',
-        <String>["1+DateTime", "1-void"], failingTests: '1');
+        <String>["1+DateTime", "1-void"]);
 
     buildTests('testCompletion_while', '''
 class Foo { int boo = 7; mth() { while (b!1) {} }}''', <String>["1+boo"]);
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 20f6a41..b594773 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -421,7 +421,7 @@
   }
 
   test_locals() {
-    addTestFile('class A {var a; x() {var b;^}}');
+    addTestFile('class A {var a; x() {var b;^}} class DateTime { }');
     return getSuggestions().then((_) {
       expect(replacementOffset, equals(completionOffset));
       expect(replacementLength, equals(0));
@@ -432,6 +432,21 @@
           DART_RELEVANCE_LOCAL_VARIABLE);
       assertHasResult(CompletionSuggestionKind.INVOCATION, 'x',
           DART_RELEVANCE_LOCAL_METHOD);
+      assertHasResult(CompletionSuggestionKind.INVOCATION, 'DateTime');
+    });
+  }
+
+  test_overrides() {
+    addFile('/libA.dart', 'class A {m() {}}');
+    addTestFile('''
+import '/libA.dart';
+class B extends A {m() {^}}
+''');
+    return getSuggestions().then((_) {
+      expect(replacementOffset, equals(completionOffset));
+      expect(replacementLength, equals(0));
+      assertHasResult(CompletionSuggestionKind.INVOCATION, 'm',
+          DART_RELEVANCE_LOCAL_METHOD);
     });
   }
 
diff --git a/pkg/analysis_server/test/mock_sdk.dart b/pkg/analysis_server/test/mock_sdk.dart
index 504ecd9..920cb32 100644
--- a/pkg/analysis_server/test/mock_sdk.dart
+++ b/pkg/analysis_server/test/mock_sdk.dart
@@ -107,6 +107,7 @@
 import 'dart:math';
 
 class Future<T> {
+  factory Future(computation()) => null;
   factory Future.delayed(Duration duration, [T computation()]) => null;
   factory Future.value([value]) => null;
   static Future wait(List<Future> futures) => null;
diff --git a/pkg/analysis_server/test/operation/operation_queue_test.dart b/pkg/analysis_server/test/operation/operation_queue_test.dart
index 09a8afd..de5e795 100644
--- a/pkg/analysis_server/test/operation/operation_queue_test.dart
+++ b/pkg/analysis_server/test/operation/operation_queue_test.dart
@@ -61,6 +61,30 @@
     expect(queue.isEmpty, true);
   }
 
+  void test_contextRemoved() {
+    var contextA = new AnalysisContextMock();
+    var contextB = new AnalysisContextMock();
+    var opA1 = new _ServerOperationMock(contextA);
+    var opA2 = new _ServerOperationMock(contextA);
+    var opB1 = new _ServerOperationMock(contextB);
+    var opB2 = new _ServerOperationMock(contextB);
+    when(opA1.priority)
+        .thenReturn(ServerOperationPriority.ANALYSIS_NOTIFICATION);
+    when(opA2.priority)
+        .thenReturn(ServerOperationPriority.ANALYSIS_NOTIFICATION);
+    when(opB1.priority)
+        .thenReturn(ServerOperationPriority.ANALYSIS_NOTIFICATION);
+    when(opB2.priority)
+        .thenReturn(ServerOperationPriority.ANALYSIS_NOTIFICATION);
+    queue.add(opA1);
+    queue.add(opB1);
+    queue.add(opA2);
+    queue.add(opB2);
+    queue.contextRemoved(contextA);
+    expect(queue.take(), same(opB1));
+    expect(queue.take(), same(opB2));
+  }
+
   void test_isEmpty_false() {
     var operation = mockOperation(ServerOperationPriority.ANALYSIS);
     queue.add(operation);
@@ -148,6 +172,10 @@
 }
 
 class _ServerOperationMock extends TypedMock implements ServerOperation {
+  final AnalysisContext context;
+
+  _ServerOperationMock([this.context]);
+
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
 
diff --git a/pkg/analysis_server/test/services/completion/completion_computer_test.dart b/pkg/analysis_server/test/services/completion/completion_computer_test.dart
index 6536782..37afa8f 100644
--- a/pkg/analysis_server/test/services/completion/completion_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/completion_computer_test.dart
@@ -181,7 +181,7 @@
     this.request = request;
     fastCount++;
     if (fastSuggestion != null) {
-      request.suggestions.add(fastSuggestion);
+      request.addSuggestion(fastSuggestion);
     }
     return fastSuggestion != null;
   }
@@ -191,7 +191,7 @@
     this.request = request;
     fullCount++;
     if (fullSuggestion != null) {
-      request.suggestions.add(fullSuggestion);
+      request.addSuggestion(fullSuggestion);
     }
     return new Future.value(fullSuggestion != null);
   }
diff --git a/pkg/analysis_server/test/services/completion/completion_target_test.dart b/pkg/analysis_server/test/services/completion/completion_target_test.dart
index e416cb4..16983af 100644
--- a/pkg/analysis_server/test/services/completion/completion_target_test.dart
+++ b/pkg/analysis_server/test/services/completion/completion_target_test.dart
@@ -39,9 +39,10 @@
   void assertTarget(entityText, nodeText,
       {int argIndex: null, bool isFunctionalArgument: false}) {
     void assertCommon() {
-      expect(target.entity.toString(), entityText);
-      expect(target.containingNode.toString(), nodeText);
-      expect(target.argIndex, argIndex);
+      expect(target.entity.toString(), entityText, reason: 'entity');
+      expect(target.containingNode.toString(), nodeText,
+          reason: 'containingNode');
+      expect(target.argIndex, argIndex, reason: 'argIndex');
     }
     // Assert with parsed unit
     assertCommon();
@@ -300,6 +301,24 @@
     assertTarget('new C();', '{var f; {var x;} new C();}');
   }
 
+  test_MapLiteralEntry() {
+    // MapLiteralEntry  MapLiteral  VariableDeclaration
+    addTestSource('foo = {^');
+    assertTarget(' : ', '{ : }');
+  }
+
+  test_MapLiteralEntry1() {
+    // MapLiteralEntry  MapLiteral  VariableDeclaration
+    addTestSource('foo = {T^');
+    assertTarget('T : ', '{T : }');
+  }
+
+  test_MapLiteralEntry2() {
+    // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
+    addTestSource('foo = {7:T^};');
+    assertTarget('T', '7 : T');
+  }
+
   test_MethodDeclaration_inLineComment() {
     // Comment  ClassDeclaration  CompilationUnit
     addTestSource('''
@@ -455,6 +474,18 @@
     assertTarget('zoo', 'zoo(z) {}');
   }
 
+  test_TypeArgumentList() {
+    // SimpleIdentifier  BinaryExpression  ExpressionStatement
+    addTestSource('main() { C<^> c; }');
+    assertTarget('', 'C < ');
+  }
+
+  test_TypeArgumentList2() {
+    // TypeName  TypeArgumentList  TypeName
+    addTestSource('main() { C<C^> c; }');
+    assertTarget('C', '<C>');
+  }
+
   test_VariableDeclaration_lhs_identifier_after() {
     // VariableDeclaration  VariableDeclarationList
     addTestSource('main() {int b^ = 1;}');
diff --git a/pkg/analysis_server/test/services/completion/completion_test_util.dart b/pkg/analysis_server/test/services/completion/completion_test_util.dart
index edafc5f..40d31a8 100644
--- a/pkg/analysis_server/test/services/completion/completion_test_util.dart
+++ b/pkg/analysis_server/test/services/completion/completion_test_util.dart
@@ -201,8 +201,9 @@
     return cs;
   }
 
-  CompletionSuggestion assertSuggestConstructor(String name) {
-    CompletionSuggestion cs = assertSuggest(name);
+  CompletionSuggestion assertSuggestConstructor(String name,
+      {int relevance: DART_RELEVANCE_DEFAULT}) {
+    CompletionSuggestion cs = assertSuggest(name, relevance: relevance);
     protocol.Element element = cs.element;
     expect(element, isNotNull);
     expect(element.kind, equals(protocol.ElementKind.CONSTRUCTOR));
@@ -570,7 +571,8 @@
     }
   }
 
-  CompletionSuggestion assertSuggestImportedConstructor(String name) {
+  CompletionSuggestion assertSuggestImportedConstructor(String name,
+      {int relevance: DART_RELEVANCE_DEFAULT}) {
     return assertNotSuggested(name);
   }
 
@@ -826,8 +828,8 @@
       expect(request.replacementOffset, completionOffset);
       expect(request.replacementLength, 0);
       assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
-      assertSuggestLocalFunction(
-          'bar', 'String', kind: CompletionSuggestionKind.IDENTIFIER);
+      assertSuggestLocalFunction('bar', 'String',
+          kind: CompletionSuggestionKind.IDENTIFIER);
       assertSuggestImportedFunction('hasLength', 'bool',
           kind: CompletionSuggestionKind.IDENTIFIER);
       assertSuggestImportedFunction('identical', 'bool',
@@ -862,8 +864,8 @@
       expect(request.replacementOffset, completionOffset);
       expect(request.replacementLength, 0);
       assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
-      assertSuggestLocalFunction(
-          'bar', 'String', kind: CompletionSuggestionKind.IDENTIFIER);
+      assertSuggestLocalFunction('bar', 'String',
+          kind: CompletionSuggestionKind.IDENTIFIER);
       assertSuggestImportedFunction('hasLength', 'bool',
           kind: CompletionSuggestionKind.IDENTIFIER);
       assertSuggestImportedFunction('identical', 'bool',
@@ -953,8 +955,8 @@
       expect(request.replacementOffset, completionOffset);
       expect(request.replacementLength, 0);
       assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
-      assertSuggestLocalFunction(
-          'bar', 'String', kind: CompletionSuggestionKind.IDENTIFIER);
+      assertSuggestLocalFunction('bar', 'String',
+          kind: CompletionSuggestionKind.IDENTIFIER);
       assertSuggestImportedFunction('hasLength', 'bool',
           kind: CompletionSuggestionKind.IDENTIFIER);
       assertSuggestImportedFunction('identical', 'bool',
@@ -987,8 +989,8 @@
       expect(request.replacementOffset, completionOffset);
       expect(request.replacementLength, 0);
       assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
-      assertSuggestImportedFunction(
-          'hasLength', 'bool', kind: CompletionSuggestionKind.IDENTIFIER);
+      assertSuggestImportedFunction('hasLength', 'bool',
+          kind: CompletionSuggestionKind.IDENTIFIER);
       assertSuggestImportedFunction('identical', 'bool',
           kind: CompletionSuggestionKind.IDENTIFIER);
       assertSuggestLocalClass('B', kind: CompletionSuggestionKind.IDENTIFIER);
@@ -1280,7 +1282,10 @@
       //    'num',
       //    false,
       //    COMPLETION_RELEVANCE_LOW);
-      assertSuggestTopLevelVarGetterSetter('T1', 'String');
+      if (computer is ImportedComputer) {
+        // TODO(danrubel) should be top level var suggestion
+        assertSuggestGetter('T1', 'String');
+      }
       assertNotSuggested('_T2');
       //assertSuggestImportedTopLevelVar('T3', 'int', COMPLETION_RELEVANCE_LOW);
       assertNotSuggested('_T4');
@@ -1313,6 +1318,7 @@
     addSource('/testG.dart', 'class G { }');
     addSource('/testH.dart', '''
       class H { }
+      class D3 { }
       int T3;
       var _T4;'''); // not imported
     addTestSource('''
@@ -1345,9 +1351,11 @@
       //assertSuggestImportedClass('C');
       // hidden element suggested as low relevance
       assertSuggestImportedClass('D', relevance: DART_RELEVANCE_LOW);
-      assertSuggestImportedFunction(
-          'D1', null, deprecated: true, relevance: DART_RELEVANCE_LOW);
+      assertSuggestImportedFunction('D1', null,
+          deprecated: true, relevance: DART_RELEVANCE_LOW);
       assertSuggestLocalFunction('D2', 'Z');
+      // unimported elements suggested with low relevance
+      assertSuggestImportedClass('D3', relevance: DART_RELEVANCE_LOW);
       //assertSuggestImportedClass('EE');
       // hidden element suggested as low relevance
       //assertSuggestImportedClass('F', COMPLETION_RELEVANCE_LOW);
@@ -1430,6 +1438,18 @@
     });
   }
 
+  test_Block_unimported() {
+    addSource('/testAB.dart', 'class Foo { }');
+    addTestSource('class C {foo(){F^}}');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
+      assertSuggestImportedClass('Foo', relevance: DART_RELEVANCE_LOW);
+      assertSuggestImportedClass('Future', relevance: DART_RELEVANCE_LOW);
+    });
+  }
+
   test_CascadeExpression_selector1() {
     // PropertyAccess  CascadeExpression  ExpressionStatement  Block
     addSource('/testB.dart', '''
@@ -2355,6 +2375,7 @@
       class A {A(this.x) { } int x;}''');
     addTestSource('''
       import "/testA.dart";
+      import "dart:async";
       int T2;
       F2() { }
       class B {B(this.x, [String boo]) { } int x;}
@@ -2364,6 +2385,7 @@
       expect(request.replacementOffset, completionOffset);
       expect(request.replacementLength, 0);
       assertSuggestImportedConstructor('Object');
+      assertSuggestImportedConstructor('Future');
       assertSuggestImportedConstructor('A');
       assertSuggestLocalConstructor('B');
       assertSuggestLocalConstructor('C');
@@ -2377,6 +2399,19 @@
     });
   }
 
+  test_InstanceCreationExpression_unimported() {
+    // SimpleIdentifier  TypeName  ConstructorName  InstanceCreationExpression
+    addSource('/testAB.dart', 'class Foo { }');
+    addTestSource('class C {foo(){new F^}}');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
+      assertSuggestImportedConstructor('Foo', relevance: DART_RELEVANCE_LOW);
+      assertSuggestImportedConstructor('Future', relevance: DART_RELEVANCE_LOW);
+    });
+  }
+
   test_InterpolationExpression() {
     // SimpleIdentifier  InterpolationExpression  StringInterpolation
     addSource('/testA.dart', '''
@@ -2589,7 +2624,9 @@
       assertSuggestImportedFunction('nowIsIt', null);
       assertNotSuggested('T1');
       // TODO (danrubel) this really should be TopLevelVar not getter/setter
-      assertSuggestTopLevelVarGetterSetter('newT1', 'int');
+      if (computer is ImportedComputer) {
+        assertSuggestGetter('newT1', 'int');
+      }
       assertNotSuggested('z');
       assertSuggestLocalTopLevelVar('m', 'dynamic');
       assertSuggestLocalFunction('newer', 'String');
@@ -2625,6 +2662,94 @@
     });
   }
 
+  test_MapLiteralEntry() {
+    // MapLiteralEntry  MapLiteral  VariableDeclaration
+    addSource('/testA.dart', '''
+      int T1;
+      F1() { }
+      typedef D1();
+      class C1 {C1(this.x) { } int x;}''');
+    addTestSource('''
+      import "/testA.dart";
+      int T2;
+      F2() { }
+      typedef D2();
+      class C2 { }
+      foo = {^''');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
+      assertSuggestImportedClass('Object');
+      // TODO(danrubel) Should be top level variable
+      if (computer is ImportedComputer) {
+        assertSuggestGetter('T1', 'int');
+        // assertSuggestImportedTopLevelVar('T1', 'int');
+      }
+      assertSuggestImportedFunction('F1', null);
+      assertSuggestImportedFunctionTypeAlias('D1', null);
+      assertSuggestImportedClass('C1');
+      assertSuggestLocalTopLevelVar('T2', 'int');
+      assertSuggestLocalFunction('F2', null);
+      assertSuggestLocalFunctionTypeAlias('D2', null);
+      assertSuggestLocalClass('C2');
+    });
+  }
+
+  test_MapLiteralEntry1() {
+    // MapLiteralEntry  MapLiteral  VariableDeclaration
+    addSource('/testA.dart', '''
+      int T1;
+      F1() { }
+      typedef D1();
+      class C1 {C1(this.x) { } int x;}''');
+    addTestSource('''
+      import "/testA.dart";
+      int T2;
+      F2() { }
+      typedef D2();
+      class C2 { }
+      foo = {T^''');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
+      // TODO(danrubel) Should be top level variable
+      if (computer is ImportedComputer) {
+        assertSuggestGetter('T1', 'int');
+        // assertSuggestImportedTopLevelVar('T1', 'int');
+      }
+      assertSuggestLocalTopLevelVar('T2', 'int');
+    });
+  }
+
+  test_MapLiteralEntry2() {
+    // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
+    addSource('/testA.dart', '''
+      int T1;
+      F1() { }
+      typedef D1();
+      class C1 {C1(this.x) { } int x;}''');
+    addTestSource('''
+      import "/testA.dart";
+      int T2;
+      F2() { }
+      typedef D2();
+      class C2 { }
+      foo = {7:T^};''');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
+      // TODO(danrubel) Should be top level variable
+      if (computer is ImportedComputer) {
+        assertSuggestGetter('T1', 'int');
+        // assertSuggestImportedTopLevelVar('T1', 'int');
+      }
+      assertSuggestLocalTopLevelVar('T2', 'int');
+    });
+  }
+
   test_MethodDeclaration_body_getters() {
     // Block  BlockFunctionBody  MethodDeclaration
     addTestSource('class A {@deprecated X get f => 0; Z a() {^} get _g => 1;}');
@@ -3400,6 +3525,55 @@
     });
   }
 
+  test_TypeArgumentList() {
+    // SimpleIdentifier  BinaryExpression  ExpressionStatement
+    addSource('/testA.dart', '''
+      class C1 {int x;}
+      F1() => 0;
+      typedef String T1(int blat);''');
+    addTestSource('''
+      import "/testA.dart";'
+      class C2 {int x;}
+      F2() => 0;
+      typedef int T2(int blat);
+      class C<E> {}
+      main() { C<^> c; }''');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
+      assertSuggestImportedClass('Object');
+      assertSuggestImportedClass('C1');
+      assertSuggestImportedFunctionTypeAlias('T1', 'String');
+      assertSuggestLocalClass('C2');
+      assertSuggestLocalFunctionTypeAlias('T2', 'int');
+      assertNotSuggested('F1');
+      assertNotSuggested('F2');
+    });
+  }
+
+  test_TypeArgumentList2() {
+    // TypeName  TypeArgumentList  TypeName
+    addSource('/testA.dart', '''
+      class C1 {int x;}
+      F1() => 0;
+      typedef String T1(int blat);''');
+    addTestSource('''
+      import "/testA.dart";'
+      class C2 {int x;}
+      F2() => 0;
+      typedef int T2(int blat);
+      class C<E> {}
+      main() { C<C^> c; }''');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
+      assertSuggestImportedClass('C1');
+      assertSuggestLocalClass('C2');
+    });
+  }
+
   test_VariableDeclaration_name() {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
diff --git a/pkg/analysis_server/test/services/completion/imported_computer_test.dart b/pkg/analysis_server/test/services/completion/imported_computer_test.dart
index 51870d0..fd323e2 100644
--- a/pkg/analysis_server/test/services/completion/imported_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/imported_computer_test.dart
@@ -117,8 +117,9 @@
   }
 
   @override
-  CompletionSuggestion assertSuggestImportedConstructor(String name) {
-    return assertSuggestConstructor(name);
+  CompletionSuggestion assertSuggestImportedConstructor(String name,
+      {int relevance: DART_RELEVANCE_DEFAULT}) {
+    return assertSuggestConstructor(name, relevance: relevance);
   }
 
   @override
@@ -592,9 +593,6 @@
   }
 
   test_mixin_ordering() {
-    // TODO(paulberry): The mixins are visited in the correct order, so we see
-    // M2.m() before M1.m(), as we should.  But the second (shadowed) result
-    // isn't being thrown out as it should.
     addSource('/libA.dart', '''
 class B {}
 class M1 {
diff --git a/pkg/analysis_server/test/services/completion/invocation_computer_test.dart b/pkg/analysis_server/test/services/completion/invocation_computer_test.dart
index 3cd9d67..16fcb6ec 100644
--- a/pkg/analysis_server/test/services/completion/invocation_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/invocation_computer_test.dart
@@ -137,6 +137,22 @@
     });
   }
 
+  test_libraryPrefix() {
+    // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
+    addTestSource('import "dart:async" as bar; foo() {bar.^}');
+    return computeFull((bool result) {
+      assertSuggestClass('Future');
+    });
+  }
+
+  test_libraryPrefix2() {
+    // SimpleIdentifier  MethodInvocation  ExpressionStatement
+    addTestSource('import "dart:async" as bar; foo() {bar.^ print("f")}');
+    return computeFull((bool result) {
+      assertSuggestClass('Future');
+    });
+  }
+
   test_local() {
     addTestSource('foo() {String x = "bar"; x.^}');
     return computeFull((bool result) {
@@ -399,7 +415,7 @@
       check_shadowing('int x;', 'set x(int value) {}', true);
 
   test_shadowing_getter_over_field() =>
-      check_shadowing('int get x => null;', 'int x;', false);
+      check_shadowing('int get x => null;', 'int x;', true);
 
   test_shadowing_getter_over_getter() =>
       check_shadowing('int get x => null;', 'int get x => null;', true);
@@ -408,7 +424,7 @@
       check_shadowing('int get x => null;', 'void x() {}', true);
 
   test_shadowing_getter_over_setter() =>
-      check_shadowing('int get x => null;', 'set x(int value) {}', false);
+      check_shadowing('int get x => null;', 'set x(int value) {}', true);
 
   test_shadowing_method_over_field() =>
       check_shadowing('void x() {}', 'int x;', true);
@@ -468,10 +484,10 @@
   }
 
   test_shadowing_setter_over_field() =>
-      check_shadowing('set x(int value) {}', 'int x;', false);
+      check_shadowing('set x(int value) {}', 'int x;', true);
 
   test_shadowing_setter_over_getter() =>
-      check_shadowing('set x(int value) {}', 'int get x => null;', false);
+      check_shadowing('set x(int value) {}', 'int get x => null;', true);
 
   test_shadowing_setter_over_method() =>
       check_shadowing('set x(int value) {}', 'void x() {}', true);
diff --git a/pkg/analysis_server/test/services/completion/local_computer_test.dart b/pkg/analysis_server/test/services/completion/local_computer_test.dart
index 05182d3..fed9d0f 100644
--- a/pkg/analysis_server/test/services/completion/local_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/local_computer_test.dart
@@ -194,6 +194,15 @@
     assertNotSuggested('x');
   }
 
+  test_overrides() {
+    addTestSource('''
+class A {m() {}}
+class B extends A {m() {^}}
+''');
+    expect(computeFast(), isTrue);
+    assertSuggestMethod('m', 'B', null, relevance: DART_RELEVANCE_LOCAL_METHOD);
+  }
+
   test_break_ignores_unrelated_statements() {
     addTestSource('''
 void main() {
@@ -225,6 +234,41 @@
     assertSuggestLabel('bar');
   }
 
+  test_constructor_parameters_mixed_required_and_named() {
+    addTestSource('class A {A(x, {int y}) {^}}');
+    expect(computeFast(), isTrue);
+    assertSuggestParameter('x', null);
+    assertSuggestParameter('y', 'int');
+  }
+
+  test_constructor_parameters_mixed_required_and_positional() {
+    addTestSource('class A {A(x, [int y]) {^}}');
+    expect(computeFast(), isTrue);
+    assertSuggestParameter('x', null);
+    assertSuggestParameter('y', 'int');
+  }
+
+  test_constructor_parameters_named() {
+    addTestSource('class A {A({x, int y}) {^}}');
+    expect(computeFast(), isTrue);
+    assertSuggestParameter('x', null);
+    assertSuggestParameter('y', 'int');
+  }
+
+  test_constructor_parameters_positional() {
+    addTestSource('class A {A([x, int y]) {^}}');
+    expect(computeFast(), isTrue);
+    assertSuggestParameter('x', null);
+    assertSuggestParameter('y', 'int');
+  }
+
+  test_constructor_parameters_required() {
+    addTestSource('class A {A(x, int y) {^}}');
+    expect(computeFast(), isTrue);
+    assertSuggestParameter('x', null);
+    assertSuggestParameter('y', 'int');
+  }
+
   test_continue_from_loop_to_switch() {
     addTestSource('''
 void main() {
@@ -698,4 +742,10 @@
     expect(suggestion.requiredParameterCount, 2);
     expect(suggestion.hasNamedParameters, false);
   }
+
+  test_shadowed_name() {
+    addTestSource('var a; class A { var a; m() { ^ } }');
+    expect(computeFast(), isTrue);
+    assertSuggestLocalField('a', null);
+  }
 }
diff --git a/pkg/analysis_server/test/services/completion/optype_test.dart b/pkg/analysis_server/test/services/completion/optype_test.dart
index 9ff44e5..897fb20 100644
--- a/pkg/analysis_server/test/services/completion/optype_test.dart
+++ b/pkg/analysis_server/test/services/completion/optype_test.dart
@@ -178,6 +178,12 @@
     assertOpType(returnValue: true, typeNames: true);
   }
 
+  test_BinaryExpression_RHS2() {
+    // SimpleIdentifier  BinaryExpression
+    addTestSource('main() {if (c < ^)}');
+    assertOpType(returnValue: true, typeNames: true);
+  }
+
   test_Block() {
     // Block  BlockFunctionBody  MethodDeclaration
     addTestSource('''
@@ -789,6 +795,24 @@
     assertOpType();
   }
 
+  test_MapLiteralEntry() {
+    // MapLiteralEntry  MapLiteral  VariableDeclaration
+    addTestSource('foo = {^');
+    assertOpType(returnValue: true, typeNames: true);
+  }
+
+  test_MapLiteralEntry1() {
+    // MapLiteralEntry  MapLiteral  VariableDeclaration
+    addTestSource('foo = {T^');
+    assertOpType(returnValue: true, typeNames: true);
+  }
+
+  test_MapLiteralEntry2() {
+    // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
+    addTestSource('foo = {7:T^};');
+    assertOpType(returnValue: true, typeNames: true);
+  }
+
   test_MethodDeclaration1() {
     // SimpleIdentifier  MethodDeclaration  ClassDeclaration
     addTestSource('class Bar {const ^Fara();}');
@@ -1046,6 +1070,18 @@
     assertOpType();
   }
 
+  test_TypeArgumentList() {
+    // SimpleIdentifier  BinaryExpression  ExpressionStatement
+    addTestSource('main() { C<^> c; }');
+    assertOpType(typeNames: true);
+  }
+
+  test_TypeArgumentList2() {
+    // TypeName  TypeArgumentList  TypeName
+    addTestSource('main() { C<C^> c; }');
+    assertOpType(typeNames: true);
+  }
+
   test_TypeParameter() {
     // SimpleIdentifier  TypeParameter  TypeParameterList
     addTestSource('class tezetst <String, ^List> {}');
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 399959c..bf4be15 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -451,6 +451,13 @@
   void set sourceFactory(SourceFactory factory);
 
   /**
+   * Return an array containing all of the sources known to this context.
+   *
+   * @return all of the sources known to this context
+   */
+  List<Source> get sources;
+
+  /**
    * Returns a type provider for this context or throws [AnalysisException] if
    * `dart:core` or `dart:async` cannot be resolved.
    */
@@ -1447,6 +1454,16 @@
     _invalidateAllLocalResolutionInformation(true);
   }
 
+  @override
+  List<Source> get sources {
+    List<Source> sources = new List<Source>();
+    MapIterator<Source, SourceEntry> iterator = _cache.iterator();
+    while (iterator.moveNext()) {
+      sources.add(iterator.key);
+    }
+    return sources;
+  }
+
   /**
    * Return a list of the sources that would be processed by [performAnalysisTask]. This
    * method duplicates, and must therefore be kept in sync with, [getNextAnalysisTask].
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index fb22d61..b56b46a 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -3737,7 +3737,7 @@
     indexField.type = intType;
     fields.add(indexField);
     getters.add(_createGetter(indexField));
-    FieldElementImpl valuesField = new FieldElementImpl("values", -1);
+    ConstFieldElementImpl valuesField = new ConstFieldElementImpl.con2("values", -1);
     valuesField.static = true;
     valuesField.const3 = true;
     valuesField.synthetic = true;
@@ -3748,6 +3748,7 @@
     // Build the enum constants.
     //
     NodeList<EnumConstantDeclaration> constants = node.constants;
+    List<DartObjectImpl> constantValues = new List<DartObjectImpl>();
     int constantCount = constants.length;
     for (int i = 0; i < constantCount; i++) {
       SimpleIdentifier constantName = constants[i].name;
@@ -3764,12 +3765,17 @@
       fieldMap[indexFieldName] = new DartObjectImpl(intType, new IntState(i));
       DartObjectImpl value =
           new DartObjectImpl(enumType, new GenericState(fieldMap));
+      constantValues.add(value);
       constantField.evaluationResult = new EvaluationResultImpl.con1(value);
       fields.add(constantField);
       getters.add(_createGetter(constantField));
       constantName.staticElement = constantField;
     }
     //
+    // Build the value of the 'values' field.
+    //
+    valuesField.evaluationResult = new EvaluationResultImpl.con1(new DartObjectImpl(valuesField.type, new ListState(constantValues)));
+    //
     // Finish building the enum.
     //
     enumElement.fields = fields;
@@ -14843,6 +14849,17 @@
   }
 
   @override
+  Object visitMethodDeclaration(MethodDeclaration node) {
+    ExecutableElement outerFunction = _enclosingFunction;
+    try {
+      _enclosingFunction = node.element;
+      return super.visitMethodDeclaration(node);
+    } finally {
+      _enclosingFunction = outerFunction;
+    }
+  }
+
+  @override
   Object visitFunctionExpression(FunctionExpression node) {
     if (node.parent is! FunctionDeclaration) {
       ExecutableElement outerFunction = _enclosingFunction;
diff --git a/pkg/analyzer/lib/src/generated/scanner.dart b/pkg/analyzer/lib/src/generated/scanner.dart
index 877a995..2685726 100644
--- a/pkg/analyzer/lib/src/generated/scanner.dart
+++ b/pkg/analyzer/lib/src/generated/scanner.dart
@@ -1492,7 +1492,6 @@
     int next = _reader.advance();
     outer: while (next != -1) {
       while (next != quoteChar) {
-        next = _reader.advance();
         if (next == -1) {
           break outer;
         } else if (next == 0xD) {
@@ -1502,7 +1501,9 @@
           }
           recordStartOfLine();
         } else if (next == 0xA) {
+          next = _reader.advance();
           recordStartOfLine();
+        } else {
           next = _reader.advance();
         }
       }
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 845711d..2c317aa 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -6337,18 +6337,21 @@
     expect(constant, isNotNull);
     expect(constant.name, firstName);
     expect(constant.isStatic, isTrue);
+    expect((constant as FieldElementImpl).evaluationResult, isNotNull);
     _assertGetter(constant);
 
     constant = fields[3];
     expect(constant, isNotNull);
     expect(constant.name, secondName);
     expect(constant.isStatic, isTrue);
+    expect((constant as FieldElementImpl).evaluationResult, isNotNull);
     _assertGetter(constant);
 
     constant = fields[4];
     expect(constant, isNotNull);
     expect(constant.name, thirdName);
     expect(constant.isStatic, isTrue);
+    expect((constant as FieldElementImpl).evaluationResult, isNotNull);
     _assertGetter(constant);
   }
 
@@ -6373,12 +6376,14 @@
     expect(field.name, "values");
     expect(field.isStatic, isTrue);
     expect(field.isSynthetic, isTrue);
+    expect((field as FieldElementImpl).evaluationResult, isNotNull);
     _assertGetter(field);
 
     FieldElement constant = fields[2];
     expect(constant, isNotNull);
     expect(constant.name, firstName);
     expect(constant.isStatic, isTrue);
+    expect((constant as FieldElementImpl).evaluationResult, isNotNull);
     _assertGetter(constant);
   }
 
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index 0949de7..2b2c5f3 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -5479,11 +5479,16 @@
   }
 
   @override
+  List<Source> get sources {
+    fail("Unexpected invocation of sources");
+    return null;
+  }
+
+  @override
   AnalysisContextStatistics get statistics {
     fail("Unexpected invocation of getStatistics");
     return null;
   }
-
   @override
   TypeProvider get typeProvider {
     fail("Unexpected invocation of getTypeProvider");
@@ -5734,6 +5739,7 @@
       int oldLength, int newLength) {
     fail("Unexpected invocation of setChangedContents");
   }
+
   @override
   void setContents(Source source, String contents) {
     fail("Unexpected invocation of setContents");
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index ca1eb93..21bc357 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -12600,6 +12600,37 @@
     expect(typeProvider.stringType.isSubtypeOf(t), isTrue);
   }
 
+  void test_mutatedOutsideScope() {
+    // https://code.google.com/p/dart/issues/detail?id=22732
+    Source source = addSource(r'''
+class Base {
+}
+
+class Derived extends Base {
+  get y => null;
+}
+
+class C {
+  void f() {
+    Base x = null;
+    if (x is Derived) {
+      print(x.y); // BAD
+    }
+    x = null;
+  }
+}
+
+void g() {
+  Base x = null;
+  if (x is Derived) {
+    print(x.y); // GOOD
+  }
+  x = null;
+}''');
+    resolve(source);
+    assertNoErrors(source);
+  }
+
   void test_objectMethodOnDynamicExpression_doubleEquals() {
     // https://code.google.com/p/dart/issues/detail?id=20342
     //
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 19e2a02..b65bd51 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -20,54 +20,6 @@
   runReflectiveTests(TokenTypeTest);
 }
 
-@reflectiveTest
-class CharSequenceReaderTest {
-  void test_advance() {
-    CharSequenceReader reader = new CharSequenceReader("x");
-    expect(reader.advance(), 0x78);
-    expect(reader.advance(), -1);
-    expect(reader.advance(), -1);
-  }
-
-  void test_creation() {
-    expect(new CharSequenceReader("x"), isNotNull);
-  }
-
-  void test_getOffset() {
-    CharSequenceReader reader = new CharSequenceReader("x");
-    expect(reader.offset, -1);
-    reader.advance();
-    expect(reader.offset, 0);
-    reader.advance();
-    expect(reader.offset, 0);
-  }
-
-  void test_getString() {
-    CharSequenceReader reader = new CharSequenceReader("xyzzy");
-    reader.offset = 3;
-    expect(reader.getString(1, 0), "yzz");
-    expect(reader.getString(2, 1), "zzy");
-  }
-
-  void test_peek() {
-    CharSequenceReader reader = new CharSequenceReader("xy");
-    expect(reader.peek(), 0x78);
-    expect(reader.peek(), 0x78);
-    reader.advance();
-    expect(reader.peek(), 0x79);
-    expect(reader.peek(), 0x79);
-    reader.advance();
-    expect(reader.peek(), -1);
-    expect(reader.peek(), -1);
-  }
-
-  void test_setOffset() {
-    CharSequenceReader reader = new CharSequenceReader("xyz");
-    reader.offset = 2;
-    expect(reader.offset, 2);
-  }
-}
-
 class CharacterRangeReaderTest extends EngineTestCase {
   void test_advance() {
     CharSequenceReader baseReader = new CharSequenceReader("xyzzy");
@@ -125,6 +77,54 @@
 }
 
 @reflectiveTest
+class CharSequenceReaderTest {
+  void test_advance() {
+    CharSequenceReader reader = new CharSequenceReader("x");
+    expect(reader.advance(), 0x78);
+    expect(reader.advance(), -1);
+    expect(reader.advance(), -1);
+  }
+
+  void test_creation() {
+    expect(new CharSequenceReader("x"), isNotNull);
+  }
+
+  void test_getOffset() {
+    CharSequenceReader reader = new CharSequenceReader("x");
+    expect(reader.offset, -1);
+    reader.advance();
+    expect(reader.offset, 0);
+    reader.advance();
+    expect(reader.offset, 0);
+  }
+
+  void test_getString() {
+    CharSequenceReader reader = new CharSequenceReader("xyzzy");
+    reader.offset = 3;
+    expect(reader.getString(1, 0), "yzz");
+    expect(reader.getString(2, 1), "zzy");
+  }
+
+  void test_peek() {
+    CharSequenceReader reader = new CharSequenceReader("xy");
+    expect(reader.peek(), 0x78);
+    expect(reader.peek(), 0x78);
+    reader.advance();
+    expect(reader.peek(), 0x79);
+    expect(reader.peek(), 0x79);
+    reader.advance();
+    expect(reader.peek(), -1);
+    expect(reader.peek(), -1);
+  }
+
+  void test_setOffset() {
+    CharSequenceReader reader = new CharSequenceReader("xyz");
+    reader.offset = 2;
+    expect(reader.offset, 2);
+  }
+}
+
+@reflectiveTest
 class KeywordStateTest {
   void test_KeywordState() {
     //
@@ -593,6 +593,15 @@
     ]);
   }
 
+  void test_lineInfo_multilineString_raw() {
+    String source = "var a = r'''\nblah\n''';\n\nfoo";
+    _assertLineInfo(source, [
+      new ScannerTest_ExpectedLocation(0, 1, 1),
+      new ScannerTest_ExpectedLocation(14, 2, 2),
+      new ScannerTest_ExpectedLocation(source.length - 2, 5, 2)
+    ]);
+  }
+
   void test_lineInfo_simpleClass() {
     String source =
         "class Test {\r\n    String s = '...';\r\n    int get x => s.MISSING_GETTER;\r\n}";
@@ -639,10 +648,6 @@
     _assertToken(TokenType.MINUS_MINUS, "--");
   }
 
-  void test_openSquareBracket() {
-    _assertToken(TokenType.OPEN_SQUARE_BRACKET, "[");
-  }
-
   void test_open_curly_bracket() {
     _assertToken(TokenType.OPEN_CURLY_BRACKET, "{");
   }
@@ -655,6 +660,10 @@
     _assertToken(TokenType.OPEN_SQUARE_BRACKET, "[");
   }
 
+  void test_openSquareBracket() {
+    _assertToken(TokenType.OPEN_SQUARE_BRACKET, "[");
+  }
+
   void test_percent() {
     _assertToken(TokenType.PERCENT, "%");
   }
@@ -667,6 +676,14 @@
     _assertToken(TokenType.PERIOD, ".");
   }
 
+  void test_period_period() {
+    _assertToken(TokenType.PERIOD_PERIOD, "..");
+  }
+
+  void test_period_period_period() {
+    _assertToken(TokenType.PERIOD_PERIOD_PERIOD, "...");
+  }
+
   void test_periodAfterNumberNotIncluded_identifier() {
     _assertTokens("42.isEven()", [
       new StringToken(TokenType.INT, "42", 0),
@@ -687,14 +704,6 @@
     ]);
   }
 
-  void test_period_period() {
-    _assertToken(TokenType.PERIOD_PERIOD, "..");
-  }
-
-  void test_period_period_period() {
-    _assertToken(TokenType.PERIOD_PERIOD_PERIOD, "...");
-  }
-
   void test_plus() {
     _assertToken(TokenType.PLUS, "+");
   }
@@ -715,14 +724,14 @@
     _assertToken(TokenType.SCRIPT_TAG, "#!/bin/dart -debug");
   }
 
-  void test_scriptTag_withSpace() {
-    _assertToken(TokenType.SCRIPT_TAG, "#! /bin/dart");
-  }
-
   void test_scriptTag_withoutSpace() {
     _assertToken(TokenType.SCRIPT_TAG, "#!/bin/dart");
   }
 
+  void test_scriptTag_withSpace() {
+    _assertToken(TokenType.SCRIPT_TAG, "#! /bin/dart");
+  }
+
   void test_semicolon() {
     _assertToken(TokenType.SEMICOLON, ";");
   }
@@ -840,8 +849,8 @@
 
   void test_string_raw_multi_unterminated() {
     String source = "r'''string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-        9, source, [new StringToken(TokenType.STRING, source, 0)]);
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 9,
+        source, [new StringToken(TokenType.STRING, source, 0)]);
   }
 
   void test_string_raw_simple_double() {
@@ -854,14 +863,14 @@
 
   void test_string_raw_simple_unterminated_eof() {
     String source = "r'string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-        7, source, [new StringToken(TokenType.STRING, source, 0)]);
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 7,
+        source, [new StringToken(TokenType.STRING, source, 0)]);
   }
 
   void test_string_raw_simple_unterminated_eol() {
     String source = "r'string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-        8, "$source\n", [new StringToken(TokenType.STRING, source, 0)]);
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 8,
+        "$source\n", [new StringToken(TokenType.STRING, source, 0)]);
   }
 
   void test_string_simple_double() {
@@ -957,14 +966,14 @@
 
   void test_string_simple_unterminated_eof() {
     String source = "'string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-        6, source, [new StringToken(TokenType.STRING, source, 0)]);
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 6,
+        source, [new StringToken(TokenType.STRING, source, 0)]);
   }
 
   void test_string_simple_unterminated_eol() {
     String source = "'string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-        7, "$source\r", [new StringToken(TokenType.STRING, source, 0)]);
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 7,
+        "$source\r", [new StringToken(TokenType.STRING, source, 0)]);
   }
 
   void test_string_simple_unterminated_interpolation_block() {
@@ -1044,9 +1053,8 @@
     GatheringErrorListener listener = new GatheringErrorListener();
     _scanWithListener(source, listener);
     listener.assertErrors([
-      new AnalysisError.con2(null, expectedOffset, 1, expectedError, [
-        source.codeUnitAt(expectedOffset)
-      ])
+      new AnalysisError.con2(null, expectedOffset, 1, expectedError,
+          [source.codeUnitAt(expectedOffset)])
     ]);
   }
 
@@ -1064,9 +1072,8 @@
     GatheringErrorListener listener = new GatheringErrorListener();
     Token token = _scanWithListener(source, listener);
     listener.assertErrors([
-      new AnalysisError.con2(null, expectedOffset, 1, expectedError, [
-        source.codeUnitAt(expectedOffset)
-      ])
+      new AnalysisError.con2(null, expectedOffset, 1, expectedError,
+          [source.codeUnitAt(expectedOffset)])
     ]);
     _checkTokens(token, expectedTokens);
   }
@@ -1104,10 +1111,14 @@
     listener.assertNoErrors();
     LineInfo info = listener.getLineInfo(new TestSource());
     expect(info, isNotNull);
-    for (ScannerTest_ExpectedLocation expectedLocation in expectedLocations) {
+    int count = expectedLocations.length;
+    for (int i = 0; i < count; i++) {
+      ScannerTest_ExpectedLocation expectedLocation = expectedLocations[i];
       LineInfo_Location location = info.getLocation(expectedLocation._offset);
-      expect(location.lineNumber, expectedLocation._lineNumber);
-      expect(location.columnNumber, expectedLocation._columnNumber);
+      expect(location.lineNumber, expectedLocation._lineNumber,
+          reason: 'Line number in location $i');
+      expect(location.columnNumber, expectedLocation._columnNumber,
+          reason: 'Column number in location $i');
     }
   }
 
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index f82d327..4eb0e0b 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -514,6 +514,9 @@
   }
 
   @override
+  List<Source> get sources => baseContext.sources;
+
+  @override
   AnalysisContextStatistics get statistics => baseContext.statistics;
 
   @override
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 6540829..0f1f433 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -399,11 +399,14 @@
     // Note that RegExes, js.ArrayInitializer and js.ObjectInitializer are not
     // [js.Literal]s.
     if (result is js.Literal) return result;
+
     js.Expression tempVar = useTempVar(allocateTempVar());
     addStatement(js.js.statement('# = #;', [tempVar, result]));
     return tempVar;
   }
 
+  // TODO(sigurdm): This is obsolete - all calls use store: false. Replace with
+  // visitExpression(node);
   withExpression(js.Expression node, fn(js.Expression result), {bool store}) {
     int oldTempVarIndex = currentTempVarIndex;
     js.Expression visited = visitExpression(node);
@@ -415,6 +418,46 @@
     return result;
   }
 
+  /// Calls [fn] with the result of evaluating [node]. Taking special care of
+  /// property accesses.
+  ///
+  /// If [store] is true the result of evaluating [node] is stored in a
+  /// temporary.
+  ///
+  /// We cannot rewrite `<receiver>.m()` to:
+  ///     temp = <receiver>.m;
+  ///     temp();
+  /// Because this leaves `this` unbound in the call. But because of dart
+  /// evaluation order we can write:
+  ///     temp = <receiver>;
+  ///     temp.m();
+  withCallTargetExpression(js.Expression node,
+                           fn(js.Expression result), {bool store}) {
+    int oldTempVarIndex = currentTempVarIndex;
+    js.Expression visited = visitExpression(node);
+    js.Expression selector;
+    js.Expression storedIfNeeded;
+    if (store) {
+      if (visited is js.PropertyAccess) {
+        js.PropertyAccess propertyAccess = visited;
+        selector = propertyAccess.selector;
+        visited = propertyAccess.receiver;
+      }
+      storedIfNeeded = _storeIfNecessary(visited);
+    } else {
+      storedIfNeeded = visited;
+    }
+    js.Expression result;
+    if (selector == null) {
+      result = fn(storedIfNeeded);
+    } else {
+      result = fn(new js.PropertyAccess(storedIfNeeded, selector));
+    }
+    currentTempVarIndex = oldTempVarIndex;
+    return result;
+  }
+
+
   /// Calls [fn] with the value of evaluating [node1] and [node2].
   ///
   /// If `shouldTransform(node2)` the first expression is stored in a temporary
@@ -761,11 +804,11 @@
         js.Statement assignLeft = isResult(left)
             ? new js.Block.empty()
             : js.js.statement('# = #;', [result, left]);
-        if (node.op == "||") {
+        if (node.op == "&&") {
           addStatement(js.js.statement('if (#) {#} else #',
               [left, gotoAndBreak(thenLabel), assignLeft]));
         } else {
-          assert(node.op == "&&");
+          assert(node.op == "||");
           addStatement(js.js.statement('if (#) {#} else #',
               [left, assignLeft, gotoAndBreak(thenLabel)]));
         }
@@ -805,7 +848,7 @@
   @override
   js.Expression visitCall(js.Call node) {
     bool storeTarget = node.arguments.any(shouldTransform);
-    return withExpression(node.target, (target) {
+    return withCallTargetExpression(node.target, (target) {
       return withExpressions(node.arguments, (List<js.Expression> arguments) {
         return new js.Call(target, arguments);
       });
@@ -920,7 +963,8 @@
       bool oldInsideUntranslatedBreakable = insideUntranslatedBreakable;
       insideUntranslatedBreakable = true;
       withExpression(node.condition, (js.Expression condition) {
-        addStatement(js.js.statement('do {#} while (#)', [node.body, condition]));
+        addStatement(js.js.statement('do {#} while (#)',
+                                     [node.body, condition]));
       }, store: false);
       insideUntranslatedBreakable = oldInsideUntranslatedBreakable;
       return;
@@ -1148,7 +1192,7 @@
   @override
   js.Expression visitNew(js.New node) {
     bool storeTarget = node.arguments.any(shouldTransform);
-    return withExpression(node.target, (target) {
+    return withCallTargetExpression(node.target, (target) {
       return withExpressions(node.arguments, (List<js.Expression> arguments) {
         return new js.New(target, arguments);
       });
@@ -1777,7 +1821,8 @@
                         js.VariableDeclarationList variableDeclarations) {
     // Each iterator invocation on the iterable should work on its own copy of
     // the parameters.
-    // TODO(sigurdm): We only need to do this copying for parameters that are mutated.
+    // TODO(sigurdm): We only need to do this copying for parameters that are
+    // mutated.
     List<js.VariableInitialization> declarations =
         new List<js.VariableInitialization>();
     List<js.Parameter> renamedParameters = new List<js.Parameter>();
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index 4fe35e5..18db66c 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -243,7 +243,9 @@
 
 class ExpressionStatement extends Statement {
   final Expression expression;
-  ExpressionStatement(this.expression);
+  ExpressionStatement(this.expression) {
+    assert(this.expression != null);
+  }
 
   accept(NodeVisitor visitor) => visitor.visitExpressionStatement(this);
   void visitChildren(NodeVisitor visitor) { expression.accept(visitor); }
diff --git a/tests/compiler/dart2js/async_await_js_transform_test.dart b/tests/compiler/dart2js/async_await_js_transform_test.dart
index 2483ceb..be164df6 100644
--- a/tests/compiler/dart2js/async_await_js_transform_test.dart
+++ b/tests/compiler/dart2js/async_await_js_transform_test.dart
@@ -262,12 +262,13 @@
         case 0:
           // Function start
           __temp1 = foo1();
-          if (__temp1) {
+          if (__temp1)
+            __result = __temp1;
+          else {
             // goto then
             __goto = 2;
             break;
-          } else
-            __result = __temp1;
+          }
           // goto join
           __goto = 3;
           break;
@@ -290,12 +291,13 @@
         case 8:
           // returning from await.
           __temp1 = __result;
-          if (__temp1) {
+          if (__temp1)
+            __result = __temp1;
+          else {
             // goto then
             __goto = 6;
             break;
-          } else
-            __result = __temp1;
+          }
           // goto join
           __goto = 7;
           break;
@@ -312,13 +314,12 @@
           c = __result;
           d = foo1() || foo2();
           __temp1 = foo1();
-          if (__temp1)
-            __result = __temp1;
-          else {
+          if (__temp1) {
             // goto then
             __goto = 10;
             break;
-          }
+          } else
+            __result = __temp1;
           // goto join
           __goto = 11;
           break;
@@ -341,13 +342,12 @@
         case 16:
           // returning from await.
           __temp1 = __result;
-          if (__temp1)
-            __result = __temp1;
-          else {
+          if (__temp1) {
             // goto then
             __goto = 14;
             break;
-          }
+          } else
+            __result = __temp1;
           // goto join
           __goto = 15;
           break;
diff --git a/tests/language/async_and_or_test.dart b/tests/language/async_and_or_test.dart
new file mode 100644
index 0000000..78a3758
--- /dev/null
+++ b/tests/language/async_and_or_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+@NoInline
+@AssumeDynamic
+confuse(x) {
+  return x;
+}
+
+test1() async {
+  Expect.isFalse(await confuse(false) && await confuse(false));
+  Expect.isFalse(await confuse(false) && await confuse(true));
+  Expect.isFalse(await confuse(true) && await confuse(false));
+  Expect.isTrue(await confuse(true) && await confuse(true));
+
+  Expect.isFalse(await confuse(false) || await confuse(false));
+  Expect.isTrue(await confuse(false) || await confuse(true));
+  Expect.isTrue(await confuse(true) || await confuse(false));
+  Expect.isTrue(await confuse(true) || await confuse(true));
+}
+
+String trace;
+
+traceA(x) {
+  trace += "a";
+  return x;
+}
+traceB(x) {
+  trace += "b";
+  return x;
+}
+
+testEvaluation(void fn()) async {
+  trace = "";
+  await fn();
+}
+
+test2() async {
+  await testEvaluation(() async {
+    Expect.isFalse(
+        await confuse(traceA(false)) && await confuse(traceB(false)));
+    Expect.equals("a", trace);
+  });
+  await testEvaluation(() async {
+    Expect.isFalse(await confuse(traceA(false)) && await confuse(traceB(true)));
+    Expect.equals("a", trace);
+  });
+  await testEvaluation(() async {
+    Expect.isFalse(await confuse(traceA(true)) && await confuse(traceB(false)));
+    Expect.equals("ab", trace);
+  });
+  await testEvaluation(() async {
+    Expect.isTrue(await confuse(traceA(true)) && await confuse(traceB(true)));
+    Expect.equals("ab", trace);
+  });
+
+  await testEvaluation(() async {
+    Expect.isFalse(
+        await confuse(traceA(false)) || await confuse(traceB(false)));
+    Expect.equals("ab", trace);
+  });
+  await testEvaluation(() async {
+    Expect.isTrue(await confuse(traceA(false)) || await confuse(traceB(true)));
+    Expect.equals("ab", trace);
+  });
+  await testEvaluation(() async {
+    Expect.isTrue(await confuse(traceA(true)) || await confuse(traceB(false)));
+    Expect.equals("a", trace);
+  });
+  await testEvaluation(() async {
+    Expect.isTrue(await confuse(traceA(true)) || await confuse(traceB(true)));
+    Expect.equals("a", trace);
+  });
+
+}
+
+test() async {
+  await test1();
+  await test2();
+}
+
+main() {
+  asyncStart();
+  test().then((_) => asyncEnd());
+}
diff --git a/tests/language/async_this_bound_test.dart b/tests/language/async_this_bound_test.dart
new file mode 100644
index 0000000..8757f03
--- /dev/null
+++ b/tests/language/async_this_bound_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+class A {
+  int a = -1;
+
+  @NoInline()
+  foo(ignored, val) {
+    Expect.equals(val, this.a);
+  }
+}
+
+testA() async {
+  var a = new A();
+  a.foo(await false, -1);
+  a.a = 0;
+  a.foo(await false, 0);
+}
+
+@NoInline()
+@AssumeDynamic()
+confuse(x) => x;
+
+class B {
+  var f;
+  @NoInline()
+  var b = 10;
+  B(this.f);
+
+  bar(x) => b;
+}
+
+foo(x) => 499;
+bar(x) => 42;
+
+change(x) {
+  x.f = (x) => 99;
+}
+
+testB() async {
+  var b = confuse(new B(foo));
+  Expect.equals(99, b.f(await change(b)));
+  var b2 = confuse(new B(bar));
+  Expect.equals(10, b2.f(await (b2.f = b2.bar)));
+}
+
+test() async {
+  await testA();
+  await testB();
+}
+
+void main() {
+  asyncStart();
+  test().then((_) => asyncEnd());
+}
\ No newline at end of file
diff --git a/tools/VERSION b/tools/VERSION
index c00da2d..f71127e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 9
 PATCH 0
 PRERELEASE 10
-PRERELEASE_PATCH 6
+PRERELEASE_PATCH 7