Index: pkg/analyzer/lib/source/pub_package_map_provider.dart |
diff --git a/pkg/analyzer/lib/source/pub_package_map_provider.dart b/pkg/analyzer/lib/source/pub_package_map_provider.dart |
index a45fc9065dbbb92bef5c220bf511f8a3bf29642e..b9b19c677589b2885872302fd0f70f213bbe4e18 100644 |
--- a/pkg/analyzer/lib/source/pub_package_map_provider.dart |
+++ b/pkg/analyzer/lib/source/pub_package_map_provider.dart |
@@ -15,6 +15,11 @@ import 'package:analyzer/src/generated/sdk_io.dart'; |
import 'package:path/path.dart'; |
/** |
+ * The function used to run pub list. |
+ */ |
+typedef io.ProcessResult RunPubList(Folder folder); |
+ |
+/** |
* Implementation of PackageMapProvider that operates by executing pub. |
*/ |
class PubPackageMapProvider implements PackageMapProvider { |
@@ -37,20 +42,29 @@ class PubPackageMapProvider implements PackageMapProvider { |
*/ |
final DirectoryBasedDartSdk sdk; |
- PubPackageMapProvider(this.resourceProvider, this.sdk); |
+ /** |
+ * The function used to run pub list. |
+ */ |
+ RunPubList _runPubList; |
+ |
+ /** |
+ * Construct a new instance. |
+ * A [RunPubList] implementation may be injected for testing |
+ */ |
+ PubPackageMapProvider(this.resourceProvider, this.sdk, [this._runPubList]) { |
+ if (_runPubList == null) { |
+ _runPubList = _runPubListDefault; |
+ } |
+ } |
@override |
PackageMapInfo computePackageMap(Folder folder) { |
// TODO(paulberry) make this asynchronous so that we can (a) do other |
// analysis while it's in progress, and (b) time out if it takes too long |
// to respond. |
- String executable = sdk.pubExecutable.getAbsolutePath(); |
io.ProcessResult result; |
try { |
- result = io.Process.runSync( |
- executable, |
- [PUB_LIST_COMMAND], |
- workingDirectory: folder.path); |
+ result = _runPubList(folder); |
} on io.ProcessException catch (exception, stackTrace) { |
AnalysisEngine.instance.logger.logInformation( |
"Error running pub $PUB_LIST_COMMAND\n$exception\n$stackTrace"); |
@@ -60,23 +74,37 @@ class PubPackageMapProvider implements PackageMapProvider { |
result != null ? 'exit code ${result.exitCode}' : 'null'; |
AnalysisEngine.instance.logger.logInformation( |
"pub $PUB_LIST_COMMAND failed: $exitCode"); |
- return _error(folder); |
+ return computePackageMapError(folder); |
} |
try { |
- return parsePackageMap(result.stdout, folder); |
+ PackageMapInfo packageMap = |
+ parsePackageMap(JSON.decode(result.stdout), folder); |
+ return packageMap; |
} catch (exception, stackTrace) { |
AnalysisEngine.instance.logger.logError( |
"Malformed output from pub $PUB_LIST_COMMAND\n$exception\n$stackTrace"); |
} |
- return _error(folder); |
+ return computePackageMapError(folder); |
+ } |
+ |
+ /** |
+ * Create a PackageMapInfo object representing an error condition. |
+ */ |
+ PackageMapInfo computePackageMapError(Folder folder) { |
+ // Even if an error occurs, we still need to know the dependencies, so that |
+ // we'll know when to try running "pub list-package-dirs" again. |
+ // Unfortunately, "pub list-package-dirs" doesn't tell us dependencies when |
+ // an error occurs, so just assume there is one dependency, "pubspec.lock". |
+ List<String> dependencies = <String>[join(folder.path, PUBSPEC_LOCK_NAME)]; |
+ return new PackageMapInfo(null, dependencies.toSet()); |
} |
/** |
* Decode the JSON output from pub into a package map. Paths in the |
* output are considered relative to [folder]. |
*/ |
- PackageMapInfo parsePackageMap(String jsonText, Folder folder) { |
+ PackageMapInfo parsePackageMap(Map obj, Folder folder) { |
// The output of pub looks like this: |
// { |
// "packages": { |
@@ -89,7 +117,6 @@ class PubPackageMapProvider implements PackageMapProvider { |
// ] |
// } |
Map<String, List<Folder>> packageMap = new HashMap<String, List<Folder>>(); |
- Map obj = JSON.decode(jsonText); |
Map packages = obj['packages']; |
processPaths(String packageName, List paths) { |
List<Folder> folders = <Folder>[]; |
@@ -125,14 +152,12 @@ class PubPackageMapProvider implements PackageMapProvider { |
} |
/** |
- * Create a PackageMapInfo object representing an error condition. |
+ * Run pub list to determine the packages and input files. |
*/ |
- PackageMapInfo _error(Folder folder) { |
- // Even if an error occurs, we still need to know the dependencies, so that |
- // we'll know when to try running "pub list-package-dirs" again. |
- // Unfortunately, "pub list-package-dirs" doesn't tell us dependencies when |
- // an error occurs, so just assume there is one dependency, "pubspec.lock". |
- List<String> dependencies = <String>[join(folder.path, PUBSPEC_LOCK_NAME)]; |
- return new PackageMapInfo(null, dependencies.toSet()); |
+ io.ProcessResult _runPubListDefault(Folder folder) { |
+ return io.Process.runSync( |
+ sdk.pubExecutable.getAbsolutePath(), |
+ [PUB_LIST_COMMAND], |
+ workingDirectory: folder.path); |
} |
} |