Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: pkg/analyzer/lib/source/pub_package_map_provider.dart

Issue 941883002: cache pub list results (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: merge Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 source.pub_package_map_provider; 5 library source.pub_package_map_provider;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:convert'; 8 import 'dart:convert';
9 import 'dart:io' as io; 9 import 'dart:io' as io;
10 10
11 import 'package:analyzer/file_system/file_system.dart'; 11 import 'package:analyzer/file_system/file_system.dart';
12 import 'package:analyzer/source/package_map_provider.dart'; 12 import 'package:analyzer/source/package_map_provider.dart';
13 import 'package:analyzer/src/generated/engine.dart'; 13 import 'package:analyzer/src/generated/engine.dart';
14 import 'package:analyzer/src/generated/sdk_io.dart'; 14 import 'package:analyzer/src/generated/sdk_io.dart';
15 import 'package:path/path.dart'; 15 import 'package:path/path.dart';
16 16
17 /** 17 /**
18 * The function used to run pub list.
19 */
20 typedef io.ProcessResult RunPubList(Folder folder);
21
22 /**
18 * Implementation of PackageMapProvider that operates by executing pub. 23 * Implementation of PackageMapProvider that operates by executing pub.
19 */ 24 */
20 class PubPackageMapProvider implements PackageMapProvider { 25 class PubPackageMapProvider implements PackageMapProvider {
21 static const String PUB_LIST_COMMAND = 'list-package-dirs'; 26 static const String PUB_LIST_COMMAND = 'list-package-dirs';
22 27
23 /** 28 /**
24 * The name of the 'pubspec.lock' file, which we assume is the dependency 29 * The name of the 'pubspec.lock' file, which we assume is the dependency
25 * in the event that [PUB_LIST_COMMAND] fails. 30 * in the event that [PUB_LIST_COMMAND] fails.
26 */ 31 */
27 static const String PUBSPEC_LOCK_NAME = 'pubspec.lock'; 32 static const String PUBSPEC_LOCK_NAME = 'pubspec.lock';
28 33
29 /** 34 /**
30 * [ResourceProvider] that is used to create the [Folder]s that populate the 35 * [ResourceProvider] that is used to create the [Folder]s that populate the
31 * package map. 36 * package map.
32 */ 37 */
33 final ResourceProvider resourceProvider; 38 final ResourceProvider resourceProvider;
34 39
35 /** 40 /**
36 * Sdk that we use to find the pub executable. 41 * Sdk that we use to find the pub executable.
37 */ 42 */
38 final DirectoryBasedDartSdk sdk; 43 final DirectoryBasedDartSdk sdk;
39 44
40 PubPackageMapProvider(this.resourceProvider, this.sdk); 45 /**
46 * The function used to run pub list.
47 */
48 RunPubList _runPubList;
49
50 /**
51 * Construct a new instance.
52 * A [RunPubList] implementation may be injected for testing
53 */
54 PubPackageMapProvider(this.resourceProvider, this.sdk, [this._runPubList]) {
55 if (_runPubList == null) {
56 _runPubList = _runPubListDefault;
57 }
58 }
41 59
42 @override 60 @override
43 PackageMapInfo computePackageMap(Folder folder) { 61 PackageMapInfo computePackageMap(Folder folder) {
44 // TODO(paulberry) make this asynchronous so that we can (a) do other 62 // TODO(paulberry) make this asynchronous so that we can (a) do other
45 // analysis while it's in progress, and (b) time out if it takes too long 63 // analysis while it's in progress, and (b) time out if it takes too long
46 // to respond. 64 // to respond.
47 String executable = sdk.pubExecutable.getAbsolutePath();
48 io.ProcessResult result; 65 io.ProcessResult result;
49 try { 66 try {
50 result = io.Process.runSync( 67 result = _runPubList(folder);
51 executable,
52 [PUB_LIST_COMMAND],
53 workingDirectory: folder.path);
54 } on io.ProcessException catch (exception, stackTrace) { 68 } on io.ProcessException catch (exception, stackTrace) {
55 AnalysisEngine.instance.logger.logInformation( 69 AnalysisEngine.instance.logger.logInformation(
56 "Error running pub $PUB_LIST_COMMAND\n$exception\n$stackTrace"); 70 "Error running pub $PUB_LIST_COMMAND\n$exception\n$stackTrace");
57 } 71 }
58 if (result == null || result.exitCode != 0) { 72 if (result == null || result.exitCode != 0) {
59 String exitCode = 73 String exitCode =
60 result != null ? 'exit code ${result.exitCode}' : 'null'; 74 result != null ? 'exit code ${result.exitCode}' : 'null';
61 AnalysisEngine.instance.logger.logInformation( 75 AnalysisEngine.instance.logger.logInformation(
62 "pub $PUB_LIST_COMMAND failed: $exitCode"); 76 "pub $PUB_LIST_COMMAND failed: $exitCode");
63 return _error(folder); 77 return computePackageMapError(folder);
64 } 78 }
65 try { 79 try {
66 return parsePackageMap(result.stdout, folder); 80 PackageMapInfo packageMap =
81 parsePackageMap(JSON.decode(result.stdout), folder);
82 return packageMap;
67 } catch (exception, stackTrace) { 83 } catch (exception, stackTrace) {
68 AnalysisEngine.instance.logger.logError( 84 AnalysisEngine.instance.logger.logError(
69 "Malformed output from pub $PUB_LIST_COMMAND\n$exception\n$stackTrace" ); 85 "Malformed output from pub $PUB_LIST_COMMAND\n$exception\n$stackTrace" );
70 } 86 }
71 87
72 return _error(folder); 88 return computePackageMapError(folder);
89 }
90
91 /**
92 * Create a PackageMapInfo object representing an error condition.
93 */
94 PackageMapInfo computePackageMapError(Folder folder) {
95 // Even if an error occurs, we still need to know the dependencies, so that
96 // we'll know when to try running "pub list-package-dirs" again.
97 // Unfortunately, "pub list-package-dirs" doesn't tell us dependencies when
98 // an error occurs, so just assume there is one dependency, "pubspec.lock".
99 List<String> dependencies = <String>[join(folder.path, PUBSPEC_LOCK_NAME)];
100 return new PackageMapInfo(null, dependencies.toSet());
73 } 101 }
74 102
75 /** 103 /**
76 * Decode the JSON output from pub into a package map. Paths in the 104 * Decode the JSON output from pub into a package map. Paths in the
77 * output are considered relative to [folder]. 105 * output are considered relative to [folder].
78 */ 106 */
79 PackageMapInfo parsePackageMap(String jsonText, Folder folder) { 107 PackageMapInfo parsePackageMap(Map obj, Folder folder) {
80 // The output of pub looks like this: 108 // The output of pub looks like this:
81 // { 109 // {
82 // "packages": { 110 // "packages": {
83 // "foo": "path/to/foo", 111 // "foo": "path/to/foo",
84 // "bar": ["path/to/bar1", "path/to/bar2"], 112 // "bar": ["path/to/bar1", "path/to/bar2"],
85 // "myapp": "path/to/myapp", // self link is included 113 // "myapp": "path/to/myapp", // self link is included
86 // }, 114 // },
87 // "input_files": [ 115 // "input_files": [
88 // "path/to/myapp/pubspec.lock" 116 // "path/to/myapp/pubspec.lock"
89 // ] 117 // ]
90 // } 118 // }
91 Map<String, List<Folder>> packageMap = new HashMap<String, List<Folder>>(); 119 Map<String, List<Folder>> packageMap = new HashMap<String, List<Folder>>();
92 Map obj = JSON.decode(jsonText);
93 Map packages = obj['packages']; 120 Map packages = obj['packages'];
94 processPaths(String packageName, List paths) { 121 processPaths(String packageName, List paths) {
95 List<Folder> folders = <Folder>[]; 122 List<Folder> folders = <Folder>[];
96 for (var path in paths) { 123 for (var path in paths) {
97 if (path is String) { 124 if (path is String) {
98 Resource resource = folder.getChild(path); 125 Resource resource = folder.getChild(path);
99 if (resource is Folder) { 126 if (resource is Folder) {
100 folders.add(resource); 127 folders.add(resource);
101 } 128 }
102 } 129 }
(...skipping 15 matching lines...) Expand all
118 for (var path in inputFiles) { 145 for (var path in inputFiles) {
119 if (path is String) { 146 if (path is String) {
120 dependencies.add(folder.canonicalizePath(path)); 147 dependencies.add(folder.canonicalizePath(path));
121 } 148 }
122 } 149 }
123 } 150 }
124 return new PackageMapInfo(packageMap, dependencies); 151 return new PackageMapInfo(packageMap, dependencies);
125 } 152 }
126 153
127 /** 154 /**
128 * Create a PackageMapInfo object representing an error condition. 155 * Run pub list to determine the packages and input files.
129 */ 156 */
130 PackageMapInfo _error(Folder folder) { 157 io.ProcessResult _runPubListDefault(Folder folder) {
131 // Even if an error occurs, we still need to know the dependencies, so that 158 return io.Process.runSync(
132 // we'll know when to try running "pub list-package-dirs" again. 159 sdk.pubExecutable.getAbsolutePath(),
133 // Unfortunately, "pub list-package-dirs" doesn't tell us dependencies when 160 [PUB_LIST_COMMAND],
134 // an error occurs, so just assume there is one dependency, "pubspec.lock". 161 workingDirectory: folder.path);
135 List<String> dependencies = <String>[join(folder.path, PUBSPEC_LOCK_NAME)];
136 return new PackageMapInfo(null, dependencies.toSet());
137 } 162 }
138 } 163 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/file_system/memory_file_system.dart ('k') | pkg/analyzer/test/source/package_map_provider_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698