Version 2.1.0-dev.9.1

Cherry-pick commit 0fe448a99643e149acb2e7e32d7a30eba7dd646d to dev
Cherry-pick commit 45d070d437bb1b596516edd3717e6ee614c5f9ac to dev
Cherry-pick commit 00f27a32cf52834b3e9e1f52889b6f1c83ad338c to dev
Cherry-pick commit 523353d28017fced825581ea327509c620eed67e to dev
Cherry-pick commit db4271378f56a66528a87f2f920c678162d59a35 to dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b5b04a..cd8adc1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+## 2.1.0-dev.9.1
+
+Cherry-pick commit 0fe448a99643e149acb2e7e32d7a30eba7dd646d to update the analysis server edit.dartfix protocol.
+
+Cherry-pick commit 45d070d437bb1b596516edd3717e6ee614c5f9ac to update linter to version 0.1.71.
+
+Cherry-pick commit 00f27a32cf52834b3e9e1f52889b6f1c83ad338c to fix usage of mixins in dart dev compiler.
+
+Cherry-pick commit 523353d28017fced825581ea327509c620eed67e to fix the ARM 32-bit build.
+
+Cherry-pick commit db4271378f56a66528a87f2f920c678162d59a35 to fix an
+issue with coverage
+
 ## 2.1.0-dev.9.0
 
 ## 2.1.0-dev.8.0
diff --git a/DEPS b/DEPS
index 3ded0c6..5323847 100644
--- a/DEPS
+++ b/DEPS
@@ -95,7 +95,7 @@
   "intl_tag": "0.15.7",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "2.0.9",
-  "linter_tag": "0.1.70",
+  "linter_tag": "0.1.71",
   "logging_tag": "0.11.3+2",
   "markdown_tag": "2.0.2",
   "matcher_tag": "0.12.3",
diff --git a/build/.gitignore b/build/.gitignore
index 0c6f306..869cdb4 100644
--- a/build/.gitignore
+++ b/build/.gitignore
@@ -4,7 +4,5 @@
 # Pulled Debian wheezy sysroots
 linux/debian_jessie_arm-sysroot
 linux/debian_jessie_arm64-sysroot
-linux/debian_wheezy_amd64-sysroot
 linux/debian_jessie_amd64-sysroot
-linux/debian_wheezy_arm-sysroot
-linux/debian_wheezy_i386-sysroot
+linux/debian_jessie_i386-sysroot
diff --git a/build/config/linux/BUILD.gn b/build/config/linux/BUILD.gn
index 215025b..62f7524 100644
--- a/build/config/linux/BUILD.gn
+++ b/build/config/linux/BUILD.gn
@@ -18,12 +18,12 @@
                              ],
                              "value") ]
 
-    # When using the pulled wheezy sysroot with gcc, we have to specify these
+    # When using the pulled Debian sysroot with gcc, we have to specify these
     # excplicitly.
-    if (dart_use_wheezy_sysroot && !is_clang) {
+    if (dart_use_debian_sysroot && !is_clang) {
       cflags += [
-        "-I=/usr/include/c++/4.6",
-        "-I=/usr/include/c++/4.6/i486-linux-gnu",
+        "-I=/usr/include/c++/4.8",
+        "-I=/usr/include/c++/4.8/i486-linux-gnu",
       ]
     }
   }
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index b1acdf6..a4364ac 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -10,25 +10,21 @@
   # the target toolchain.
   target_sysroot = ""
 
-  # Whether the Debian wheezy sysroot should be used.
-  dart_use_wheezy_sysroot = false
+  # Whether the Debian sysroot should be used.
+  dart_use_debian_sysroot = false
 }
 
-if (is_linux && dart_use_wheezy_sysroot) {
+if (is_linux && dart_use_debian_sysroot) {
   if (current_cpu == "x86") {
-    target_sysroot = rebase_path("//build/linux/debian_wheezy_i386-sysroot", root_build_dir)
+    target_sysroot = rebase_path("//build/linux/debian_jessie_i386-sysroot", root_build_dir)
   } else if (current_cpu == "x64") {
-    if (is_asan || is_lsan || is_msan || is_tsan) {
-      target_sysroot = rebase_path("//build/linux/debian_jessie_amd64-sysroot", root_build_dir)
-    } else {
-      target_sysroot = rebase_path("//build/linux/debian_wheezy_amd64-sysroot", root_build_dir)
-    }
+    target_sysroot = rebase_path("//build/linux/debian_jessie_amd64-sysroot", root_build_dir)
   } else if (current_cpu == "arm") {
-    target_sysroot = rebase_path("//build/linux/debian_wheezy_arm-sysroot", root_build_dir)
+    target_sysroot = rebase_path("//build/linux/debian_jessie_arm-sysroot", root_build_dir)
   } else if (current_cpu == "arm64") {
     target_sysroot = rebase_path("//build/linux/debian_jessie_arm64-sysroot", root_build_dir)
   } else {
-    print("There is no Debian wheezy sysroot present for $current_cpu")
+    print("There is no Debian sysroot present for $current_cpu")
     assert(false)
   }
 }
diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py
index 88bdd62..4500023 100755
--- a/build/linux/sysroot_scripts/install-sysroot.py
+++ b/build/linux/sysroot_scripts/install-sysroot.py
@@ -95,16 +95,15 @@
 
 def InstallDefaultSysrootForArch(target_arch):
   if target_arch == 'amd64':
-    InstallSysroot('Wheezy', 'amd64')
     InstallSysroot('Jessie', 'amd64')
   elif target_arch == 'arm':
-    InstallSysroot('Wheezy', 'arm')
+    InstallSysroot('Jessie', 'arm')
   elif target_arch == 'arm64':
     InstallSysroot('Jessie', 'arm64')
   elif target_arch == 'i386':
-    InstallSysroot('Wheezy', 'i386')
+    InstallSysroot('Jessie', 'i386')
   elif target_arch == 'mips':
-    InstallSysroot('Wheezy', 'mips')
+    InstallSysroot('Jessie', 'mips')
   else:
     raise Error('Unknown architecture: %s' % target_arch)
 
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 15e83c4..5af3aa0 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -2660,6 +2660,7 @@
   
   
   
+  
 <dl><dt class="typeDefinition"><a name="type_AddContentOverlay">AddContentOverlay: object</a></dt><dd>
     <p>
       A directive to begin overlaying the contents of a file. The supplied
@@ -4379,9 +4380,9 @@
       </dd></dl></dd><dt class="typeDefinition"><a name="type_RuntimeCompletionExpression">RuntimeCompletionExpression: object</a></dt><dd>
     <p>
       An expression for which we want to know its runtime type.
-      In expressions like `a.b.c.where((e) =&gt; e.^)` we want to know the
-      runtime type of `a.b.c` to enforce it statically at the time when we
-      compute completion suggestions, and get better type for `e`.
+      In expressions like 'a.b.c.where((e) =&gt; e.^)' we want to know the
+      runtime type of 'a.b.c' to enforce it statically at the time when we
+      compute completion suggestions, and get better type for 'e'.
     </p>
     
   <dl><dt class="field"><b>offset: int</b></dt><dd>
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 9d85d08..1280460 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -173,11 +173,10 @@
 const String EDIT_REQUEST_ORGANIZE_DIRECTIVES_FILE = 'file';
 const String EDIT_REQUEST_SORT_MEMBERS = 'edit.sortMembers';
 const String EDIT_REQUEST_SORT_MEMBERS_FILE = 'file';
-const String EDIT_RESPONSE_DARTFIX_DESCRIPTION_OF_FIXES = 'descriptionOfFixes';
-const String EDIT_RESPONSE_DARTFIX_FIXES = 'fixes';
+const String EDIT_RESPONSE_DARTFIX_EDITS = 'edits';
 const String EDIT_RESPONSE_DARTFIX_HAS_ERRORS = 'hasErrors';
-const String EDIT_RESPONSE_DARTFIX_OTHER_RECOMMENDATIONS =
-    'otherRecommendations';
+const String EDIT_RESPONSE_DARTFIX_OTHER_SUGGESTIONS = 'otherSuggestions';
+const String EDIT_RESPONSE_DARTFIX_SUGGESTIONS = 'suggestions';
 const String EDIT_RESPONSE_FORMAT_EDITS = 'edits';
 const String EDIT_RESPONSE_FORMAT_SELECTION_LENGTH = 'selectionLength';
 const String EDIT_RESPONSE_FORMAT_SELECTION_OFFSET = 'selectionOffset';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index cb7d946..3a0a480 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -5932,6 +5932,105 @@
 }
 
 /**
+ * DartFixSuggestion
+ *
+ * {
+ *   "description": String
+ *   "location": optional Location
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class DartFixSuggestion implements HasToJson {
+  String _description;
+
+  Location _location;
+
+  /**
+   * A human readable description of the suggested change.
+   */
+  String get description => _description;
+
+  /**
+   * A human readable description of the suggested change.
+   */
+  void set description(String value) {
+    assert(value != null);
+    this._description = value;
+  }
+
+  /**
+   * The location of the suggested change.
+   */
+  Location get location => _location;
+
+  /**
+   * The location of the suggested change.
+   */
+  void set location(Location value) {
+    this._location = value;
+  }
+
+  DartFixSuggestion(String description, {Location location}) {
+    this.description = description;
+    this.location = location;
+  }
+
+  factory DartFixSuggestion.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String description;
+      if (json.containsKey("description")) {
+        description = jsonDecoder.decodeString(
+            jsonPath + ".description", json["description"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "description");
+      }
+      Location location;
+      if (json.containsKey("location")) {
+        location = new Location.fromJson(
+            jsonDecoder, jsonPath + ".location", json["location"]);
+      }
+      return new DartFixSuggestion(description, location: location);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "DartFixSuggestion", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["description"] = description;
+    if (location != null) {
+      result["location"] = location.toJson();
+    }
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is DartFixSuggestion) {
+      return description == other.description && location == other.location;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, description.hashCode);
+    hash = JenkinsSmiHash.combine(hash, location.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * diagnostic.getDiagnostics params
  *
  * Clients may not extend, implement or mix-in this class.
@@ -6268,60 +6367,60 @@
  * edit.dartfix result
  *
  * {
- *   "descriptionOfFixes": List<String>
- *   "otherRecommendations": List<String>
+ *   "suggestions": List<DartFixSuggestion>
+ *   "otherSuggestions": List<DartFixSuggestion>
  *   "hasErrors": bool
- *   "fixes": List<SourceFileEdit>
+ *   "edits": List<SourceFileEdit>
  * }
  *
  * Clients may not extend, implement or mix-in this class.
  */
 class EditDartfixResult implements ResponseResult {
-  List<String> _descriptionOfFixes;
+  List<DartFixSuggestion> _suggestions;
 
-  List<String> _otherRecommendations;
+  List<DartFixSuggestion> _otherSuggestions;
 
   bool _hasErrors;
 
-  List<SourceFileEdit> _fixes;
+  List<SourceFileEdit> _edits;
 
   /**
-   * A list of human readable changes made by applying the fixes.
+   * A list of recommended changes that can be automatically made by applying
+   * the 'edits' included in this response.
    */
-  List<String> get descriptionOfFixes => _descriptionOfFixes;
+  List<DartFixSuggestion> get suggestions => _suggestions;
 
   /**
-   * A list of human readable changes made by applying the fixes.
+   * A list of recommended changes that can be automatically made by applying
+   * the 'edits' included in this response.
    */
-  void set descriptionOfFixes(List<String> value) {
+  void set suggestions(List<DartFixSuggestion> value) {
     assert(value != null);
-    this._descriptionOfFixes = value;
+    this._suggestions = value;
   }
 
   /**
-   * A list of human readable recommended changes that cannot be made
-   * automatically.
+   * A list of recommended changes that could not be automatically made.
    */
-  List<String> get otherRecommendations => _otherRecommendations;
+  List<DartFixSuggestion> get otherSuggestions => _otherSuggestions;
 
   /**
-   * A list of human readable recommended changes that cannot be made
-   * automatically.
+   * A list of recommended changes that could not be automatically made.
    */
-  void set otherRecommendations(List<String> value) {
+  void set otherSuggestions(List<DartFixSuggestion> value) {
     assert(value != null);
-    this._otherRecommendations = value;
+    this._otherSuggestions = value;
   }
 
   /**
    * True if the analyzed source contains errors that might impact the
-   * correctness of the recommended fixes that can be automatically applied.
+   * correctness of the recommended changes that can be automatically applied.
    */
   bool get hasErrors => _hasErrors;
 
   /**
    * True if the analyzed source contains errors that might impact the
-   * correctness of the recommended fixes that can be automatically applied.
+   * correctness of the recommended changes that can be automatically applied.
    */
   void set hasErrors(bool value) {
     assert(value != null);
@@ -6329,27 +6428,27 @@
   }
 
   /**
-   * The suggested fixes.
+   * A list of source edits to apply the recommended changes.
    */
-  List<SourceFileEdit> get fixes => _fixes;
+  List<SourceFileEdit> get edits => _edits;
 
   /**
-   * The suggested fixes.
+   * A list of source edits to apply the recommended changes.
    */
-  void set fixes(List<SourceFileEdit> value) {
+  void set edits(List<SourceFileEdit> value) {
     assert(value != null);
-    this._fixes = value;
+    this._edits = value;
   }
 
   EditDartfixResult(
-      List<String> descriptionOfFixes,
-      List<String> otherRecommendations,
+      List<DartFixSuggestion> suggestions,
+      List<DartFixSuggestion> otherSuggestions,
       bool hasErrors,
-      List<SourceFileEdit> fixes) {
-    this.descriptionOfFixes = descriptionOfFixes;
-    this.otherRecommendations = otherRecommendations;
+      List<SourceFileEdit> edits) {
+    this.suggestions = suggestions;
+    this.otherSuggestions = otherSuggestions;
     this.hasErrors = hasErrors;
-    this.fixes = fixes;
+    this.edits = edits;
   }
 
   factory EditDartfixResult.fromJson(
@@ -6358,23 +6457,25 @@
       json = {};
     }
     if (json is Map) {
-      List<String> descriptionOfFixes;
-      if (json.containsKey("descriptionOfFixes")) {
-        descriptionOfFixes = jsonDecoder.decodeList(
-            jsonPath + ".descriptionOfFixes",
-            json["descriptionOfFixes"],
-            jsonDecoder.decodeString);
+      List<DartFixSuggestion> suggestions;
+      if (json.containsKey("suggestions")) {
+        suggestions = jsonDecoder.decodeList(
+            jsonPath + ".suggestions",
+            json["suggestions"],
+            (String jsonPath, Object json) =>
+                new DartFixSuggestion.fromJson(jsonDecoder, jsonPath, json));
       } else {
-        throw jsonDecoder.mismatch(jsonPath, "descriptionOfFixes");
+        throw jsonDecoder.mismatch(jsonPath, "suggestions");
       }
-      List<String> otherRecommendations;
-      if (json.containsKey("otherRecommendations")) {
-        otherRecommendations = jsonDecoder.decodeList(
-            jsonPath + ".otherRecommendations",
-            json["otherRecommendations"],
-            jsonDecoder.decodeString);
+      List<DartFixSuggestion> otherSuggestions;
+      if (json.containsKey("otherSuggestions")) {
+        otherSuggestions = jsonDecoder.decodeList(
+            jsonPath + ".otherSuggestions",
+            json["otherSuggestions"],
+            (String jsonPath, Object json) =>
+                new DartFixSuggestion.fromJson(jsonDecoder, jsonPath, json));
       } else {
-        throw jsonDecoder.mismatch(jsonPath, "otherRecommendations");
+        throw jsonDecoder.mismatch(jsonPath, "otherSuggestions");
       }
       bool hasErrors;
       if (json.containsKey("hasErrors")) {
@@ -6383,18 +6484,18 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "hasErrors");
       }
-      List<SourceFileEdit> fixes;
-      if (json.containsKey("fixes")) {
-        fixes = jsonDecoder.decodeList(
-            jsonPath + ".fixes",
-            json["fixes"],
+      List<SourceFileEdit> edits;
+      if (json.containsKey("edits")) {
+        edits = jsonDecoder.decodeList(
+            jsonPath + ".edits",
+            json["edits"],
             (String jsonPath, Object json) =>
                 new SourceFileEdit.fromJson(jsonDecoder, jsonPath, json));
       } else {
-        throw jsonDecoder.mismatch(jsonPath, "fixes");
+        throw jsonDecoder.mismatch(jsonPath, "edits");
       }
       return new EditDartfixResult(
-          descriptionOfFixes, otherRecommendations, hasErrors, fixes);
+          suggestions, otherSuggestions, hasErrors, edits);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix result", json);
     }
@@ -6410,11 +6511,14 @@
   @override
   Map<String, dynamic> toJson() {
     Map<String, dynamic> result = {};
-    result["descriptionOfFixes"] = descriptionOfFixes;
-    result["otherRecommendations"] = otherRecommendations;
+    result["suggestions"] =
+        suggestions.map((DartFixSuggestion value) => value.toJson()).toList();
+    result["otherSuggestions"] = otherSuggestions
+        .map((DartFixSuggestion value) => value.toJson())
+        .toList();
     result["hasErrors"] = hasErrors;
-    result["fixes"] =
-        fixes.map((SourceFileEdit value) => value.toJson()).toList();
+    result["edits"] =
+        edits.map((SourceFileEdit value) => value.toJson()).toList();
     return result;
   }
 
@@ -6429,12 +6533,12 @@
   @override
   bool operator ==(other) {
     if (other is EditDartfixResult) {
-      return listEqual(descriptionOfFixes, other.descriptionOfFixes,
-              (String a, String b) => a == b) &&
-          listEqual(otherRecommendations, other.otherRecommendations,
-              (String a, String b) => a == b) &&
+      return listEqual(suggestions, other.suggestions,
+              (DartFixSuggestion a, DartFixSuggestion b) => a == b) &&
+          listEqual(otherSuggestions, other.otherSuggestions,
+              (DartFixSuggestion a, DartFixSuggestion b) => a == b) &&
           hasErrors == other.hasErrors &&
-          listEqual(fixes, other.fixes,
+          listEqual(edits, other.edits,
               (SourceFileEdit a, SourceFileEdit b) => a == b);
     }
     return false;
@@ -6443,10 +6547,10 @@
   @override
   int get hashCode {
     int hash = 0;
-    hash = JenkinsSmiHash.combine(hash, descriptionOfFixes.hashCode);
-    hash = JenkinsSmiHash.combine(hash, otherRecommendations.hashCode);
+    hash = JenkinsSmiHash.combine(hash, suggestions.hashCode);
+    hash = JenkinsSmiHash.combine(hash, otherSuggestions.hashCode);
     hash = JenkinsSmiHash.combine(hash, hasErrors.hashCode);
-    hash = JenkinsSmiHash.combine(hash, fixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, edits.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
index 3a8e344..6673fb4 100644
--- a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
@@ -23,7 +23,7 @@
 import 'package:analyzer/src/lint/registry.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
-    show SourceChange, SourceEdit, SourceFileEdit;
+    show Location, SourceChange, SourceEdit, SourceFileEdit;
 import 'package:front_end/src/fasta/fasta_codes.dart';
 import 'package:front_end/src/scanner/token.dart';
 import 'package:source_span/src/span.dart';
@@ -34,14 +34,14 @@
   final fixFolders = <Folder>[];
   final fixFiles = <File>[];
 
-  List<String> descriptionOfFixes;
-  List<String> otherRecommendations;
+  List<DartFixSuggestion> suggestions;
+  List<DartFixSuggestion> otherSuggestions;
   SourceChange sourceChange;
 
   EditDartFix(this.server, this.request);
 
-  void addFix(String description, SourceChange change) {
-    descriptionOfFixes.add(description);
+  void addFix(String description, Location location, SourceChange change) {
+    suggestions.add(new DartFixSuggestion(description, location: location));
     for (SourceFileEdit fileEdit in change.edits) {
       for (SourceEdit sourceEdit in fileEdit.edits) {
         sourceChange.addEdit(fileEdit.file, fileEdit.fileStamp, sourceEdit);
@@ -49,8 +49,9 @@
     }
   }
 
-  void addRecommendation(String recommendation) {
-    otherRecommendations.add(recommendation);
+  void addRecommendation(String description, [Location location]) {
+    otherSuggestions
+        .add(new DartFixSuggestion(description, location: location));
   }
 
   Future<Response> compute() async {
@@ -125,8 +126,8 @@
     for (String rootPath in contextManager.includedPaths) {
       resources.add(resourceProvider.getResource(rootPath));
     }
-    descriptionOfFixes = <String>[];
-    otherRecommendations = <String>[];
+    suggestions = <DartFixSuggestion>[];
+    otherSuggestions = <DartFixSuggestion>[];
     sourceChange = new SourceChange('dartfix');
     bool hasErrors = false;
     while (resources.isNotEmpty) {
@@ -186,8 +187,8 @@
       await fix.applyRemainingFixes();
     }
 
-    return new EditDartfixResult(descriptionOfFixes, otherRecommendations,
-            hasErrors, sourceChange.edits)
+    return new EditDartfixResult(
+            suggestions, otherSuggestions, hasErrors, sourceChange.edits)
         .toResponse(request.id);
   }
 
@@ -204,7 +205,6 @@
       return false;
     }
 
-    final location = '${locationDescription(result, error.offset)}';
     final dartContext = new DartFixContextImpl(
         new FixContextImpl(
             server.resourceProvider, result.driver, error, result.errors),
@@ -212,12 +212,13 @@
         result.unit);
     final processor = new FixProcessor(dartContext);
     Fix fix = await processor.computeFix();
+    final location = locationFor(result, error.offset, error.length);
     if (fix != null) {
-      addFix('${fix.change.message} in $location', fix.change);
+      addFix(fix.change.message, location, fix.change);
     } else {
       // TODO(danrubel): Determine why the fix could not be applied
       // and report that in the description.
-      addRecommendation('Could not fix "${error.message}" in $location');
+      addRecommendation('Could not fix "${error.message}"', location);
     }
     return true;
   }
@@ -240,29 +241,11 @@
     return false;
   }
 
-  /// Return a human readable description of the specified offset and file.
-  String locationDescription(AnalysisResult result, int offset) {
-    // TODO(danrubel): Pass the location back to the client along with the
-    // message indicating what was or was not automatically fixed
-    // rather than interpreting and integrating the location into the message.
-    final description = new StringBuffer();
-    // Determine the relative path
-    for (Folder folder in fixFolders) {
-      if (folder.contains(result.path)) {
-        description.write(server.resourceProvider.pathContext
-            .relative(result.path, from: folder.path));
-        break;
-      }
-    }
-    if (description.isEmpty) {
-      description.write(result.path);
-    }
-    // Determine the line and column number
-    if (offset >= 0) {
-      final loc = result.unit.lineInfo.getLocation(offset);
-      description.write(':${loc.lineNumber}');
-    }
-    return description.toString();
+  Location locationFor(AnalysisResult result, int offset, int length) {
+    final locInfo = result.unit.lineInfo.getLocation(offset);
+    final location = new Location(
+        result.path, offset, length, locInfo.lineNumber, locInfo.columnNumber);
+    return location;
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart b/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
index 81758f9..52dda1f 100644
--- a/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
@@ -23,18 +23,18 @@
           new EditDartFixAssistContext(dartFix, source, result.unit, literal));
       List<Assist> assists =
           await processor.computeAssist(DartAssistKind.CONVERT_TO_INT_LITERAL);
-      final location = dartFix.locationDescription(result, literal.offset);
+      final location =
+          dartFix.locationFor(result, literal.offset, literal.length);
       if (assists.isNotEmpty) {
         for (Assist assist in assists) {
-          dartFix.addFix(
-              'Replace a double literal with an int literal in $location',
-              assist.change);
+          dartFix.addFix('Replace a double literal with an int literal',
+              location, assist.change);
         }
       } else {
         // TODO(danrubel): If assists is empty, then determine why
         // assist could not be performed and report that in the description.
-        dartFix.addRecommendation('Could not replace'
-            ' a double literal with an int literal in $location');
+        dartFix.addRecommendation(
+            'Could not replace a double literal with an int literal', location);
       }
     }
   }
diff --git a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
index 5e2aad1..52f924a 100644
--- a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
@@ -41,11 +41,11 @@
                 dartFix, elem.source, result.unit, declaration.name));
         List<Assist> assists = await processor
             .computeAssist(DartAssistKind.CONVERT_CLASS_TO_MIXIN);
-        final location = dartFix.locationDescription(result, elem.nameOffset);
+        final location =
+            dartFix.locationFor(result, elem.nameOffset, elem.nameLength);
         if (assists.isNotEmpty) {
           for (Assist assist in assists) {
-            dartFix.addFix(
-                'Convert ${elem.displayName} to a mixin in $location',
+            dartFix.addFix('Convert ${elem.displayName} to a mixin', location,
                 assist.change);
           }
         } else {
@@ -53,7 +53,8 @@
           // assist could not be performed and report that in the description.
           dartFix.addRecommendation(
               'Could not convert ${elem.displayName} to a mixin'
-              ' because the class contains a constructor in $location');
+              ' because the class contains a constructor',
+              location);
         }
       }
     }
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index 3976d6c..401723d 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1517,23 +1517,24 @@
    *
    * Returns
    *
-   * descriptionOfFixes: List<String>
+   * suggestions: List<DartFixSuggestion>
    *
-   *   A list of human readable changes made by applying the fixes.
+   *   A list of recommended changes that can be automatically made by applying
+   *   the 'edits' included in this response.
    *
-   * otherRecommendations: List<String>
+   * otherSuggestions: List<DartFixSuggestion>
    *
-   *   A list of human readable recommended changes that cannot be made
-   *   automatically.
+   *   A list of recommended changes that could not be automatically made.
    *
    * hasErrors: bool
    *
    *   True if the analyzed source contains errors that might impact the
-   *   correctness of the recommended fixes that can be automatically applied.
+   *   correctness of the recommended changes that can be automatically
+   *   applied.
    *
-   * fixes: List<SourceFileEdit>
+   * edits: List<SourceFileEdit>
    *
-   *   The suggested fixes.
+   *   A list of source edits to apply the recommended changes.
    */
   Future<EditDartfixResult> sendEditDartfix(List<String> included) async {
     var params = new EditDartfixParams(included).toJson();
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index db9505f..13ba921 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -298,6 +298,18 @@
         }));
 
 /**
+ * DartFixSuggestion
+ *
+ * {
+ *   "description": String
+ *   "location": optional Location
+ * }
+ */
+final Matcher isDartFixSuggestion = new LazyMatcher(() => new MatchesJsonObject(
+    "DartFixSuggestion", {"description": isString},
+    optionalFields: {"location": isLocation}));
+
+/**
  * Element
  *
  * {
@@ -2131,18 +2143,18 @@
  * edit.dartfix result
  *
  * {
- *   "descriptionOfFixes": List<String>
- *   "otherRecommendations": List<String>
+ *   "suggestions": List<DartFixSuggestion>
+ *   "otherSuggestions": List<DartFixSuggestion>
  *   "hasErrors": bool
- *   "fixes": List<SourceFileEdit>
+ *   "edits": List<SourceFileEdit>
  * }
  */
 final Matcher isEditDartfixResult =
     new LazyMatcher(() => new MatchesJsonObject("edit.dartfix result", {
-          "descriptionOfFixes": isListOf(isString),
-          "otherRecommendations": isListOf(isString),
+          "suggestions": isListOf(isDartFixSuggestion),
+          "otherSuggestions": isListOf(isDartFixSuggestion),
           "hasErrors": isBool,
-          "fixes": isListOf(isSourceFileEdit)
+          "edits": isListOf(isSourceFileEdit)
         }));
 
 /**
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/DartFixSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/DartFixSuggestion.java
new file mode 100644
index 0000000..7a106f8
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/DartFixSuggestion.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * A suggestion from an edit.dartfix request.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class DartFixSuggestion {
+
+  public static final DartFixSuggestion[] EMPTY_ARRAY = new DartFixSuggestion[0];
+
+  public static final List<DartFixSuggestion> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * A human readable description of the suggested change.
+   */
+  private final String description;
+
+  /**
+   * The location of the suggested change.
+   */
+  private final Location location;
+
+  /**
+   * Constructor for {@link DartFixSuggestion}.
+   */
+  public DartFixSuggestion(String description, Location location) {
+    this.description = description;
+    this.location = location;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof DartFixSuggestion) {
+      DartFixSuggestion other = (DartFixSuggestion) obj;
+      return
+        ObjectUtilities.equals(other.description, description) &&
+        ObjectUtilities.equals(other.location, location);
+    }
+    return false;
+  }
+
+  public static DartFixSuggestion fromJson(JsonObject jsonObject) {
+    String description = jsonObject.get("description").getAsString();
+    Location location = jsonObject.get("location") == null ? null : Location.fromJson(jsonObject.get("location").getAsJsonObject());
+    return new DartFixSuggestion(description, location);
+  }
+
+  public static List<DartFixSuggestion> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<DartFixSuggestion> list = new ArrayList<DartFixSuggestion>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * A human readable description of the suggested change.
+   */
+  public String getDescription() {
+    return description;
+  }
+
+  /**
+   * The location of the suggested change.
+   */
+  public Location getLocation() {
+    return location;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(description);
+    builder.append(location);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("description", description);
+    if (location != null) {
+      jsonObject.add("location", location.toJson());
+    }
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("description=");
+    builder.append(description + ", ");
+    builder.append("location=");
+    builder.append(location);
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RuntimeCompletionExpression.java b/pkg/analysis_server/tool/spec/generated/java/types/RuntimeCompletionExpression.java
index eb6b0f0..b2d6b70 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RuntimeCompletionExpression.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RuntimeCompletionExpression.java
@@ -24,9 +24,9 @@
 import org.apache.commons.lang3.StringUtils;
 
 /**
- * An expression for which we want to know its runtime type. In expressions like `a.b.c.where((e)
- * =&gt; e.^)` we want to know the runtime type of `a.b.c` to enforce it statically at the time
- * when we compute completion suggestions, and get better type for `e`.
+ * An expression for which we want to know its runtime type. In expressions like 'a.b.c.where((e)
+ * =&gt; e.^)' we want to know the runtime type of 'a.b.c' to enforce it statically at the time
+ * when we compute completion suggestions, and get better type for 'e'.
  *
  * @coverage dart.server.generated.types
  */
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 8eced61..2f66a93 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -1958,35 +1958,36 @@
       </field>
     </params>
     <result>
-      <field name="descriptionOfFixes">
+      <field name="suggestions">
         <list>
-          <ref>String</ref>
+          <ref>DartFixSuggestion</ref>
         </list>
         <p>
-          A list of human readable changes made by applying the fixes.
+          A list of recommended changes that can be automatically made
+          by applying the 'edits' included in this response.
         </p>
       </field>
-      <field name="otherRecommendations">
+      <field name="otherSuggestions">
         <list>
-          <ref>String</ref>
+          <ref>DartFixSuggestion</ref>
         </list>
         <p>
-          A list of human readable recommended changes that cannot be made automatically.
+          A list of recommended changes that could not be automatically made.
         </p>
       </field>
       <field name="hasErrors">
         <ref>bool</ref>
         <p>
           True if the analyzed source contains errors that might impact the correctness
-          of the recommended fixes that can be automatically applied.
+          of the recommended changes that can be automatically applied.
         </p>
       </field>
-      <field name="fixes">
+      <field name="edits">
         <list>
           <ref>SourceFileEdit</ref>
         </list>
         <p>
-          The suggested fixes.
+          A list of source edits to apply the recommended changes.
         </p>
       </field>
     </result>
@@ -3313,9 +3314,9 @@
   <type name="RuntimeCompletionExpression">
     <p>
       An expression for which we want to know its runtime type.
-      In expressions like `a.b.c.where((e) => e.^)` we want to know the
-      runtime type of `a.b.c` to enforce it statically at the time when we
-      compute completion suggestions, and get better type for `e`.
+      In expressions like 'a.b.c.where((e) => e.^)' we want to know the
+      runtime type of 'a.b.c' to enforce it statically at the time when we
+      compute completion suggestions, and get better type for 'e'.
     </p>
     <object>
       <field name="offset">
@@ -4232,6 +4233,25 @@
       request.
     </p>
   </type>
+  <type name="DartFixSuggestion" experimental="true">
+    <p>
+      A suggestion from an edit.dartfix request.
+    </p>
+    <object>
+      <field name="description">
+        <ref>String</ref>
+        <p>
+          A human readable description of the suggested change.
+        </p>
+      </field>
+      <field name="location" optional="true">
+        <ref>Location</ref>
+        <p>
+          The location of the suggested change.
+        </p>
+      </field>
+    </object>
+  </type>
   <type name="SearchResult">
     <p>
       A single result from a search request.
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 9d85d08..1280460 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -173,11 +173,10 @@
 const String EDIT_REQUEST_ORGANIZE_DIRECTIVES_FILE = 'file';
 const String EDIT_REQUEST_SORT_MEMBERS = 'edit.sortMembers';
 const String EDIT_REQUEST_SORT_MEMBERS_FILE = 'file';
-const String EDIT_RESPONSE_DARTFIX_DESCRIPTION_OF_FIXES = 'descriptionOfFixes';
-const String EDIT_RESPONSE_DARTFIX_FIXES = 'fixes';
+const String EDIT_RESPONSE_DARTFIX_EDITS = 'edits';
 const String EDIT_RESPONSE_DARTFIX_HAS_ERRORS = 'hasErrors';
-const String EDIT_RESPONSE_DARTFIX_OTHER_RECOMMENDATIONS =
-    'otherRecommendations';
+const String EDIT_RESPONSE_DARTFIX_OTHER_SUGGESTIONS = 'otherSuggestions';
+const String EDIT_RESPONSE_DARTFIX_SUGGESTIONS = 'suggestions';
 const String EDIT_RESPONSE_FORMAT_EDITS = 'edits';
 const String EDIT_RESPONSE_FORMAT_SELECTION_LENGTH = 'selectionLength';
 const String EDIT_RESPONSE_FORMAT_SELECTION_OFFSET = 'selectionOffset';
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index 2bbf169..9fabb4c 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -5932,6 +5932,105 @@
 }
 
 /**
+ * DartFixSuggestion
+ *
+ * {
+ *   "description": String
+ *   "location": optional Location
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class DartFixSuggestion implements HasToJson {
+  String _description;
+
+  Location _location;
+
+  /**
+   * A human readable description of the suggested change.
+   */
+  String get description => _description;
+
+  /**
+   * A human readable description of the suggested change.
+   */
+  void set description(String value) {
+    assert(value != null);
+    this._description = value;
+  }
+
+  /**
+   * The location of the suggested change.
+   */
+  Location get location => _location;
+
+  /**
+   * The location of the suggested change.
+   */
+  void set location(Location value) {
+    this._location = value;
+  }
+
+  DartFixSuggestion(String description, {Location location}) {
+    this.description = description;
+    this.location = location;
+  }
+
+  factory DartFixSuggestion.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String description;
+      if (json.containsKey("description")) {
+        description = jsonDecoder.decodeString(
+            jsonPath + ".description", json["description"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "description");
+      }
+      Location location;
+      if (json.containsKey("location")) {
+        location = new Location.fromJson(
+            jsonDecoder, jsonPath + ".location", json["location"]);
+      }
+      return new DartFixSuggestion(description, location: location);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "DartFixSuggestion", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["description"] = description;
+    if (location != null) {
+      result["location"] = location.toJson();
+    }
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is DartFixSuggestion) {
+      return description == other.description && location == other.location;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, description.hashCode);
+    hash = JenkinsSmiHash.combine(hash, location.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * diagnostic.getDiagnostics params
  *
  * Clients may not extend, implement or mix-in this class.
@@ -6268,60 +6367,60 @@
  * edit.dartfix result
  *
  * {
- *   "descriptionOfFixes": List<String>
- *   "otherRecommendations": List<String>
+ *   "suggestions": List<DartFixSuggestion>
+ *   "otherSuggestions": List<DartFixSuggestion>
  *   "hasErrors": bool
- *   "fixes": List<SourceFileEdit>
+ *   "edits": List<SourceFileEdit>
  * }
  *
  * Clients may not extend, implement or mix-in this class.
  */
 class EditDartfixResult implements ResponseResult {
-  List<String> _descriptionOfFixes;
+  List<DartFixSuggestion> _suggestions;
 
-  List<String> _otherRecommendations;
+  List<DartFixSuggestion> _otherSuggestions;
 
   bool _hasErrors;
 
-  List<SourceFileEdit> _fixes;
+  List<SourceFileEdit> _edits;
 
   /**
-   * A list of human readable changes made by applying the fixes.
+   * A list of recommended changes that can be automatically made by applying
+   * the 'edits' included in this response.
    */
-  List<String> get descriptionOfFixes => _descriptionOfFixes;
+  List<DartFixSuggestion> get suggestions => _suggestions;
 
   /**
-   * A list of human readable changes made by applying the fixes.
+   * A list of recommended changes that can be automatically made by applying
+   * the 'edits' included in this response.
    */
-  void set descriptionOfFixes(List<String> value) {
+  void set suggestions(List<DartFixSuggestion> value) {
     assert(value != null);
-    this._descriptionOfFixes = value;
+    this._suggestions = value;
   }
 
   /**
-   * A list of human readable recommended changes that cannot be made
-   * automatically.
+   * A list of recommended changes that could not be automatically made.
    */
-  List<String> get otherRecommendations => _otherRecommendations;
+  List<DartFixSuggestion> get otherSuggestions => _otherSuggestions;
 
   /**
-   * A list of human readable recommended changes that cannot be made
-   * automatically.
+   * A list of recommended changes that could not be automatically made.
    */
-  void set otherRecommendations(List<String> value) {
+  void set otherSuggestions(List<DartFixSuggestion> value) {
     assert(value != null);
-    this._otherRecommendations = value;
+    this._otherSuggestions = value;
   }
 
   /**
    * True if the analyzed source contains errors that might impact the
-   * correctness of the recommended fixes that can be automatically applied.
+   * correctness of the recommended changes that can be automatically applied.
    */
   bool get hasErrors => _hasErrors;
 
   /**
    * True if the analyzed source contains errors that might impact the
-   * correctness of the recommended fixes that can be automatically applied.
+   * correctness of the recommended changes that can be automatically applied.
    */
   void set hasErrors(bool value) {
     assert(value != null);
@@ -6329,27 +6428,27 @@
   }
 
   /**
-   * The suggested fixes.
+   * A list of source edits to apply the recommended changes.
    */
-  List<SourceFileEdit> get fixes => _fixes;
+  List<SourceFileEdit> get edits => _edits;
 
   /**
-   * The suggested fixes.
+   * A list of source edits to apply the recommended changes.
    */
-  void set fixes(List<SourceFileEdit> value) {
+  void set edits(List<SourceFileEdit> value) {
     assert(value != null);
-    this._fixes = value;
+    this._edits = value;
   }
 
   EditDartfixResult(
-      List<String> descriptionOfFixes,
-      List<String> otherRecommendations,
+      List<DartFixSuggestion> suggestions,
+      List<DartFixSuggestion> otherSuggestions,
       bool hasErrors,
-      List<SourceFileEdit> fixes) {
-    this.descriptionOfFixes = descriptionOfFixes;
-    this.otherRecommendations = otherRecommendations;
+      List<SourceFileEdit> edits) {
+    this.suggestions = suggestions;
+    this.otherSuggestions = otherSuggestions;
     this.hasErrors = hasErrors;
-    this.fixes = fixes;
+    this.edits = edits;
   }
 
   factory EditDartfixResult.fromJson(
@@ -6358,23 +6457,25 @@
       json = {};
     }
     if (json is Map) {
-      List<String> descriptionOfFixes;
-      if (json.containsKey("descriptionOfFixes")) {
-        descriptionOfFixes = jsonDecoder.decodeList(
-            jsonPath + ".descriptionOfFixes",
-            json["descriptionOfFixes"],
-            jsonDecoder.decodeString);
+      List<DartFixSuggestion> suggestions;
+      if (json.containsKey("suggestions")) {
+        suggestions = jsonDecoder.decodeList(
+            jsonPath + ".suggestions",
+            json["suggestions"],
+            (String jsonPath, Object json) =>
+                new DartFixSuggestion.fromJson(jsonDecoder, jsonPath, json));
       } else {
-        throw jsonDecoder.mismatch(jsonPath, "descriptionOfFixes");
+        throw jsonDecoder.mismatch(jsonPath, "suggestions");
       }
-      List<String> otherRecommendations;
-      if (json.containsKey("otherRecommendations")) {
-        otherRecommendations = jsonDecoder.decodeList(
-            jsonPath + ".otherRecommendations",
-            json["otherRecommendations"],
-            jsonDecoder.decodeString);
+      List<DartFixSuggestion> otherSuggestions;
+      if (json.containsKey("otherSuggestions")) {
+        otherSuggestions = jsonDecoder.decodeList(
+            jsonPath + ".otherSuggestions",
+            json["otherSuggestions"],
+            (String jsonPath, Object json) =>
+                new DartFixSuggestion.fromJson(jsonDecoder, jsonPath, json));
       } else {
-        throw jsonDecoder.mismatch(jsonPath, "otherRecommendations");
+        throw jsonDecoder.mismatch(jsonPath, "otherSuggestions");
       }
       bool hasErrors;
       if (json.containsKey("hasErrors")) {
@@ -6383,18 +6484,18 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "hasErrors");
       }
-      List<SourceFileEdit> fixes;
-      if (json.containsKey("fixes")) {
-        fixes = jsonDecoder.decodeList(
-            jsonPath + ".fixes",
-            json["fixes"],
+      List<SourceFileEdit> edits;
+      if (json.containsKey("edits")) {
+        edits = jsonDecoder.decodeList(
+            jsonPath + ".edits",
+            json["edits"],
             (String jsonPath, Object json) =>
                 new SourceFileEdit.fromJson(jsonDecoder, jsonPath, json));
       } else {
-        throw jsonDecoder.mismatch(jsonPath, "fixes");
+        throw jsonDecoder.mismatch(jsonPath, "edits");
       }
       return new EditDartfixResult(
-          descriptionOfFixes, otherRecommendations, hasErrors, fixes);
+          suggestions, otherSuggestions, hasErrors, edits);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix result", json);
     }
@@ -6410,11 +6511,14 @@
   @override
   Map<String, dynamic> toJson() {
     Map<String, dynamic> result = {};
-    result["descriptionOfFixes"] = descriptionOfFixes;
-    result["otherRecommendations"] = otherRecommendations;
+    result["suggestions"] =
+        suggestions.map((DartFixSuggestion value) => value.toJson()).toList();
+    result["otherSuggestions"] = otherSuggestions
+        .map((DartFixSuggestion value) => value.toJson())
+        .toList();
     result["hasErrors"] = hasErrors;
-    result["fixes"] =
-        fixes.map((SourceFileEdit value) => value.toJson()).toList();
+    result["edits"] =
+        edits.map((SourceFileEdit value) => value.toJson()).toList();
     return result;
   }
 
@@ -6429,12 +6533,12 @@
   @override
   bool operator ==(other) {
     if (other is EditDartfixResult) {
-      return listEqual(descriptionOfFixes, other.descriptionOfFixes,
-              (String a, String b) => a == b) &&
-          listEqual(otherRecommendations, other.otherRecommendations,
-              (String a, String b) => a == b) &&
+      return listEqual(suggestions, other.suggestions,
+              (DartFixSuggestion a, DartFixSuggestion b) => a == b) &&
+          listEqual(otherSuggestions, other.otherSuggestions,
+              (DartFixSuggestion a, DartFixSuggestion b) => a == b) &&
           hasErrors == other.hasErrors &&
-          listEqual(fixes, other.fixes,
+          listEqual(edits, other.edits,
               (SourceFileEdit a, SourceFileEdit b) => a == b);
     }
     return false;
@@ -6443,10 +6547,10 @@
   @override
   int get hashCode {
     int hash = 0;
-    hash = JenkinsSmiHash.combine(hash, descriptionOfFixes.hashCode);
-    hash = JenkinsSmiHash.combine(hash, otherRecommendations.hashCode);
+    hash = JenkinsSmiHash.combine(hash, suggestions.hashCode);
+    hash = JenkinsSmiHash.combine(hash, otherSuggestions.hashCode);
     hash = JenkinsSmiHash.combine(hash, hasErrors.hashCode);
-    hash = JenkinsSmiHash.combine(hash, fixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, edits.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
diff --git a/pkg/dartfix/lib/src/driver.dart b/pkg/dartfix/lib/src/driver.dart
index 80b6c11..80e7a05 100644
--- a/pkg/dartfix/lib/src/driver.dart
+++ b/pkg/dartfix/lib/src/driver.dart
@@ -122,25 +122,23 @@
   }
 
   Future applyFixes(EditDartfixResult result) async {
-    showDescriptions('Recommended changes', result.descriptionOfFixes);
-    showDescriptions(
-      'Recommended changes that cannot not be automatically applied',
-      result.otherRecommendations,
-    );
-    if (result.descriptionOfFixes.isEmpty) {
+    showDescriptions('Recommended changes', result.suggestions);
+    showDescriptions('Recommended changes that cannot be automatically applied',
+        result.otherSuggestions);
+    if (result.suggestions.isEmpty) {
       logger.stdout('');
-      logger.stdout(result.otherRecommendations.isNotEmpty
-          ? 'No recommended changes that cannot be automatically applied.'
+      logger.stdout(result.otherSuggestions.isNotEmpty
+          ? 'None of the recommended changes can be automatically applied.'
           : 'No recommended changes.');
       return;
     }
     logger.stdout('');
     logger.stdout(ansi.emphasized('Files to be changed:'));
-    for (SourceFileEdit fileEdit in result.fixes) {
+    for (SourceFileEdit fileEdit in result.edits) {
       logger.stdout('  ${_relativePath(fileEdit.file)}');
     }
     if (shouldApplyChanges(result)) {
-      for (SourceFileEdit fileEdit in result.fixes) {
+      for (SourceFileEdit fileEdit in result.edits) {
         final file = new File(fileEdit.file);
         String code = await file.readAsString();
         for (SourceEdit edit in fileEdit.edits) {
@@ -152,13 +150,16 @@
     }
   }
 
-  void showDescriptions(String title, List<String> descriptions) {
-    if (descriptions.isNotEmpty) {
+  void showDescriptions(String title, List<DartFixSuggestion> suggestions) {
+    if (suggestions.isNotEmpty) {
       logger.stdout('');
       logger.stdout(ansi.emphasized('$title:'));
-      List<String> sorted = new List.from(descriptions)..sort();
-      for (String line in sorted) {
-        logger.stdout('  $line');
+      List<DartFixSuggestion> sorted = new List.from(suggestions)
+        ..sort(compareSuggestions);
+      for (DartFixSuggestion suggestion in sorted) {
+        Location loc = suggestion.location;
+        logger.stdout('  ${_toSentenceFragment(suggestion.description)}'
+            '${loc == null ? "" : " • ${loc.startLine}:${loc.startColumn}"}');
       }
     }
   }
@@ -327,6 +328,14 @@
     }
   }
 
+  int compareSuggestions(DartFixSuggestion s1, DartFixSuggestion s2) {
+    int result = s1.description.compareTo(s2.description);
+    if (result != 0) {
+      return result;
+    }
+    return (s2.location?.offset ?? 0) - (s1.location?.offset ?? 0);
+  }
+
   bool shouldFilterError(AnalysisError error) {
     // Do not show TODOs or errors that will be automatically fixed.
 
diff --git a/pkg/dev_compiler/lib/src/analyzer/property_model.dart b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
index 1691857..b7dc784 100644
--- a/pkg/dev_compiler/lib/src/analyzer/property_model.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
@@ -58,22 +58,27 @@
   final _extensiblePrivateClasses = HashSet<ClassElement>();
 
   _LibraryVirtualFieldModel.build(LibraryElement library) {
-    var allTypes = library.units.expand((u) => u.types).toList();
+    var allClasses = Set<ClassElement>();
+    for (var libraryPart in library.units) {
+      allClasses.addAll(libraryPart.types);
+      allClasses.addAll(libraryPart.mixins);
+    }
 
     // The set of public types is our initial extensible type set.
     // From there, visit all immediate private types in this library, and so on
     // from those private types, marking them as extensible.
-    var typesToVisit =
-        Queue<ClassElement>.from(allTypes.where((t) => t.isPublic));
-    while (typesToVisit.isNotEmpty) {
-      var extensibleType = typesToVisit.removeFirst();
+    var classesToVisit =
+        Queue<ClassElement>.from(allClasses.where((t) => t.isPublic));
+    while (classesToVisit.isNotEmpty) {
+      var extensibleClass = classesToVisit.removeFirst();
 
       // For each supertype of a public type in this library,
       // if we encounter a private class, we mark it as being extended, and
       // add it to our work set if this is the first time we've visited it.
-      for (var type in getImmediateSuperclasses(extensibleType)) {
-        if (!type.isPublic && type.library == library) {
-          if (_extensiblePrivateClasses.add(type)) typesToVisit.add(type);
+      for (var superclass in getImmediateSuperclasses(extensibleClass)) {
+        if (!superclass.isPublic && superclass.library == library) {
+          if (_extensiblePrivateClasses.add(superclass))
+            classesToVisit.add(superclass);
         }
       }
     }
@@ -88,43 +93,44 @@
     }
 
     var allFields =
-        HashMap.fromIterables(allTypes, allTypes.map(getInstanceFieldMap));
+        HashMap.fromIterables(allClasses, allClasses.map(getInstanceFieldMap));
 
-    for (var type in allTypes) {
-      Set<ClassElement> supertypes = null;
+    for (var class_ in allClasses) {
+      Set<ClassElement> superclasses;
 
       // Visit accessors in the current class, and see if they override an
       // otherwise private field.
-      for (var accessor in type.accessors) {
+      for (var accessor in class_.accessors) {
         // For getter/setter pairs only process them once.
         if (accessor.correspondingGetter != null) continue;
         // Ignore abstract or static accessors.
         if (accessor.isAbstract || accessor.isStatic) continue;
         // Ignore public accessors in extensible classes.
         if (accessor.isPublic &&
-            (type.isPublic || _extensiblePrivateClasses.contains(type))) {
+            (class_.isPublic || _extensiblePrivateClasses.contains(class_))) {
           continue;
         }
 
-        if (supertypes == null) {
-          supertypes = Set();
-          void collectSupertypes(ClassElement cls) {
-            if (!supertypes.add(cls)) return;
+        if (superclasses == null) {
+          superclasses = Set();
+          void collectSuperclasses(ClassElement cls) {
+            if (!superclasses.add(cls)) return;
             var s = cls.supertype?.element;
-            if (s != null) collectSupertypes(s);
-            cls.mixins.forEach((m) => collectSupertypes(m.element));
+            if (s != null) collectSuperclasses(s);
+            cls.mixins.forEach((m) => collectSuperclasses(m.element));
           }
 
-          collectSupertypes(type);
-          supertypes.remove(type);
-          supertypes.removeWhere((c) => c.library != type.library);
+          collectSuperclasses(class_);
+          superclasses.remove(class_);
+          superclasses.removeWhere((c) => c.library != library);
         }
 
         // Look in all super classes to see if we're overriding a field in our
         // library, if so mark that field as overridden.
         var name = accessor.variable.name;
-        _overriddenPrivateFields.addAll(
-            supertypes.map((c) => allFields[c][name]).where((f) => f != null));
+        _overriddenPrivateFields.addAll(superclasses
+            .map((c) => allFields[c][name])
+            .where((f) => f != null));
       }
     }
   }
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index e004f89..0921e35 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -186,6 +186,7 @@
     library ??= visitLibraryElement(e.library);
     library.addClass(class_);
 
+    class_.isMixinDeclaration = e.isMixin;
     class_.typeParameters
         .addAll(e.typeParameters.map(visitTypeParameterElement));
 
@@ -504,6 +505,9 @@
       for (var t in u.types) {
         visitClassElement(t, library);
       }
+      for (var t in u.mixins) {
+        visitClassElement(t, library);
+      }
       for (var t in u.functionTypeAliases) {
         visitFunctionTypeAliasElement(t, library);
       }
diff --git a/pkg/dev_compiler/lib/src/kernel/property_model.dart b/pkg/dev_compiler/lib/src/kernel/property_model.dart
index 4242554..df0444b 100644
--- a/pkg/dev_compiler/lib/src/kernel/property_model.dart
+++ b/pkg/dev_compiler/lib/src/kernel/property_model.dart
@@ -92,7 +92,7 @@
         HashMap.fromIterables(allClasses, allClasses.map(getInstanceFieldMap));
 
     for (var class_ in allClasses) {
-      Set<Class> superclasses = null;
+      Set<Class> superclasses;
 
       // Visit accessors in the current class, and see if they override an
       // otherwise private field.
@@ -124,8 +124,7 @@
 
           collectSupertypes(class_);
           superclasses.remove(class_);
-          superclasses.removeWhere(
-              (s) => s.enclosingLibrary != class_.enclosingLibrary);
+          superclasses.removeWhere((s) => s.enclosingLibrary != library);
         }
 
         // Look in all super classes to see if we're overriding a field in our
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 50b44d9..0bcef13 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -112,15 +112,18 @@
 }
 
 intptr_t SourceReport::GetScriptIndex(const Script& script) {
+  ScriptTableEntry wrapper;
   const String& url = String::Handle(zone(), script.url());
-  ScriptTableEntry* pair = script_table_.LookupValue(&url);
+  wrapper.key = &url;
+  wrapper.script = &Script::Handle(zone(), script.raw());
+  ScriptTableEntry* pair = script_table_.LookupValue(&wrapper);
   if (pair != NULL) {
     return pair->index;
   }
   ScriptTableEntry* tmp = new ScriptTableEntry();
   tmp->key = &url;
   tmp->index = next_script_index_++;
-  tmp->script = &Script::Handle(zone(), script.raw());
+  tmp->script = wrapper.script;
   script_table_entries_.Add(tmp);
   script_table_.Insert(tmp);
   ASSERT(script_table_entries_.length() == next_script_index_);
@@ -139,7 +142,10 @@
     ASSERT(i == index);
     const String& url2 = String::Handle(zone(), script->url());
     ASSERT(url2.Equals(*url));
-    ScriptTableEntry* pair = script_table_.LookupValue(&url2);
+    ScriptTableEntry wrapper;
+    wrapper.key = &url2;
+    wrapper.script = &Script::Handle(zone(), script->raw());
+    ScriptTableEntry* pair = script_table_.LookupValue(&wrapper);
     ASSERT(i == pair->index);
   }
 }
diff --git a/runtime/vm/source_report.h b/runtime/vm/source_report.h
index 8db2418..5ab147f 100644
--- a/runtime/vm/source_report.h
+++ b/runtime/vm/source_report.h
@@ -94,17 +94,17 @@
   // Needed for DirectChainedHashMap.
   struct ScriptTableTrait {
     typedef ScriptTableEntry* Value;
-    typedef const String* Key;
+    typedef const ScriptTableEntry* Key;
     typedef ScriptTableEntry* Pair;
 
-    static Key KeyOf(Pair kv) { return kv->key; }
+    static Key KeyOf(Pair kv) { return kv; }
 
     static Value ValueOf(Pair kv) { return kv; }
 
-    static inline intptr_t Hashcode(Key key) { return key->Hash(); }
+    static inline intptr_t Hashcode(Key key) { return key->key->Hash(); }
 
     static inline bool IsKeyEqual(Pair kv, Key key) {
-      return kv->key->Equals(*key);
+      return kv->script->raw() == key->script->raw();
     }
   };
 
diff --git a/tests/language_2/mixin_declaration/mixin_declaration_syntax_test.dart b/tests/language_2/mixin_declaration/mixin_declaration_syntax_test.dart
index 9bfc38f..aba4640 100644
--- a/tests/language_2/mixin_declaration/mixin_declaration_syntax_test.dart
+++ b/tests/language_2/mixin_declaration/mixin_declaration_syntax_test.dart
@@ -402,4 +402,19 @@
   }
 
   Expect.equals(CeOwithM().toString(), CwithM().toString());
+
+  {
+    // Regression test for private fields.
+    var c = PrivateFieldClass();
+    Expect.equals(42, c._foo);
+  }
+}
+
+
+mixin PrivateFieldMixin {
+  int _foo = 40;
+}
+
+class PrivateFieldClass with PrivateFieldMixin {
+  int get _foo => super._foo + 2;
 }
diff --git a/tools/VERSION b/tools/VERSION
index 804d4a7..4f5aa1c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 1
 PATCH 0
 PRERELEASE 9
-PRERELEASE_PATCH 0
+PRERELEASE_PATCH 1
diff --git a/tools/gn.py b/tools/gn.py
index 50740ef..9b34862 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -248,7 +248,7 @@
 
   # Setup the user-defined sysroot.
   if UseSysroot(args, gn_args):
-    gn_args['dart_use_wheezy_sysroot'] = True
+    gn_args['dart_use_debian_sysroot'] = True
   else:
     sysroot = TargetSysroot(args)
     if sysroot:
diff --git a/tools/set_ia32_sysroot.sh b/tools/set_ia32_sysroot.sh
index c7156ce..1944330 100755
--- a/tools/set_ia32_sysroot.sh
+++ b/tools/set_ia32_sysroot.sh
@@ -4,16 +4,16 @@
 # 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.
 
-# Sets the compiler environment variables to use a downloaded wheezy sysroot
+# Sets the compiler environment variables to use a downloaded Debian sysroot
 # when building Dart with architecture ia32.
-# Run this in the same working directory that you have run 
+# Run this in the same working directory that you have run
 # sdk/tools/download_chromium_sysroot.sh in.
 # Must be sourced, not run in a subshell, to modify the environment.
 # Run with the command ". sdk/tools/set_ia32_sysroot.sh"
 # Only tested and used on Ubuntu trusty linux. Used to build dart with
 # no requirement for glibc greater than version 2.14.
 
-export CXXFLAGS="--sysroot=$PWD/build/linux/debian_wheezy_i386-sysroot -I=/usr/include/c++/4.6 -I=/usr/include/c++/4.6/i486-linux-gnu"
+export CXXFLAGS="--sysroot=$PWD/build/linux/debian_jessie_i386-sysroot -I=/usr/include/c++/4.8 -I=/usr/include/c++/4.8/i486-linux-gnu"
 
-export LDFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_i386-sysroot
-export CFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_i386-sysroot
+export LDFLAGS=--sysroot=$PWD/build/linux/debian_jessie_i386-sysroot
+export CFLAGS=--sysroot=$PWD/build/linux/debian_jessie_i386-sysroot
diff --git a/tools/set_x64_sysroot.sh b/tools/set_x64_sysroot.sh
index bc28961..9c199ff 100755
--- a/tools/set_x64_sysroot.sh
+++ b/tools/set_x64_sysroot.sh
@@ -4,16 +4,16 @@
 # 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.
 
-# Sets the compiler environment variables to use a downloaded wheezy sysroot
+# Sets the compiler environment variables to use a downloaded Debian sysroot
 # when building Dart with architecture x64.
-# Run this in the same working directory that you have run 
+# Run this in the same working directory that you have run
 # sdk/tools/download_chromium_sysroot.sh in.
 # Must be sourced, not run in a subshell, to modify the environment.
 # Run with the command ". sdk/tools/set_x64_sysroot.sh"
 # Only tested and used on Ubuntu trusty linux. Used to build dart with
 # no requirement for glibc greater than version 2.14.
 
-export CXXFLAGS="--sysroot=$PWD/build/linux/debian_wheezy_amd64-sysroot -I=/usr/include/c++/4.6 -I=/usr/include/c++/4.6/x86_64-linux-gnu"
+export CXXFLAGS="--sysroot=$PWD/build/linux/debian_jessie_amd64-sysroot -I=/usr/include/c++/4.8 -I=/usr/include/c++/4.8/x86_64-linux-gnu"
 
-export LDFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_amd64-sysroot
-export CFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_amd64-sysroot
+export LDFLAGS=--sysroot=$PWD/build/linux/debian_jessie_amd64-sysroot
+export CFLAGS=--sysroot=$PWD/build/linux/debian_jessie_amd64-sysroot