Change to only look for package_config.json if asked for .packages by name. (#78)

Some clean-up.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1cd45d0..0b5e156 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 1.9.2
+
+- Updated to support new rules for picking `package_config.json` over
+  a specified `.packages`.
+
 ## 1.9.1
 
 - Remove accidental transitive import of `dart:io` from entrypoints that are
diff --git a/lib/package_config.dart b/lib/package_config.dart
index bca865d..1113ac8 100644
--- a/lib/package_config.dart
+++ b/lib/package_config.dart
@@ -24,9 +24,10 @@
 /// It is considered a `package_config.json` file if its first character
 /// is a `{`.
 ///
-/// If the file is a `.packages` file and [preferNewest] is true, the default,
-/// also checks if there is a `.dart_tool/package_config.json` file next to the original file,
-/// and if so, loads that instead.
+/// If the file is a `.packages` file (the file name is `.packages`)
+/// and [preferNewest] is true, the default, also checks if there is
+/// a `.dart_tool/package_config.json` file next
+/// to the original file, and if so, loads that instead.
 /// If [preferNewest] is set to false, a directly specified `.packages` file
 /// is loaded even if there is an available `package_config.json` file.
 /// The caller can determine this from the [PackageConfig.version]
@@ -50,6 +51,7 @@
 /// non-whitespace character is a `{`.
 ///
 /// If [preferNewest] is true, the default, and the file is a `.packages` file,
+/// as determined by its file name being `.packages`,
 /// first checks if there is a `.dart_tool/package_config.json` file
 /// next to the original file, and if so, loads that instead.
 /// The [file] *must not* be a `package:` URI.
diff --git a/lib/src/package_config_io.dart b/lib/src/package_config_io.dart
index 954be6b..31bc1cc 100644
--- a/lib/src/package_config_io.dart
+++ b/lib/src/package_config_io.dart
@@ -30,6 +30,13 @@
 /// The file must exist and be a normal file.
 Future<PackageConfig> readAnyConfigFile(
     File file, bool preferNewest, void onError(Object error)) async {
+  if (preferNewest && fileName(file.path) == ".packages") {
+    var alternateFile =
+        File(pathJoin(dirName(file.path), ".dart_tool", "package_config.json"));
+    if (alternateFile.existsSync()) {
+      return await readPackageConfigJsonFile(alternateFile, onError);
+    }
+  }
   Uint8List bytes;
   try {
     bytes = await file.readAsBytes();
@@ -37,28 +44,7 @@
     onError(e);
     return const SimplePackageConfig.empty();
   }
-  var firstChar = firstNonWhitespaceChar(bytes);
-  if (firstChar != $lbrace) {
-    // Definitely not a JSON object, probably a .packages.
-    if (preferNewest) {
-      var alternateFile = File(
-          pathJoin(dirName(file.path), ".dart_tool", "package_config.json"));
-      if (alternateFile.existsSync()) {
-        Uint8List /*?*/ bytes;
-        try {
-          bytes = await alternateFile.readAsBytes();
-        } catch (e) {
-          onError(e);
-          return const SimplePackageConfig.empty();
-        }
-        if (bytes != null) {
-          return parsePackageConfigBytes(bytes, alternateFile.uri, onError);
-        }
-      }
-    }
-    return packages_file.parse(bytes, file.uri, onError);
-  }
-  return parsePackageConfigBytes(bytes, file.uri, onError);
+  return parseAnyConfigFile(bytes, file.uri, onError);
 }
 
 /// Like [readAnyConfigFile] but uses a URI and an optional loader.
@@ -73,11 +59,24 @@
   }
   if (loader == null) {
     if (file.isScheme("file")) {
-      return readAnyConfigFile(File.fromUri(file), preferNewest, onError);
+      return await readAnyConfigFile(File.fromUri(file), preferNewest, onError);
     }
     loader = defaultLoader;
   }
-  Uint8List bytes;
+  if (preferNewest && file.pathSegments.last == ".packages") {
+    var alternateFile = file.resolve(".dart_tool/package_config.json");
+    Uint8List /*?*/ bytes;
+    try {
+      bytes = await loader(alternateFile);
+    } catch (e) {
+      onError(e);
+      return const SimplePackageConfig.empty();
+    }
+    if (bytes != null) {
+      return parsePackageConfigBytes(bytes, alternateFile, onError);
+    }
+  }
+  Uint8List /*?*/ bytes;
   try {
     bytes = await loader(file);
   } catch (e) {
@@ -89,23 +88,18 @@
         file.toString(), "file", "File cannot be read"));
     return const SimplePackageConfig.empty();
   }
+  return parseAnyConfigFile(bytes, file, onError);
+}
+
+/// Parses a `.packages` or `package_config.json` file's contents.
+///
+/// Assumes it's a JSON file if the first non-whitespace character
+/// is `{`, otherwise assumes it's a `.packages` file.
+PackageConfig parseAnyConfigFile(
+    Uint8List bytes, Uri file, void onError(Object error)) {
   var firstChar = firstNonWhitespaceChar(bytes);
   if (firstChar != $lbrace) {
     // Definitely not a JSON object, probably a .packages.
-    if (preferNewest) {
-      // Check if there is a package_config.json file.
-      var alternateFile = file.resolveUri(packageConfigJsonPath);
-      Uint8List alternateBytes;
-      try {
-        alternateBytes = await loader(alternateFile);
-      } catch (e) {
-        onError(e);
-        return const SimplePackageConfig.empty();
-      }
-      if (alternateBytes != null) {
-        return parsePackageConfigBytes(alternateBytes, alternateFile, onError);
-      }
-    }
     return packages_file.parse(bytes, file, onError);
   }
   return parsePackageConfigBytes(bytes, file, onError);
diff --git a/lib/src/package_config_json.dart b/lib/src/package_config_json.dart
index b9b3416..27abf50 100644
--- a/lib/src/package_config_json.dart
+++ b/lib/src/package_config_json.dart
@@ -39,7 +39,7 @@
   try {
     jsonObject = _jsonUtf8Decoder.convert(bytes);
   } on FormatException catch (e) {
-    onError(PackageConfigFormatException(e.message, e.source, e.offset));
+    onError(PackageConfigFormatException.from(e));
     return const SimplePackageConfig.empty();
   }
   return parsePackageConfigJson(jsonObject, file, onError);
@@ -51,7 +51,7 @@
   try {
     jsonObject = jsonDecode(source);
   } on FormatException catch (e) {
-    onError(PackageConfigFormatException(e.message, e.source, e.offset));
+    onError(PackageConfigFormatException.from(e));
     return const SimplePackageConfig.empty();
   }
   return parsePackageConfigJson(jsonObject, file, onError);
@@ -271,7 +271,6 @@
     }
   }
   packages_file.write(output, config, baseUri: baseUri, comment: comment);
-  return;
 }
 
 /// If "extraData" is a JSON map, then return it, otherwise return null.
@@ -304,12 +303,10 @@
   if (object == null || true == object || false == object) return true;
   if (object is num || object is String) return true;
   if (object is List<dynamic>) {
-    for (var element in object) if (!_validateJson(element)) return false;
-    return true;
+    return object.every(_validateJson);
   }
   if (object is Map<String, dynamic>) {
-    for (var value in object.values) if (!_validateJson(value)) return false;
-    return true;
+    return object.values.every(_validateJson);
   }
   return false;
 }
diff --git a/lib/src/util_io.dart b/lib/src/util_io.dart
index 7f21a8d..2aa8c94 100644
--- a/lib/src/util_io.dart
+++ b/lib/src/util_io.dart
@@ -13,7 +13,7 @@
   if (uri.isScheme("file")) {
     var file = File.fromUri(uri);
     try {
-      return file.readAsBytes();
+      return await file.readAsBytes();
     } catch (_) {
       return null;
     }
diff --git a/pubspec.yaml b/pubspec.yaml
index 853c051..3f5ec27 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: package_config
-version: 1.9.1
+version: 1.9.2
 description: Support for working with Package Configuration files.
 homepage: https://github.com/dart-lang/package_config
 
diff --git a/test/discovery_test.dart b/test/discovery_test.dart
index 1a9a61c..5cbc992 100644
--- a/test/discovery_test.dart
+++ b/test/discovery_test.dart
@@ -301,13 +301,13 @@
     });
 
     // Find package_config.json in subdir even if initial file syntax error.
-    fileTest("specified file syntax error", {
-      "anyname": "syntax error",
+    fileTest("specified file syntax onError", {
+      ".packages": "syntax error",
       ".dart_tool": {
         "package_config.json": packageConfigFile,
       },
     }, (Directory directory) async {
-      var file = dirFile(directory, "anyname");
+      var file = dirFile(directory, ".packages");
       var config = await loadPackageConfig(file);
       expect(config.version, 2);
       validatePackagesFile(config, directory);
diff --git a/test/discovery_uri_test.dart b/test/discovery_uri_test.dart
index 52fca3f..23c02d7 100644
--- a/test/discovery_uri_test.dart
+++ b/test/discovery_uri_test.dart
@@ -60,7 +60,7 @@
       ".dart_tool": {
         "package_config.json": packageConfigFile,
       }
-    }, (Uri directory, loader) async {
+    }, (directory, loader) async {
       var config = await findPackageConfigUri(directory, loader: loader);
       expect(config.version, 2); // Found package_config.json file.
       validatePackagesFile(config, directory);
@@ -71,7 +71,7 @@
       ".packages": packagesFile,
       "script.dart": "main(){}",
       "packages": {"shouldNotBeFound": {}}
-    }, (Uri directory, loader) async {
+    }, (directory, loader) async {
       var config = await findPackageConfigUri(directory, loader: loader);
       expect(config.version, 1); // Found .packages file.
       validatePackagesFile(config, directory);
@@ -86,7 +86,7 @@
       "subdir": {
         "script.dart": "main(){}",
       }
-    }, (Uri directory, loader) async {
+    }, (directory, loader) async {
       var config = await findPackageConfigUri(directory.resolve("subdir/"),
           loader: loader);
       expect(config.version, 2);
@@ -97,7 +97,7 @@
     loaderTest(".packages recursive", {
       ".packages": packagesFile,
       "subdir": {"script.dart": "main(){}"}
-    }, (Uri directory, loader) async {
+    }, (directory, loader) async {
       var config;
       config = await findPackageConfigUri(directory.resolve("subdir/"),
           loader: loader);
@@ -240,9 +240,9 @@
           throwsFormatException);
     });
 
-    loaderTest("specified file syntax error", {
+    loaderTest("specified file syntax onError", {
       "anyname": "syntax error",
-    }, (Uri directory, loader) async {
+    }, (directory, loader) async {
       var file = directory.resolve("anyname");
       var hadError = false;
       await loadPackageConfigUri(file,
@@ -254,23 +254,22 @@
       expect(hadError, true);
     });
 
-    // Find package_config.json in subdir even if initial file syntax error.
-    loaderTest("specified file syntax error", {
+    // Don't look for package_config.json if original file not named .packages.
+    loaderTest("specified file syntax error with alternative", {
       "anyname": "syntax error",
       ".dart_tool": {
         "package_config.json": packageConfigFile,
       },
-    }, (Uri directory, loader) async {
+    }, (directory, loader) async {
       var file = directory.resolve("anyname");
-      var config = await loadPackageConfigUri(file, loader: loader);
-      expect(config.version, 2);
-      validatePackagesFile(config, directory);
+      expect(() => loadPackageConfigUri(file, loader: loader),
+          throwsFormatException);
     });
 
     // A file starting with `{` is a package_config.json file.
     loaderTest("file syntax error with {", {
       ".packages": "{syntax error",
-    }, (Uri directory, loader) async {
+    }, (directory, loader) async {
       var file = directory.resolve(".packages");
       var hadError = false;
       await loadPackageConfigUri(file,