| 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);
|
| }
|
| }
|
|
|