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

Side by Side Diff: sdk/lib/_internal/pub_generated/lib/src/pubspec.dart

Issue 657673002: Regenerate pub sources. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 2 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) 2012, the Dart project authors. Please see the AUTHORS file
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.
4
1 library pub.pubspec; 5 library pub.pubspec;
6
2 import 'package:path/path.dart' as path; 7 import 'package:path/path.dart' as path;
3 import 'package:pub_semver/pub_semver.dart'; 8 import 'package:pub_semver/pub_semver.dart';
4 import 'package:source_span/source_span.dart'; 9 import 'package:source_span/source_span.dart';
5 import 'package:yaml/yaml.dart'; 10 import 'package:yaml/yaml.dart';
11
6 import 'barback/transformer_config.dart'; 12 import 'barback/transformer_config.dart';
7 import 'exceptions.dart'; 13 import 'exceptions.dart';
8 import 'io.dart'; 14 import 'io.dart';
9 import 'package.dart'; 15 import 'package.dart';
10 import 'source_registry.dart'; 16 import 'source_registry.dart';
11 import 'utils.dart'; 17 import 'utils.dart';
18
19 /// The parsed contents of a pubspec file.
20 ///
21 /// The fields of a pubspec are, for the most part, validated when they're first
22 /// accessed. This allows a partially-invalid pubspec to be used if only the
23 /// valid portions are relevant. To get a list of all errors in the pubspec, use
24 /// [allErrors].
12 class Pubspec { 25 class Pubspec {
26 // If a new lazily-initialized field is added to this class and the
27 // initialization can throw a [PubspecException], that error should also be
28 // exposed through [allErrors].
29
30 /// The registry of sources to use when parsing [dependencies] and
31 /// [devDependencies].
32 ///
33 /// This will be null if this was created using [new Pubspec] or [new
34 /// Pubspec.empty].
13 final SourceRegistry _sources; 35 final SourceRegistry _sources;
36
37 /// The location from which the pubspec was loaded.
38 ///
39 /// This can be null if the pubspec was created in-memory or if its location
40 /// is unknown.
14 Uri get _location => fields.span.sourceUrl; 41 Uri get _location => fields.span.sourceUrl;
42
43 /// All pubspec fields.
44 ///
45 /// This includes the fields from which other properties are derived.
15 final YamlMap fields; 46 final YamlMap fields;
47
48 /// The package's name.
16 String get name { 49 String get name {
17 if (_name != null) return _name; 50 if (_name != null) return _name;
51
18 var name = fields['name']; 52 var name = fields['name'];
19 if (name == null) { 53 if (name == null) {
20 throw new PubspecException( 54 throw new PubspecException(
21 'Missing the required "name" field.', 55 'Missing the required "name" field.',
22 fields.span); 56 fields.span);
23 } else if (name is! String) { 57 } else if (name is! String) {
24 throw new PubspecException( 58 throw new PubspecException(
25 '"name" field must be a string.', 59 '"name" field must be a string.',
26 fields.nodes['name'].span); 60 fields.nodes['name'].span);
27 } 61 }
62
28 _name = name; 63 _name = name;
29 return _name; 64 return _name;
30 } 65 }
31 String _name; 66 String _name;
67
68 /// The package's version.
32 Version get version { 69 Version get version {
33 if (_version != null) return _version; 70 if (_version != null) return _version;
71
34 var version = fields['version']; 72 var version = fields['version'];
35 if (version == null) { 73 if (version == null) {
36 _version = Version.none; 74 _version = Version.none;
37 return _version; 75 return _version;
38 } 76 }
77
39 var span = fields.nodes['version'].span; 78 var span = fields.nodes['version'].span;
40 if (version is num) { 79 if (version is num) {
41 var fixed = '$version.0'; 80 var fixed = '$version.0';
42 if (version is int) { 81 if (version is int) {
43 fixed = '$fixed.0'; 82 fixed = '$fixed.0';
44 } 83 }
45 _error('"version" field must have three numeric components: major, ' 84 _error(
46 'minor, and patch. Instead of "$version", consider "$fixed".', span); 85 '"version" field must have three numeric components: major, '
86 'minor, and patch. Instead of "$version", consider "$fixed".',
87 span);
47 } 88 }
48 if (version is! String) { 89 if (version is! String) {
49 _error('"version" field must be a string.', span); 90 _error('"version" field must be a string.', span);
50 } 91 }
92
51 _version = 93 _version =
52 _wrapFormatException('version number', span, () => new Version.parse(ver sion)); 94 _wrapFormatException('version number', span, () => new Version.parse(ver sion));
53 return _version; 95 return _version;
54 } 96 }
55 Version _version; 97 Version _version;
98
99 /// The additional packages this package depends on.
56 List<PackageDep> get dependencies { 100 List<PackageDep> get dependencies {
57 if (_dependencies != null) return _dependencies; 101 if (_dependencies != null) return _dependencies;
58 _dependencies = _parseDependencies('dependencies'); 102 _dependencies = _parseDependencies('dependencies');
59 if (_devDependencies == null) { 103 if (_devDependencies == null) {
60 _checkDependencyOverlap(_dependencies, devDependencies); 104 _checkDependencyOverlap(_dependencies, devDependencies);
61 } 105 }
62 return _dependencies; 106 return _dependencies;
63 } 107 }
64 List<PackageDep> _dependencies; 108 List<PackageDep> _dependencies;
109
110 /// The packages this package depends on when it is the root package.
65 List<PackageDep> get devDependencies { 111 List<PackageDep> get devDependencies {
66 if (_devDependencies != null) return _devDependencies; 112 if (_devDependencies != null) return _devDependencies;
67 _devDependencies = _parseDependencies('dev_dependencies'); 113 _devDependencies = _parseDependencies('dev_dependencies');
68 if (_dependencies == null) { 114 if (_dependencies == null) {
69 _checkDependencyOverlap(dependencies, _devDependencies); 115 _checkDependencyOverlap(dependencies, _devDependencies);
70 } 116 }
71 return _devDependencies; 117 return _devDependencies;
72 } 118 }
73 List<PackageDep> _devDependencies; 119 List<PackageDep> _devDependencies;
120
121 /// The dependency constraints that this package overrides when it is the
122 /// root package.
123 ///
124 /// Dependencies here will replace any dependency on a package with the same
125 /// name anywhere in the dependency graph.
74 List<PackageDep> get dependencyOverrides { 126 List<PackageDep> get dependencyOverrides {
75 if (_dependencyOverrides != null) return _dependencyOverrides; 127 if (_dependencyOverrides != null) return _dependencyOverrides;
76 _dependencyOverrides = _parseDependencies('dependency_overrides'); 128 _dependencyOverrides = _parseDependencies('dependency_overrides');
77 return _dependencyOverrides; 129 return _dependencyOverrides;
78 } 130 }
79 List<PackageDep> _dependencyOverrides; 131 List<PackageDep> _dependencyOverrides;
132
133 /// The configurations of the transformers to use for this package.
80 List<Set<TransformerConfig>> get transformers { 134 List<Set<TransformerConfig>> get transformers {
81 if (_transformers != null) return _transformers; 135 if (_transformers != null) return _transformers;
136
82 var transformers = fields['transformers']; 137 var transformers = fields['transformers'];
83 if (transformers == null) { 138 if (transformers == null) {
84 _transformers = []; 139 _transformers = [];
85 return _transformers; 140 return _transformers;
86 } 141 }
142
87 if (transformers is! List) { 143 if (transformers is! List) {
88 _error( 144 _error(
89 '"transformers" field must be a list.', 145 '"transformers" field must be a list.',
90 fields.nodes['transformers'].span); 146 fields.nodes['transformers'].span);
91 } 147 }
148
92 var i = 0; 149 var i = 0;
93 _transformers = transformers.nodes.map((phase) { 150 _transformers = transformers.nodes.map((phase) {
94 var phaseNodes = phase is YamlList ? phase.nodes : [phase]; 151 var phaseNodes = phase is YamlList ? phase.nodes : [phase];
95 return phaseNodes.map((transformerNode) { 152 return phaseNodes.map((transformerNode) {
96 var transformer = transformerNode.value; 153 var transformer = transformerNode.value;
97 if (transformer is! String && transformer is! Map) { 154 if (transformer is! String && transformer is! Map) {
98 _error( 155 _error(
99 'A transformer must be a string or map.', 156 'A transformer must be a string or map.',
100 transformerNode.span); 157 transformerNode.span);
101 } 158 }
159
102 var libraryNode; 160 var libraryNode;
103 var configurationNode; 161 var configurationNode;
104 if (transformer is String) { 162 if (transformer is String) {
105 libraryNode = transformerNode; 163 libraryNode = transformerNode;
106 } else { 164 } else {
107 if (transformer.length != 1) { 165 if (transformer.length != 1) {
108 _error( 166 _error(
109 'A transformer map must have a single key: the transformer ' 'id entifier.', 167 'A transformer map must have a single key: the transformer ' 'id entifier.',
110 transformerNode.span); 168 transformerNode.span);
111 } else if (transformer.keys.single is! String) { 169 } else if (transformer.keys.single is! String) {
112 _error( 170 _error(
113 'A transformer identifier must be a string.', 171 'A transformer identifier must be a string.',
114 transformer.nodes.keys.single.span); 172 transformer.nodes.keys.single.span);
115 } 173 }
174
116 libraryNode = transformer.nodes.keys.single; 175 libraryNode = transformer.nodes.keys.single;
117 configurationNode = transformer.nodes.values.single; 176 configurationNode = transformer.nodes.values.single;
118 if (configurationNode is! YamlMap) { 177 if (configurationNode is! YamlMap) {
119 _error( 178 _error(
120 "A transformer's configuration must be a map.", 179 "A transformer's configuration must be a map.",
121 configurationNode.span); 180 configurationNode.span);
122 } 181 }
123 } 182 }
183
124 var config = _wrapSpanFormatException('transformer config', () { 184 var config = _wrapSpanFormatException('transformer config', () {
125 return new TransformerConfig.parse( 185 return new TransformerConfig.parse(
126 libraryNode.value, 186 libraryNode.value,
127 libraryNode.span, 187 libraryNode.span,
128 configurationNode); 188 configurationNode);
129 }); 189 });
190
130 var package = config.id.package; 191 var package = config.id.package;
131 if (package != name && 192 if (package != name &&
132 !config.id.isBuiltInTransformer && 193 !config.id.isBuiltInTransformer &&
133 !dependencies.any((ref) => ref.name == package) && 194 !dependencies.any((ref) => ref.name == package) &&
134 !devDependencies.any((ref) => ref.name == package) && 195 !devDependencies.any((ref) => ref.name == package) &&
135 !dependencyOverrides.any((ref) => ref.name == package)) { 196 !dependencyOverrides.any((ref) => ref.name == package)) {
136 _error('"$package" is not a dependency.', libraryNode.span); 197 _error('"$package" is not a dependency.', libraryNode.span);
137 } 198 }
199
138 return config; 200 return config;
139 }).toSet(); 201 }).toSet();
140 }).toList(); 202 }).toList();
203
141 return _transformers; 204 return _transformers;
142 } 205 }
143 List<Set<TransformerConfig>> _transformers; 206 List<Set<TransformerConfig>> _transformers;
207
208 /// The environment-related metadata.
144 PubspecEnvironment get environment { 209 PubspecEnvironment get environment {
145 if (_environment != null) return _environment; 210 if (_environment != null) return _environment;
211
146 var yaml = fields['environment']; 212 var yaml = fields['environment'];
147 if (yaml == null) { 213 if (yaml == null) {
148 _environment = new PubspecEnvironment(VersionConstraint.any); 214 _environment = new PubspecEnvironment(VersionConstraint.any);
149 return _environment; 215 return _environment;
150 } 216 }
217
151 if (yaml is! Map) { 218 if (yaml is! Map) {
152 _error( 219 _error(
153 '"environment" field must be a map.', 220 '"environment" field must be a map.',
154 fields.nodes['environment'].span); 221 fields.nodes['environment'].span);
155 } 222 }
223
156 _environment = 224 _environment =
157 new PubspecEnvironment(_parseVersionConstraint(yaml.nodes['sdk'])); 225 new PubspecEnvironment(_parseVersionConstraint(yaml.nodes['sdk']));
158 return _environment; 226 return _environment;
159 } 227 }
160 PubspecEnvironment _environment; 228 PubspecEnvironment _environment;
229
230 /// The URL of the server that the package should default to being published
231 /// to, "none" if the package should not be published, or `null` if it should
232 /// be published to the default server.
233 ///
234 /// If this does return a URL string, it will be a valid parseable URL.
161 String get publishTo { 235 String get publishTo {
162 if (_parsedPublishTo) return _publishTo; 236 if (_parsedPublishTo) return _publishTo;
237
163 var publishTo = fields['publish_to']; 238 var publishTo = fields['publish_to'];
164 if (publishTo != null) { 239 if (publishTo != null) {
165 var span = fields.nodes['publish_to'].span; 240 var span = fields.nodes['publish_to'].span;
241
166 if (publishTo is! String) { 242 if (publishTo is! String) {
167 _error('"publish_to" field must be a string.', span); 243 _error('"publish_to" field must be a string.', span);
168 } 244 }
245
246 // It must be "none" or a valid URL.
169 if (publishTo != "none") { 247 if (publishTo != "none") {
170 _wrapFormatException( 248 _wrapFormatException(
171 '"publish_to" field', 249 '"publish_to" field',
172 span, 250 span,
173 () => Uri.parse(publishTo)); 251 () => Uri.parse(publishTo));
174 } 252 }
175 } 253 }
254
176 _parsedPublishTo = true; 255 _parsedPublishTo = true;
177 _publishTo = publishTo; 256 _publishTo = publishTo;
178 return _publishTo; 257 return _publishTo;
179 } 258 }
180 bool _parsedPublishTo = false; 259 bool _parsedPublishTo = false;
181 String _publishTo; 260 String _publishTo;
261
262 /// The executables that should be placed on the user's PATH when this
263 /// package is globally activated.
264 ///
265 /// It is a map of strings to string. Each key is the name of the command
266 /// that will be placed on the user's PATH. The value is the name of the
267 /// .dart script (without extension) in the package's `bin` directory that
268 /// should be run for that command. Both key and value must be "simple"
269 /// strings: alphanumerics, underscores and hypens only. If a value is
270 /// omitted, it is inferred to use the same name as the key.
182 Map<String, String> get executables { 271 Map<String, String> get executables {
183 if (_executables != null) return _executables; 272 if (_executables != null) return _executables;
273
184 _executables = {}; 274 _executables = {};
185 var yaml = fields['executables']; 275 var yaml = fields['executables'];
186 if (yaml == null) return _executables; 276 if (yaml == null) return _executables;
277
187 if (yaml is! Map) { 278 if (yaml is! Map) {
188 _error( 279 _error(
189 '"executables" field must be a map.', 280 '"executables" field must be a map.',
190 fields.nodes['executables'].span); 281 fields.nodes['executables'].span);
191 } 282 }
283
192 yaml.nodes.forEach((key, value) { 284 yaml.nodes.forEach((key, value) {
193 validateName(name, description) {} 285 // Don't allow path separators or other stuff meaningful to the shell.
286 validateName(name, description) {
287 }
288
194 if (key.value is! String) { 289 if (key.value is! String) {
195 _error('"executables" keys must be strings.', key.span); 290 _error('"executables" keys must be strings.', key.span);
196 } 291 }
292
197 final keyPattern = new RegExp(r"^[a-zA-Z0-9_-]+$"); 293 final keyPattern = new RegExp(r"^[a-zA-Z0-9_-]+$");
198 if (!keyPattern.hasMatch(key.value)) { 294 if (!keyPattern.hasMatch(key.value)) {
199 _error( 295 _error(
200 '"executables" keys may only contain letters, ' 296 '"executables" keys may only contain letters, '
201 'numbers, hyphens and underscores.', 297 'numbers, hyphens and underscores.',
202 key.span); 298 key.span);
203 } 299 }
300
204 if (value.value == null) { 301 if (value.value == null) {
205 value = key; 302 value = key;
206 } else if (value.value is! String) { 303 } else if (value.value is! String) {
207 _error('"executables" values must be strings or null.', value.span); 304 _error('"executables" values must be strings or null.', value.span);
208 } 305 }
306
209 final valuePattern = new RegExp(r"[/\\]"); 307 final valuePattern = new RegExp(r"[/\\]");
210 if (valuePattern.hasMatch(value.value)) { 308 if (valuePattern.hasMatch(value.value)) {
211 _error( 309 _error(
212 '"executables" values may not contain path separators.', 310 '"executables" values may not contain path separators.',
213 value.span); 311 value.span);
214 } 312 }
313
215 _executables[key.value] = value.value; 314 _executables[key.value] = value.value;
216 }); 315 });
316
217 return _executables; 317 return _executables;
218 } 318 }
219 Map<String, String> _executables; 319 Map<String, String> _executables;
320
321 /// Whether the package is private and cannot be published.
322 ///
323 /// This is specified in the pubspec by setting "publish_to" to "none".
220 bool get isPrivate => publishTo == "none"; 324 bool get isPrivate => publishTo == "none";
325
326 /// Whether or not the pubspec has no contents.
221 bool get isEmpty => 327 bool get isEmpty =>
222 name == null && version == Version.none && dependencies.isEmpty; 328 name == null && version == Version.none && dependencies.isEmpty;
329
330 /// Loads the pubspec for a package located in [packageDir].
331 ///
332 /// If [expectedName] is passed and the pubspec doesn't have a matching name
333 /// field, this will throw a [PubspecError].
223 factory Pubspec.load(String packageDir, SourceRegistry sources, 334 factory Pubspec.load(String packageDir, SourceRegistry sources,
224 {String expectedName}) { 335 {String expectedName}) {
225 var pubspecPath = path.join(packageDir, 'pubspec.yaml'); 336 var pubspecPath = path.join(packageDir, 'pubspec.yaml');
226 var pubspecUri = path.toUri(pubspecPath); 337 var pubspecUri = path.toUri(pubspecPath);
227 if (!fileExists(pubspecPath)) { 338 if (!fileExists(pubspecPath)) {
228 throw new FileException( 339 throw new FileException(
229 'Could not find a file named "pubspec.yaml" in "$packageDir".', 340 'Could not find a file named "pubspec.yaml" in "$packageDir".',
230 pubspecPath); 341 pubspecPath);
231 } 342 }
343
232 return new Pubspec.parse( 344 return new Pubspec.parse(
233 readTextFile(pubspecPath), 345 readTextFile(pubspecPath),
234 sources, 346 sources,
235 expectedName: expectedName, 347 expectedName: expectedName,
236 location: pubspecUri); 348 location: pubspecUri);
237 } 349 }
350
238 Pubspec(this._name, {Version version, Iterable<PackageDep> dependencies, 351 Pubspec(this._name, {Version version, Iterable<PackageDep> dependencies,
239 Iterable<PackageDep> devDependencies, Iterable<PackageDep> dependencyOverr ides, 352 Iterable<PackageDep> devDependencies, Iterable<PackageDep> dependencyOverr ides,
240 VersionConstraint sdkConstraint, 353 VersionConstraint sdkConstraint,
241 Iterable<Iterable<TransformerConfig>> transformers, Map fields, 354 Iterable<Iterable<TransformerConfig>> transformers, Map fields,
242 SourceRegistry sources}) 355 SourceRegistry sources})
243 : _version = version, 356 : _version = version,
244 _dependencies = dependencies == null ? null : dependencies.toList(), 357 _dependencies = dependencies == null ? null : dependencies.toList(),
245 _devDependencies = devDependencies == null ? 358 _devDependencies = devDependencies == null ?
246 null : 359 null :
247 devDependencies.toList(), 360 devDependencies.toList(),
248 _dependencyOverrides = dependencyOverrides == null ? 361 _dependencyOverrides = dependencyOverrides == null ?
249 null : 362 null :
250 dependencyOverrides.toList(), 363 dependencyOverrides.toList(),
251 _environment = new PubspecEnvironment(sdkConstraint), 364 _environment = new PubspecEnvironment(sdkConstraint),
252 _transformers = transformers == null ? 365 _transformers = transformers == null ?
253 [] : 366 [] :
254 transformers.map((phase) => phase.toSet()).toList(), 367 transformers.map((phase) => phase.toSet()).toList(),
255 fields = fields == null ? new YamlMap() : new YamlMap.wrap(fields), 368 fields = fields == null ? new YamlMap() : new YamlMap.wrap(fields),
256 _sources = sources; 369 _sources = sources;
370
257 Pubspec.empty() 371 Pubspec.empty()
258 : _sources = null, 372 : _sources = null,
259 _name = null, 373 _name = null,
260 _version = Version.none, 374 _version = Version.none,
261 _dependencies = <PackageDep>[], 375 _dependencies = <PackageDep>[],
262 _devDependencies = <PackageDep>[], 376 _devDependencies = <PackageDep>[],
263 _environment = new PubspecEnvironment(), 377 _environment = new PubspecEnvironment(),
264 _transformers = <Set<TransformerConfig>>[], 378 _transformers = <Set<TransformerConfig>>[],
265 fields = new YamlMap(); 379 fields = new YamlMap();
380
381 /// Returns a Pubspec object for an already-parsed map representing its
382 /// contents.
383 ///
384 /// If [expectedName] is passed and the pubspec doesn't have a matching name
385 /// field, this will throw a [PubspecError].
386 ///
387 /// [location] is the location from which this pubspec was loaded.
266 Pubspec.fromMap(Map fields, this._sources, {String expectedName, 388 Pubspec.fromMap(Map fields, this._sources, {String expectedName,
267 Uri location}) 389 Uri location})
268 : fields = fields is YamlMap ? 390 : fields = fields is YamlMap ?
269 fields : 391 fields :
270 new YamlMap.wrap(fields, sourceUrl: location) { 392 new YamlMap.wrap(fields, sourceUrl: location) {
393 // If [expectedName] is passed, ensure that the actual 'name' field exists
394 // and matches the expectation.
271 if (expectedName == null) return; 395 if (expectedName == null) return;
272 if (name == expectedName) return; 396 if (name == expectedName) return;
397
273 throw new PubspecException( 398 throw new PubspecException(
274 '"name" field doesn\'t match expected name ' '"$expectedName".', 399 '"name" field doesn\'t match expected name ' '"$expectedName".',
275 this.fields.nodes["name"].span); 400 this.fields.nodes["name"].span);
276 } 401 }
402
403 /// Parses the pubspec stored at [filePath] whose text is [contents].
404 ///
405 /// If the pubspec doesn't define a version for itself, it defaults to
406 /// [Version.none].
277 factory Pubspec.parse(String contents, SourceRegistry sources, 407 factory Pubspec.parse(String contents, SourceRegistry sources,
278 {String expectedName, Uri location}) { 408 {String expectedName, Uri location}) {
279 var pubspecNode = loadYamlNode(contents, sourceUrl: location); 409 var pubspecNode = loadYamlNode(contents, sourceUrl: location);
280 if (pubspecNode is YamlScalar && pubspecNode.value == null) { 410 if (pubspecNode is YamlScalar && pubspecNode.value == null) {
281 pubspecNode = new YamlMap(sourceUrl: location); 411 pubspecNode = new YamlMap(sourceUrl: location);
282 } else if (pubspecNode is! YamlMap) { 412 } else if (pubspecNode is! YamlMap) {
283 throw new PubspecException( 413 throw new PubspecException(
284 'The pubspec must be a YAML mapping.', 414 'The pubspec must be a YAML mapping.',
285 pubspecNode.span); 415 pubspecNode.span);
286 } 416 }
417
287 return new Pubspec.fromMap( 418 return new Pubspec.fromMap(
288 pubspecNode, 419 pubspecNode,
289 sources, 420 sources,
290 expectedName: expectedName, 421 expectedName: expectedName,
291 location: location); 422 location: location);
292 } 423 }
424
425 /// Returns a list of most errors in this pubspec.
426 ///
427 /// This will return at most one error for each field.
293 List<PubspecException> get allErrors { 428 List<PubspecException> get allErrors {
294 var errors = <PubspecException>[]; 429 var errors = <PubspecException>[];
295 _getError(fn()) { 430 _getError(fn()) {
296 try { 431 try {
297 fn(); 432 fn();
298 } on PubspecException catch (e) { 433 } on PubspecException catch (e) {
299 errors.add(e); 434 errors.add(e);
300 } 435 }
301 } 436 }
437
302 _getError(() => this.name); 438 _getError(() => this.name);
303 _getError(() => this.version); 439 _getError(() => this.version);
304 _getError(() => this.dependencies); 440 _getError(() => this.dependencies);
305 _getError(() => this.devDependencies); 441 _getError(() => this.devDependencies);
306 _getError(() => this.transformers); 442 _getError(() => this.transformers);
307 _getError(() => this.environment); 443 _getError(() => this.environment);
308 _getError(() => this.publishTo); 444 _getError(() => this.publishTo);
309 return errors; 445 return errors;
310 } 446 }
447
448 /// Parses the dependency field named [field], and returns the corresponding
449 /// list of dependencies.
311 List<PackageDep> _parseDependencies(String field) { 450 List<PackageDep> _parseDependencies(String field) {
312 var dependencies = <PackageDep>[]; 451 var dependencies = <PackageDep>[];
452
313 var yaml = fields[field]; 453 var yaml = fields[field];
454 // Allow an empty dependencies key.
314 if (yaml == null) return dependencies; 455 if (yaml == null) return dependencies;
456
315 if (yaml is! Map) { 457 if (yaml is! Map) {
316 _error('"$field" field must be a map.', fields.nodes[field].span); 458 _error('"$field" field must be a map.', fields.nodes[field].span);
317 } 459 }
460
318 var nonStringNode = 461 var nonStringNode =
319 yaml.nodes.keys.firstWhere((e) => e.value is! String, orElse: () => null ); 462 yaml.nodes.keys.firstWhere((e) => e.value is! String, orElse: () => null );
320 if (nonStringNode != null) { 463 if (nonStringNode != null) {
321 _error('A dependency name must be a string.', nonStringNode.span); 464 _error('A dependency name must be a string.', nonStringNode.span);
322 } 465 }
466
323 yaml.nodes.forEach((nameNode, specNode) { 467 yaml.nodes.forEach((nameNode, specNode) {
324 var name = nameNode.value; 468 var name = nameNode.value;
325 var spec = specNode.value; 469 var spec = specNode.value;
326 if (fields['name'] != null && name == this.name) { 470 if (fields['name'] != null && name == this.name) {
327 _error('A package may not list itself as a dependency.', nameNode.span); 471 _error('A package may not list itself as a dependency.', nameNode.span);
328 } 472 }
473
329 var descriptionNode; 474 var descriptionNode;
330 var sourceName; 475 var sourceName;
476
331 var versionConstraint = new VersionRange(); 477 var versionConstraint = new VersionRange();
332 if (spec == null) { 478 if (spec == null) {
333 descriptionNode = nameNode; 479 descriptionNode = nameNode;
334 sourceName = _sources.defaultSource.name; 480 sourceName = _sources.defaultSource.name;
335 } else if (spec is String) { 481 } else if (spec is String) {
336 descriptionNode = nameNode; 482 descriptionNode = nameNode;
337 sourceName = _sources.defaultSource.name; 483 sourceName = _sources.defaultSource.name;
338 versionConstraint = _parseVersionConstraint(specNode); 484 versionConstraint = _parseVersionConstraint(specNode);
339 } else if (spec is Map) { 485 } else if (spec is Map) {
486 // Don't write to the immutable YAML map.
340 spec = new Map.from(spec); 487 spec = new Map.from(spec);
488
341 if (spec.containsKey('version')) { 489 if (spec.containsKey('version')) {
342 spec.remove('version'); 490 spec.remove('version');
343 versionConstraint = 491 versionConstraint =
344 _parseVersionConstraint(specNode.nodes['version']); 492 _parseVersionConstraint(specNode.nodes['version']);
345 } 493 }
494
346 var sourceNames = spec.keys.toList(); 495 var sourceNames = spec.keys.toList();
347 if (sourceNames.length > 1) { 496 if (sourceNames.length > 1) {
348 _error('A dependency may only have one source.', specNode.span); 497 _error('A dependency may only have one source.', specNode.span);
349 } 498 }
499
350 sourceName = sourceNames.single; 500 sourceName = sourceNames.single;
351 if (sourceName is! String) { 501 if (sourceName is! String) {
352 _error( 502 _error(
353 'A source name must be a string.', 503 'A source name must be a string.',
354 specNode.nodes.keys.single.span); 504 specNode.nodes.keys.single.span);
355 } 505 }
506
356 descriptionNode = specNode.nodes[sourceName]; 507 descriptionNode = specNode.nodes[sourceName];
357 } else { 508 } else {
358 _error( 509 _error(
359 'A dependency specification must be a string or a mapping.', 510 'A dependency specification must be a string or a mapping.',
360 specNode.span); 511 specNode.span);
361 } 512 }
513
514 // Let the source validate the description.
362 var description = 515 var description =
363 _wrapFormatException('description', descriptionNode.span, () { 516 _wrapFormatException('description', descriptionNode.span, () {
364 var pubspecPath; 517 var pubspecPath;
365 if (_location != null && _isFileUri(_location)) { 518 if (_location != null && _isFileUri(_location)) {
366 pubspecPath = path.fromUri(_location); 519 pubspecPath = path.fromUri(_location);
367 } 520 }
521
368 return _sources[sourceName].parseDescription( 522 return _sources[sourceName].parseDescription(
369 pubspecPath, 523 pubspecPath,
370 descriptionNode.value, 524 descriptionNode.value,
371 fromLockFile: false); 525 fromLockFile: false);
372 }); 526 });
527
373 dependencies.add( 528 dependencies.add(
374 new PackageDep(name, sourceName, versionConstraint, description)); 529 new PackageDep(name, sourceName, versionConstraint, description));
375 }); 530 });
531
376 return dependencies; 532 return dependencies;
377 } 533 }
534
535 /// Parses [node] to a [VersionConstraint].
378 VersionConstraint _parseVersionConstraint(YamlNode node) { 536 VersionConstraint _parseVersionConstraint(YamlNode node) {
379 if (node.value == null) return VersionConstraint.any; 537 if (node.value == null) return VersionConstraint.any;
380 if (node.value is! String) { 538 if (node.value is! String) {
381 _error('A version constraint must be a string.', node.span); 539 _error('A version constraint must be a string.', node.span);
382 } 540 }
541
383 return _wrapFormatException( 542 return _wrapFormatException(
384 'version constraint', 543 'version constraint',
385 node.span, 544 node.span,
386 () => new VersionConstraint.parse(node.value)); 545 () => new VersionConstraint.parse(node.value));
387 } 546 }
547
548 /// Makes sure the same package doesn't appear as both a regular and dev
549 /// dependency.
388 void _checkDependencyOverlap(List<PackageDep> dependencies, 550 void _checkDependencyOverlap(List<PackageDep> dependencies,
389 List<PackageDep> devDependencies) { 551 List<PackageDep> devDependencies) {
390 var dependencyNames = dependencies.map((dep) => dep.name).toSet(); 552 var dependencyNames = dependencies.map((dep) => dep.name).toSet();
391 var collisions = 553 var collisions =
392 dependencyNames.intersection(devDependencies.map((dep) => dep.name).toSe t()); 554 dependencyNames.intersection(devDependencies.map((dep) => dep.name).toSe t());
393 if (collisions.isEmpty) return; 555 if (collisions.isEmpty) return;
556
394 var span = fields["dependencies"].nodes.keys.firstWhere( 557 var span = fields["dependencies"].nodes.keys.firstWhere(
395 (key) => collisions.contains(key.value)).span; 558 (key) => collisions.contains(key.value)).span;
559
560 // TODO(nweiz): associate source range info with PackageDeps and use it
561 // here.
396 _error( 562 _error(
397 '${pluralize('Package', collisions.length)} ' 563 '${pluralize('Package', collisions.length)} '
398 '${toSentence(collisions.map((package) => '"$package"'))} cannot ' 564 '${toSentence(collisions.map((package) => '"$package"'))} cannot '
399 'appear in both "dependencies" and "dev_dependencies".', 565 'appear in both "dependencies" and "dev_dependencies".',
400 span); 566 span);
401 } 567 }
568
569 /// Runs [fn] and wraps any [FormatException] it throws in a
570 /// [PubspecException].
571 ///
572 /// [description] should be a noun phrase that describes whatever's being
573 /// parsed or processed by [fn]. [span] should be the location of whatever's
574 /// being processed within the pubspec.
402 _wrapFormatException(String description, SourceSpan span, fn()) { 575 _wrapFormatException(String description, SourceSpan span, fn()) {
403 try { 576 try {
404 return fn(); 577 return fn();
405 } on FormatException catch (e) { 578 } on FormatException catch (e) {
406 _error('Invalid $description: ${e.message}', span); 579 _error('Invalid $description: ${e.message}', span);
407 } 580 }
408 } 581 }
582
409 _wrapSpanFormatException(String description, fn()) { 583 _wrapSpanFormatException(String description, fn()) {
410 try { 584 try {
411 return fn(); 585 return fn();
412 } on SourceSpanFormatException catch (e) { 586 } on SourceSpanFormatException catch (e) {
413 _error('Invalid $description: ${e.message}', e.span); 587 _error('Invalid $description: ${e.message}', e.span);
414 } 588 }
415 } 589 }
590
591 /// Throws a [PubspecException] with the given message.
416 void _error(String message, SourceSpan span) { 592 void _error(String message, SourceSpan span) {
417 var name; 593 var name;
418 try { 594 try {
419 name = this.name; 595 name = this.name;
420 } on PubspecException catch (_) {} 596 } on PubspecException catch (_) {
597 // [name] is null.
598 }
599
421 throw new PubspecException(message, span); 600 throw new PubspecException(message, span);
422 } 601 }
423 } 602 }
603
604 /// The environment-related metadata in the pubspec.
605 ///
606 /// Corresponds to the data under the "environment:" key in the pubspec.
424 class PubspecEnvironment { 607 class PubspecEnvironment {
608 /// The version constraint specifying which SDK versions this package works
609 /// with.
425 final VersionConstraint sdkVersion; 610 final VersionConstraint sdkVersion;
611
426 PubspecEnvironment([VersionConstraint sdk]) 612 PubspecEnvironment([VersionConstraint sdk])
427 : sdkVersion = sdk != null ? sdk : VersionConstraint.any; 613 : sdkVersion = sdk != null ? sdk : VersionConstraint.any;
428 } 614 }
615
616 /// An exception thrown when parsing a pubspec.
617 ///
618 /// These exceptions are often thrown lazily while accessing pubspec properties.
429 class PubspecException extends SourceSpanFormatException implements 619 class PubspecException extends SourceSpanFormatException implements
430 ApplicationException { 620 ApplicationException {
431 PubspecException(String message, SourceSpan span) : super(message, span); 621 PubspecException(String message, SourceSpan span)
622 : super(message, span);
432 } 623 }
624
625 /// Returns whether [uri] is a file URI.
626 ///
627 /// This is slightly more complicated than just checking if the scheme is
628 /// 'file', since relative URIs also refer to the filesystem on the VM.
433 bool _isFileUri(Uri uri) => uri.scheme == 'file' || uri.scheme == ''; 629 bool _isFileUri(Uri uri) => uri.scheme == 'file' || uri.scheme == '';
OLDNEW
« no previous file with comments | « sdk/lib/_internal/pub_generated/lib/src/progress.dart ('k') | sdk/lib/_internal/pub_generated/lib/src/sdk.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698