OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /** | 5 /// Definitions used to run the polymer linter and deploy tools without using |
6 * Definitions used to run the polymer linter and deploy tools without using | 6 /// pub serve or pub deploy. |
7 * pub serve or pub deploy. | |
8 */ | |
9 library polymer.src.build.runner; | 7 library polymer.src.build.runner; |
10 | 8 |
11 import 'dart:async'; | 9 import 'dart:async'; |
12 import 'dart:convert'; | 10 import 'dart:convert'; |
13 import 'dart:io'; | 11 import 'dart:io'; |
14 | 12 |
15 import 'package:barback/barback.dart'; | 13 import 'package:barback/barback.dart'; |
16 import 'package:path/path.dart' as path; | 14 import 'package:path/path.dart' as path; |
17 import 'package:stack_trace/stack_trace.dart'; | 15 import 'package:stack_trace/stack_trace.dart'; |
18 import 'package:yaml/yaml.dart'; | 16 import 'package:yaml/yaml.dart'; |
19 | 17 |
20 | 18 |
21 /** Collects different parameters needed to configure and run barback. */ | 19 /// Collects different parameters needed to configure and run barback. |
22 class BarbackOptions { | 20 class BarbackOptions { |
23 /** | 21 /// Phases of transformers to run for the current package. |
24 * Phases of transformers to run for the current package. | 22 /// Use packagePhases to specify phases for other packages. |
25 * Use packagePhases to specify phases for other packages. | |
26 */ | |
27 final List<List<Transformer>> phases; | 23 final List<List<Transformer>> phases; |
28 | 24 |
29 /** Package to treat as the current package in barback. */ | 25 /// Package to treat as the current package in barback. |
30 final String currentPackage; | 26 final String currentPackage; |
31 | 27 |
32 /** Directory root for the current package. */ | 28 /// Directory root for the current package. |
33 final String packageHome; | 29 final String packageHome; |
34 | 30 |
35 /** | 31 /// Mapping between package names and the path in the file system where |
36 * Mapping between package names and the path in the file system where | 32 /// to find the sources of such package. |
37 * to find the sources of such package. | |
38 */ | |
39 final Map<String, String> packageDirs; | 33 final Map<String, String> packageDirs; |
40 | 34 |
41 /** Whether to run transformers on the test folder. */ | 35 /// Whether to run transformers on the test folder. |
42 final bool transformTests; | 36 final bool transformTests; |
43 | 37 |
44 /** Directory where to generate code, if any. */ | 38 /// Directory where to generate code, if any. |
45 final String outDir; | 39 final String outDir; |
46 | 40 |
47 /** | 41 /// Whether to print error messages using a json-format that tools, such as |
48 * Whether to print error messages using a json-format that tools, such as the | 42 /// the Dart Editor, can process. |
49 * Dart Editor, can process. | |
50 */ | |
51 final bool machineFormat; | 43 final bool machineFormat; |
52 | 44 |
53 /** | 45 /// Whether to follow symlinks when listing directories. By default this is |
54 * Whether to follow symlinks when listing directories. By default this is | 46 /// false because directories have symlinks for the packages directory created |
55 * false because directories have symlinks for the packages directory created | 47 /// by pub, but it can be turned on for custom uses of this library. |
56 * by pub, but it can be turned on for custom uses of this library. | |
57 */ | |
58 final bool followLinks; | 48 final bool followLinks; |
59 | 49 |
60 /** | 50 /// Phases of transformers to apply to packages other than the current |
61 * Phases of transformers to apply to packages other than the current | 51 /// package, keyed by the package name. |
62 * package, keyed by the package name. | |
63 */ | |
64 final Map<String, List<List<Transformer>>> packagePhases; | 52 final Map<String, List<List<Transformer>>> packagePhases; |
65 | 53 |
66 BarbackOptions(this.phases, this.outDir, {currentPackage, String packageHome, | 54 BarbackOptions(this.phases, this.outDir, {currentPackage, String packageHome, |
67 packageDirs, this.transformTests: false, this.machineFormat: false, | 55 packageDirs, this.transformTests: false, this.machineFormat: false, |
68 this.followLinks: false, | 56 this.followLinks: false, |
69 this.packagePhases: const {}}) | 57 this.packagePhases: const {}}) |
70 : currentPackage = (currentPackage != null | 58 : currentPackage = (currentPackage != null |
71 ? currentPackage : readCurrentPackageFromPubspec()), | 59 ? currentPackage : readCurrentPackageFromPubspec()), |
72 packageHome = packageHome, | 60 packageHome = packageHome, |
73 packageDirs = (packageDirs != null | 61 packageDirs = (packageDirs != null |
74 ? packageDirs : readPackageDirsFromPub(packageHome, currentPackage)); | 62 ? packageDirs : readPackageDirsFromPub(packageHome, currentPackage)); |
75 | 63 |
76 } | 64 } |
77 | 65 |
78 /** | 66 /// Creates a barback system as specified by [options] and runs it. Returns a |
79 * Creates a barback system as specified by [options] and runs it. Returns a | 67 /// future that contains the list of assets generated after barback runs to |
80 * future that contains the list of assets generated after barback runs to | 68 /// completion. |
81 * completion. | |
82 */ | |
83 Future<AssetSet> runBarback(BarbackOptions options) { | 69 Future<AssetSet> runBarback(BarbackOptions options) { |
84 var barback = new Barback(new _PackageProvider(options.packageDirs)); | 70 var barback = new Barback(new _PackageProvider(options.packageDirs)); |
85 _initBarback(barback, options); | 71 _initBarback(barback, options); |
86 _attachListeners(barback, options); | 72 _attachListeners(barback, options); |
87 if (options.outDir == null) return barback.getAllAssets(); | 73 if (options.outDir == null) return barback.getAllAssets(); |
88 return _emitAllFiles(barback, options); | 74 return _emitAllFiles(barback, options); |
89 } | 75 } |
90 | 76 |
91 /** Extract the current package from the pubspec.yaml file. */ | 77 /// Extract the current package from the pubspec.yaml file. |
92 String readCurrentPackageFromPubspec([String dir]) { | 78 String readCurrentPackageFromPubspec([String dir]) { |
93 var pubspec = new File( | 79 var pubspec = new File( |
94 dir == null ? 'pubspec.yaml' : path.join(dir, 'pubspec.yaml')); | 80 dir == null ? 'pubspec.yaml' : path.join(dir, 'pubspec.yaml')); |
95 if (!pubspec.existsSync()) { | 81 if (!pubspec.existsSync()) { |
96 print('error: pubspec.yaml file not found, please run this script from ' | 82 print('error: pubspec.yaml file not found, please run this script from ' |
97 'your package root directory.'); | 83 'your package root directory.'); |
98 return null; | 84 return null; |
99 } | 85 } |
100 return loadYaml(pubspec.readAsStringSync())['name']; | 86 return loadYaml(pubspec.readAsStringSync())['name']; |
101 } | 87 } |
102 | 88 |
103 /** | 89 /// Extract a mapping between package names and the path in the file system |
104 * Extract a mapping between package names and the path in the file system where | 90 /// which has the source of the package. This map will contain an entry for the |
105 * to find the sources of such package. This map will contain an entry for the | 91 /// current package and everything it depends on (extracted via `pub |
106 * current package and everything it depends on (extracted via `pub | 92 /// list-package-dirs`). |
107 * list-package-dirs`). | |
108 */ | |
109 Map<String, String> readPackageDirsFromPub( | 93 Map<String, String> readPackageDirsFromPub( |
110 [String packageHome, String currentPackage]) { | 94 [String packageHome, String currentPackage]) { |
111 var cachedDir = Directory.current; | 95 var cachedDir = Directory.current; |
112 if (packageHome != null) { | 96 if (packageHome != null) { |
113 Directory.current = new Directory(packageHome); | 97 Directory.current = new Directory(packageHome); |
114 } else { | 98 } else { |
115 packageHome = cachedDir.path; | 99 packageHome = cachedDir.path; |
116 } | 100 } |
117 | 101 |
118 var dartExec = Platform.executable; | 102 var dartExec = Platform.executable; |
(...skipping 12 matching lines...) Expand all Loading... |
131 | 115 |
132 if (currentPackage == null) { | 116 if (currentPackage == null) { |
133 currentPackage = readCurrentPackageFromPubspec(packageHome); | 117 currentPackage = readCurrentPackageFromPubspec(packageHome); |
134 } | 118 } |
135 map[currentPackage] = packageHome; | 119 map[currentPackage] = packageHome; |
136 | 120 |
137 Directory.current = cachedDir; | 121 Directory.current = cachedDir; |
138 return map; | 122 return map; |
139 } | 123 } |
140 | 124 |
141 /** Return the relative path of each file under [subDir] in [package]. */ | 125 /// Return the relative path of each file under [subDir] in [package]. |
142 Iterable<String> _listPackageDir(String package, String subDir, | 126 Iterable<String> _listPackageDir(String package, String subDir, |
143 BarbackOptions options) { | 127 BarbackOptions options) { |
144 var packageDir = options.packageDirs[package]; | 128 var packageDir = options.packageDirs[package]; |
145 if (packageDir == null) return const []; | 129 if (packageDir == null) return const []; |
146 var dir = new Directory(path.join(packageDir, subDir)); | 130 var dir = new Directory(path.join(packageDir, subDir)); |
147 if (!dir.existsSync()) return const []; | 131 if (!dir.existsSync()) return const []; |
148 return dir.listSync(recursive: true, followLinks: options.followLinks) | 132 return dir.listSync(recursive: true, followLinks: options.followLinks) |
149 .where((f) => f is File) | 133 .where((f) => f is File) |
150 .map((f) => path.relative(f.path, from: packageDir)); | 134 .map((f) => path.relative(f.path, from: packageDir)); |
151 } | 135 } |
152 | 136 |
153 /** A simple provider that reads files directly from the pub cache. */ | 137 /// A simple provider that reads files directly from the pub cache. |
154 class _PackageProvider implements PackageProvider { | 138 class _PackageProvider implements PackageProvider { |
155 Map<String, String> packageDirs; | 139 Map<String, String> packageDirs; |
156 Iterable<String> get packages => packageDirs.keys; | 140 Iterable<String> get packages => packageDirs.keys; |
157 | 141 |
158 _PackageProvider(this.packageDirs); | 142 _PackageProvider(this.packageDirs); |
159 | 143 |
160 Future<Asset> getAsset(AssetId id) => new Future.value( | 144 Future<Asset> getAsset(AssetId id) => new Future.value( |
161 new Asset.fromPath(id, path.join(packageDirs[id.package], | 145 new Asset.fromPath(id, path.join(packageDirs[id.package], |
162 _toSystemPath(id.path)))); | 146 _toSystemPath(id.path)))); |
163 } | 147 } |
164 | 148 |
165 /** Convert asset paths to system paths (Assets always use the posix style). */ | 149 /// Convert asset paths to system paths (Assets always use the posix style). |
166 String _toSystemPath(String assetPath) { | 150 String _toSystemPath(String assetPath) { |
167 if (path.Style.platform != path.Style.windows) return assetPath; | 151 if (path.Style.platform != path.Style.windows) return assetPath; |
168 return path.joinAll(path.posix.split(assetPath)); | 152 return path.joinAll(path.posix.split(assetPath)); |
169 } | 153 } |
170 | 154 |
171 /** Tell barback which transformers to use and which assets to process. */ | 155 /// Tell barback which transformers to use and which assets to process. |
172 void _initBarback(Barback barback, BarbackOptions options) { | 156 void _initBarback(Barback barback, BarbackOptions options) { |
173 var assets = []; | 157 var assets = []; |
174 void addAssets(String package, String subDir) { | 158 void addAssets(String package, String subDir) { |
175 for (var filepath in _listPackageDir(package, subDir, options)) { | 159 for (var filepath in _listPackageDir(package, subDir, options)) { |
176 assets.add(new AssetId(package, filepath)); | 160 assets.add(new AssetId(package, filepath)); |
177 } | 161 } |
178 } | 162 } |
179 | 163 |
180 for (var package in options.packageDirs.keys) { | 164 for (var package in options.packageDirs.keys) { |
181 // Notify barback to process anything under 'lib' and 'asset'. | 165 // Notify barback to process anything under 'lib' and 'asset'. |
182 addAssets(package, 'lib'); | 166 addAssets(package, 'lib'); |
183 addAssets(package, 'asset'); | 167 addAssets(package, 'asset'); |
184 | 168 |
185 if (options.packagePhases.containsKey(package)) { | 169 if (options.packagePhases.containsKey(package)) { |
186 barback.updateTransformers(package, options.packagePhases[package]); | 170 barback.updateTransformers(package, options.packagePhases[package]); |
187 } | 171 } |
188 } | 172 } |
189 barback.updateTransformers(options.currentPackage, options.phases); | 173 barback.updateTransformers(options.currentPackage, options.phases); |
190 | 174 |
191 // In case of the current package, include also 'web'. | 175 // In case of the current package, include also 'web'. |
192 addAssets(options.currentPackage, 'web'); | 176 addAssets(options.currentPackage, 'web'); |
193 if (options.transformTests) addAssets(options.currentPackage, 'test'); | 177 if (options.transformTests) addAssets(options.currentPackage, 'test'); |
194 | 178 |
195 // Add the sources after the transformers so all transformers are present | 179 // Add the sources after the transformers so all transformers are present |
196 // when barback starts processing the assets. | 180 // when barback starts processing the assets. |
197 barback.updateSources(assets); | 181 barback.updateSources(assets); |
198 } | 182 } |
199 | 183 |
200 /** Attach error listeners on [barback] so we can report errors. */ | 184 /// Attach error listeners on [barback] so we can report errors. |
201 void _attachListeners(Barback barback, BarbackOptions options) { | 185 void _attachListeners(Barback barback, BarbackOptions options) { |
202 // Listen for errors and results | 186 // Listen for errors and results |
203 barback.errors.listen((e) { | 187 barback.errors.listen((e) { |
204 var trace = null; | 188 var trace = null; |
205 if (e is Error) trace = e.stackTrace; | 189 if (e is Error) trace = e.stackTrace; |
206 if (trace != null) { | 190 if (trace != null) { |
207 print(Trace.format(trace)); | 191 print(Trace.format(trace)); |
208 } | 192 } |
209 print('error running barback: $e'); | 193 print('error running barback: $e'); |
210 exit(1); | 194 exit(1); |
211 }); | 195 }); |
212 | 196 |
213 barback.results.listen((result) { | 197 barback.results.listen((result) { |
214 if (!result.succeeded) { | 198 if (!result.succeeded) { |
215 print("build failed with errors: ${result.errors}"); | 199 print("build failed with errors: ${result.errors}"); |
216 exit(1); | 200 exit(1); |
217 } | 201 } |
218 }); | 202 }); |
219 | 203 |
220 barback.log.listen((entry) { | 204 barback.log.listen((entry) { |
221 if (options.machineFormat) { | 205 if (options.machineFormat) { |
222 print(_jsonFormatter(entry)); | 206 print(_jsonFormatter(entry)); |
223 } else { | 207 } else { |
224 print(_consoleFormatter(entry)); | 208 print(_consoleFormatter(entry)); |
225 } | 209 } |
226 }); | 210 }); |
227 } | 211 } |
228 | 212 |
229 /** | 213 /// Emits all outputs of [barback] and copies files that we didn't process (like |
230 * Emits all outputs of [barback] and copies files that we didn't process (like | 214 /// dependent package's libraries). |
231 * dependent package's libraries). | |
232 */ | |
233 Future _emitAllFiles(Barback barback, BarbackOptions options) { | 215 Future _emitAllFiles(Barback barback, BarbackOptions options) { |
234 return barback.getAllAssets().then((assets) { | 216 return barback.getAllAssets().then((assets) { |
235 // Delete existing output folder before we generate anything | 217 // Delete existing output folder before we generate anything |
236 var dir = new Directory(options.outDir); | 218 var dir = new Directory(options.outDir); |
237 if (dir.existsSync()) dir.deleteSync(recursive: true); | 219 if (dir.existsSync()) dir.deleteSync(recursive: true); |
238 return _emitPackagesDir(options) | 220 return _emitPackagesDir(options) |
239 .then((_) => _emitTransformedFiles(assets, options)) | 221 .then((_) => _emitTransformedFiles(assets, options)) |
240 .then((_) => _addPackagesSymlinks(assets, options)) | 222 .then((_) => _addPackagesSymlinks(assets, options)) |
241 .then((_) => assets); | 223 .then((_) => assets); |
242 }); | 224 }); |
(...skipping 22 matching lines...) Expand all Loading... |
265 filepath = path.join(options.outDir, _toSystemPath(id.path)); | 247 filepath = path.join(options.outDir, _toSystemPath(id.path)); |
266 } else { | 248 } else { |
267 // TODO(sigmund): do something about other assets? | 249 // TODO(sigmund): do something about other assets? |
268 return null; | 250 return null; |
269 } | 251 } |
270 | 252 |
271 return _writeAsset(filepath, asset); | 253 return _writeAsset(filepath, asset); |
272 }); | 254 }); |
273 } | 255 } |
274 | 256 |
275 /** | 257 /// Adds a package symlink from each directory under `out/web/foo/` to |
276 * Adds a package symlink from each directory under `out/web/foo/` to | 258 /// `out/packages`. |
277 * `out/packages`. | |
278 */ | |
279 void _addPackagesSymlinks(AssetSet assets, BarbackOptions options) { | 259 void _addPackagesSymlinks(AssetSet assets, BarbackOptions options) { |
280 var outPackages = path.join(options.outDir, 'packages'); | 260 var outPackages = path.join(options.outDir, 'packages'); |
281 var currentPackage = options.currentPackage; | 261 var currentPackage = options.currentPackage; |
282 for (var asset in assets) { | 262 for (var asset in assets) { |
283 var id = asset.id; | 263 var id = asset.id; |
284 if (id.package != currentPackage) continue; | 264 if (id.package != currentPackage) continue; |
285 var firstDir = _firstDir(id.path); | 265 var firstDir = _firstDir(id.path); |
286 if (firstDir == null) continue; | 266 if (firstDir == null) continue; |
287 | 267 |
288 if (firstDir == 'web' || (options.transformTests && firstDir == 'test')) { | 268 if (firstDir == 'web' || (options.transformTests && firstDir == 'test')) { |
289 var dir = path.join(options.outDir, path.dirname(_toSystemPath(id.path))); | 269 var dir = path.join(options.outDir, path.dirname(_toSystemPath(id.path))); |
290 var linkPath = path.join(dir, 'packages'); | 270 var linkPath = path.join(dir, 'packages'); |
291 var link = new Link(linkPath); | 271 var link = new Link(linkPath); |
292 if (!link.existsSync()) { | 272 if (!link.existsSync()) { |
293 var targetPath = Platform.operatingSystem == 'windows' | 273 var targetPath = Platform.operatingSystem == 'windows' |
294 ? path.normalize(path.absolute(outPackages)) | 274 ? path.normalize(path.absolute(outPackages)) |
295 : path.normalize(path.relative(outPackages, from: dir)); | 275 : path.normalize(path.relative(outPackages, from: dir)); |
296 link.createSync(targetPath); | 276 link.createSync(targetPath); |
297 } | 277 } |
298 } | 278 } |
299 } | 279 } |
300 } | 280 } |
301 | 281 |
302 /** | 282 /// Emits a 'packages' directory directly under `out/packages` with the contents |
303 * Emits a 'packages' directory directly under `out/packages` with the contents | 283 /// of every file that was not transformed by barback. |
304 * of every file that was not transformed by barback. | |
305 */ | |
306 Future _emitPackagesDir(BarbackOptions options) { | 284 Future _emitPackagesDir(BarbackOptions options) { |
307 var outPackages = path.join(options.outDir, 'packages'); | 285 var outPackages = path.join(options.outDir, 'packages'); |
308 _ensureDir(outPackages); | 286 _ensureDir(outPackages); |
309 | 287 |
310 // Copy all the files we didn't process | 288 // Copy all the files we didn't process |
311 var dirs = options.packageDirs; | 289 var dirs = options.packageDirs; |
312 | 290 |
313 return Future.forEach(dirs.keys, (package) { | 291 return Future.forEach(dirs.keys, (package) { |
314 return Future.forEach(_listPackageDir(package, 'lib', options), (relpath) { | 292 return Future.forEach(_listPackageDir(package, 'lib', options), (relpath) { |
315 var inpath = path.join(dirs[package], relpath); | 293 var inpath = path.join(dirs[package], relpath); |
316 var outpath = path.join(outPackages, package, relpath.substring(4)); | 294 var outpath = path.join(outPackages, package, relpath.substring(4)); |
317 return _copyFile(inpath, outpath); | 295 return _copyFile(inpath, outpath); |
318 }); | 296 }); |
319 }); | 297 }); |
320 } | 298 } |
321 | 299 |
322 /** Ensure [dirpath] exists. */ | 300 /// Ensure [dirpath] exists. |
323 void _ensureDir(String dirpath) { | 301 void _ensureDir(String dirpath) { |
324 new Directory(dirpath).createSync(recursive: true); | 302 new Directory(dirpath).createSync(recursive: true); |
325 } | 303 } |
326 | 304 |
327 /** | 305 /// Returns the first directory name on a url-style path, or null if there are |
328 * Returns the first directory name on a url-style path, or null if there are no | 306 /// no slashes. |
329 * slashes. | |
330 */ | |
331 String _firstDir(String url) { | 307 String _firstDir(String url) { |
332 var firstSlash = url.indexOf('/'); | 308 var firstSlash = url.indexOf('/'); |
333 if (firstSlash == -1) return null; | 309 if (firstSlash == -1) return null; |
334 return url.substring(0, firstSlash); | 310 return url.substring(0, firstSlash); |
335 } | 311 } |
336 | 312 |
337 /** Copy a file from [inpath] to [outpath]. */ | 313 /// Copy a file from [inpath] to [outpath]. |
338 Future _copyFile(String inpath, String outpath) { | 314 Future _copyFile(String inpath, String outpath) { |
339 _ensureDir(path.dirname(outpath)); | 315 _ensureDir(path.dirname(outpath)); |
340 return new File(inpath).openRead().pipe(new File(outpath).openWrite()); | 316 return new File(inpath).openRead().pipe(new File(outpath).openWrite()); |
341 } | 317 } |
342 | 318 |
343 /** Write contents of an [asset] into a file at [filepath]. */ | 319 /// Write contents of an [asset] into a file at [filepath]. |
344 Future _writeAsset(String filepath, Asset asset) { | 320 Future _writeAsset(String filepath, Asset asset) { |
345 _ensureDir(path.dirname(filepath)); | 321 _ensureDir(path.dirname(filepath)); |
346 return asset.read().pipe(new File(filepath).openWrite()); | 322 return asset.read().pipe(new File(filepath).openWrite()); |
347 } | 323 } |
348 | 324 |
349 String _kindFromEntry(LogEntry entry) { | 325 String _kindFromEntry(LogEntry entry) { |
350 var level = entry.level; | 326 var level = entry.level; |
351 return level == LogLevel.ERROR ? 'error' | 327 return level == LogLevel.ERROR ? 'error' |
352 : (level == LogLevel.WARNING ? 'warning' : 'info'); | 328 : (level == LogLevel.WARNING ? 'warning' : 'info'); |
353 } | 329 } |
354 | 330 |
355 /** | 331 /// Formatter that generates messages using a format that can be parsed |
356 * Formatter that generates messages using a format that can be parsed | 332 /// by tools, such as the Dart Editor, for reporting error messages. |
357 * by tools, such as the Dart Editor, for reporting error messages. | |
358 */ | |
359 String _jsonFormatter(LogEntry entry) { | 333 String _jsonFormatter(LogEntry entry) { |
360 var kind = _kindFromEntry(entry); | 334 var kind = _kindFromEntry(entry); |
361 var span = entry.span; | 335 var span = entry.span; |
362 return JSON.encode((span == null) | 336 return JSON.encode((span == null) |
363 ? [{'method': kind, 'params': {'message': entry.message}}] | 337 ? [{'method': kind, 'params': {'message': entry.message}}] |
364 : [{'method': kind, | 338 : [{'method': kind, |
365 'params': { | 339 'params': { |
366 'file': span.sourceUrl, | 340 'file': span.sourceUrl, |
367 'message': entry.message, | 341 'message': entry.message, |
368 'line': span.start.line + 1, | 342 'line': span.start.line + 1, |
369 'charStart': span.start.offset, | 343 'charStart': span.start.offset, |
370 'charEnd': span.end.offset, | 344 'charEnd': span.end.offset, |
371 }}]); | 345 }}]); |
372 } | 346 } |
373 | 347 |
374 /** | 348 /// Formatter that generates messages that are easy to read on the console (used |
375 * Formatter that generates messages that are easy to read on the console (used | 349 /// by default). |
376 * by default). | |
377 */ | |
378 String _consoleFormatter(LogEntry entry) { | 350 String _consoleFormatter(LogEntry entry) { |
379 var kind = _kindFromEntry(entry); | 351 var kind = _kindFromEntry(entry); |
380 var useColors = stdioType(stdout) == StdioType.TERMINAL; | 352 var useColors = stdioType(stdout) == StdioType.TERMINAL; |
381 var levelColor = (kind == 'error') ? _RED_COLOR : _MAGENTA_COLOR; | 353 var levelColor = (kind == 'error') ? _RED_COLOR : _MAGENTA_COLOR; |
382 var output = new StringBuffer(); | 354 var output = new StringBuffer(); |
383 if (useColors) output.write(levelColor); | 355 if (useColors) output.write(levelColor); |
384 output..write(kind)..write(' '); | 356 output..write(kind)..write(' '); |
385 if (useColors) output.write(_NO_COLOR); | 357 if (useColors) output.write(_NO_COLOR); |
386 if (entry.span == null) { | 358 if (entry.span == null) { |
387 output.write(entry.message); | 359 output.write(entry.message); |
388 } else { | 360 } else { |
389 output.write(entry.span.getLocationMessage(entry.message, | 361 output.write(entry.span.getLocationMessage(entry.message, |
390 useColors: useColors, | 362 useColors: useColors, |
391 color: levelColor)); | 363 color: levelColor)); |
392 } | 364 } |
393 return output.toString(); | 365 return output.toString(); |
394 } | 366 } |
395 | 367 |
396 const String _RED_COLOR = '\u001b[31m'; | 368 const String _RED_COLOR = '\u001b[31m'; |
397 const String _MAGENTA_COLOR = '\u001b[35m'; | 369 const String _MAGENTA_COLOR = '\u001b[35m'; |
398 const String _NO_COLOR = '\u001b[0m'; | 370 const String _NO_COLOR = '\u001b[0m'; |
OLD | NEW |