| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library package.map.provider; | 5 library package.map.provider; |
| 6 | 6 |
| 7 import 'dart:convert'; | 7 import 'dart:convert'; |
| 8 import 'dart:io' as io; | 8 import 'dart:io' as io; |
| 9 | 9 |
| 10 import 'package:analysis_server/src/analysis_server.dart'; | 10 import 'package:analysis_server/src/analysis_server.dart'; |
| 11 import 'package:analysis_server/src/resource.dart'; | 11 import 'package:analysis_server/src/resource.dart'; |
| 12 import 'package:analyzer/src/generated/engine.dart'; | 12 import 'package:analyzer/src/generated/engine.dart'; |
| 13 | 13 |
| 14 /** | 14 /** |
| 15 * A PackageMapProvider is an entity capable of determining the mapping from | 15 * A PackageMapProvider is an entity capable of determining the mapping from |
| 16 * package name to source directory for a given folder. | 16 * package name to source directory for a given folder. |
| 17 */ | 17 */ |
| 18 abstract class PackageMapProvider { | 18 abstract class PackageMapProvider { |
| 19 /** | 19 /** |
| 20 * Compute a package map for the given folder, if possible. | 20 * Compute a package map for the given folder, if possible. |
| 21 * | 21 * |
| 22 * If a package map can't be computed, return null. | 22 * If a package map can't be computed, return null. |
| 23 */ | 23 */ |
| 24 Map<String, List<Folder>> computePackageMap(Folder folder); | 24 PackageMapInfo computePackageMap(Folder folder); |
| 25 } | 25 } |
| 26 | 26 |
| 27 /** | 27 /** |
| 28 * Data structure output by PackageMapProvider. This contains both the package |
| 29 * map and dependency information. |
| 30 */ |
| 31 class PackageMapInfo { |
| 32 /** |
| 33 * The package map itself. This is a map from package name to a list of |
| 34 * the folders containing source code for the package. |
| 35 */ |
| 36 Map<String, List<Folder>> packageMap; |
| 37 |
| 38 /** |
| 39 * Dependency information. This is a set of the paths which were consulted |
| 40 * in order to generate the package map. If any of these files is |
| 41 * modified, the package map will need to be regenerated. |
| 42 */ |
| 43 Set<String> dependencies; |
| 44 |
| 45 PackageMapInfo(this.packageMap, this.dependencies); |
| 46 } |
| 47 |
| 48 /** |
| 28 * Implementation of PackageMapProvider that operates by executing pub. | 49 * Implementation of PackageMapProvider that operates by executing pub. |
| 29 */ | 50 */ |
| 30 class PubPackageMapProvider implements PackageMapProvider { | 51 class PubPackageMapProvider implements PackageMapProvider { |
| 31 static const String PUB_LIST_COMMAND = 'list-package-dirs'; | 52 static const String PUB_LIST_COMMAND = 'list-package-dirs'; |
| 32 | 53 |
| 33 /** | 54 /** |
| 34 * [ResourceProvider] that is used to create the [Folder]s that populate the | 55 * [ResourceProvider] that is used to create the [Folder]s that populate the |
| 35 * package map. | 56 * package map. |
| 36 */ | 57 */ |
| 37 final ResourceProvider resourceProvider; | 58 final ResourceProvider resourceProvider; |
| 38 | 59 |
| 39 PubPackageMapProvider(this.resourceProvider); | 60 PubPackageMapProvider(this.resourceProvider); |
| 40 | 61 |
| 41 @override | 62 @override |
| 42 Map<String, List<Folder>> computePackageMap(Folder folder) { | 63 PackageMapInfo computePackageMap(Folder folder) { |
| 43 // TODO(paulberry) make this asynchronous so that we can (a) do other | 64 // TODO(paulberry) make this asynchronous so that we can (a) do other |
| 44 // analysis while it's in progress, and (b) time out if it takes too long | 65 // analysis while it's in progress, and (b) time out if it takes too long |
| 45 // to respond. | 66 // to respond. |
| 46 String executable = SHARED_SDK.pubExecutable.getAbsolutePath(); | 67 String executable = SHARED_SDK.pubExecutable.getAbsolutePath(); |
| 47 io.ProcessResult result; | 68 io.ProcessResult result; |
| 48 try { | 69 try { |
| 49 result = io.Process.runSync( | 70 result = io.Process.runSync( |
| 50 executable, [PUB_LIST_COMMAND], workingDirectory: folder.path); | 71 executable, [PUB_LIST_COMMAND], workingDirectory: folder.path); |
| 51 } on io.ProcessException catch (exception, stackTrace) { | 72 } on io.ProcessException catch (exception, stackTrace) { |
| 52 AnalysisEngine.instance.logger.logInformation( | 73 AnalysisEngine.instance.logger.logInformation( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 63 AnalysisEngine.instance.logger.logError( | 84 AnalysisEngine.instance.logger.logError( |
| 64 "Malformed output from pub $PUB_LIST_COMMAND\n${exception}\n${stackTra
ce}"); | 85 "Malformed output from pub $PUB_LIST_COMMAND\n${exception}\n${stackTra
ce}"); |
| 65 } | 86 } |
| 66 | 87 |
| 67 return null; | 88 return null; |
| 68 } | 89 } |
| 69 | 90 |
| 70 /** | 91 /** |
| 71 * Decode the JSON output from pub into a package map. | 92 * Decode the JSON output from pub into a package map. |
| 72 */ | 93 */ |
| 73 Map<String, List<Folder>> parsePackageMap(String jsonText) { | 94 PackageMapInfo parsePackageMap(String jsonText) { |
| 74 // The output of pub looks like this: | 95 // The output of pub looks like this: |
| 75 // { | 96 // { |
| 76 // "packages": { | 97 // "packages": { |
| 77 // "foo": "path/to/foo", | 98 // "foo": "path/to/foo", |
| 78 // "bar": ["path/to/bar1", "path/to/bar2"], | 99 // "bar": ["path/to/bar1", "path/to/bar2"], |
| 79 // "myapp": "path/to/myapp", // self link is included | 100 // "myapp": "path/to/myapp", // self link is included |
| 80 // }, | 101 // }, |
| 81 // "input_files": [ | 102 // "input_files": [ |
| 82 // "path/to/myapp/pubspec.lock" | 103 // "path/to/myapp/pubspec.lock" |
| 83 // ] | 104 // ] |
| (...skipping 15 matching lines...) Expand all Loading... |
| 99 packageMap[packageName] = folders; | 120 packageMap[packageName] = folders; |
| 100 } | 121 } |
| 101 } | 122 } |
| 102 packages.forEach((key, value) { | 123 packages.forEach((key, value) { |
| 103 if (value is String) { | 124 if (value is String) { |
| 104 processPaths(key, [value]); | 125 processPaths(key, [value]); |
| 105 } else if (value is List) { | 126 } else if (value is List) { |
| 106 processPaths(key, value); | 127 processPaths(key, value); |
| 107 } | 128 } |
| 108 }); | 129 }); |
| 109 return packageMap; | 130 Set<String> dependencies = new Set<String>(); |
| 131 List inputFiles = obj['input_files']; |
| 132 if (inputFiles != null) { |
| 133 for (var path in inputFiles) { |
| 134 if (path is String) { |
| 135 dependencies.add(path); |
| 136 } |
| 137 } |
| 138 } |
| 139 return new PackageMapInfo(packageMap, dependencies); |
| 110 } | 140 } |
| 111 } | 141 } |
| OLD | NEW |