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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/pub_generated/lib/src/pubspec.dart
diff --git a/sdk/lib/_internal/pub_generated/lib/src/pubspec.dart b/sdk/lib/_internal/pub_generated/lib/src/pubspec.dart
index d3dd3b82657ccdb0766c3c17c85521a460caa2eb..8fb27db00dbbb7295abc6f678224ee75cdacc425 100644
--- a/sdk/lib/_internal/pub_generated/lib/src/pubspec.dart
+++ b/sdk/lib/_internal/pub_generated/lib/src/pubspec.dart
@@ -1,20 +1,54 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
library pub.pubspec;
+
import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart';
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';
+
import 'barback/transformer_config.dart';
import 'exceptions.dart';
import 'io.dart';
import 'package.dart';
import 'source_registry.dart';
import 'utils.dart';
+
+/// The parsed contents of a pubspec file.
+///
+/// The fields of a pubspec are, for the most part, validated when they're first
+/// accessed. This allows a partially-invalid pubspec to be used if only the
+/// valid portions are relevant. To get a list of all errors in the pubspec, use
+/// [allErrors].
class Pubspec {
+ // If a new lazily-initialized field is added to this class and the
+ // initialization can throw a [PubspecException], that error should also be
+ // exposed through [allErrors].
+
+ /// The registry of sources to use when parsing [dependencies] and
+ /// [devDependencies].
+ ///
+ /// This will be null if this was created using [new Pubspec] or [new
+ /// Pubspec.empty].
final SourceRegistry _sources;
+
+ /// The location from which the pubspec was loaded.
+ ///
+ /// This can be null if the pubspec was created in-memory or if its location
+ /// is unknown.
Uri get _location => fields.span.sourceUrl;
+
+ /// All pubspec fields.
+ ///
+ /// This includes the fields from which other properties are derived.
final YamlMap fields;
+
+ /// The package's name.
String get name {
if (_name != null) return _name;
+
var name = fields['name'];
if (name == null) {
throw new PubspecException(
@@ -25,34 +59,44 @@ class Pubspec {
'"name" field must be a string.',
fields.nodes['name'].span);
}
+
_name = name;
return _name;
}
String _name;
+
+ /// The package's version.
Version get version {
if (_version != null) return _version;
+
var version = fields['version'];
if (version == null) {
_version = Version.none;
return _version;
}
+
var span = fields.nodes['version'].span;
if (version is num) {
var fixed = '$version.0';
if (version is int) {
fixed = '$fixed.0';
}
- _error('"version" field must have three numeric components: major, '
- 'minor, and patch. Instead of "$version", consider "$fixed".', span);
+ _error(
+ '"version" field must have three numeric components: major, '
+ 'minor, and patch. Instead of "$version", consider "$fixed".',
+ span);
}
if (version is! String) {
_error('"version" field must be a string.', span);
}
+
_version =
_wrapFormatException('version number', span, () => new Version.parse(version));
return _version;
}
Version _version;
+
+ /// The additional packages this package depends on.
List<PackageDep> get dependencies {
if (_dependencies != null) return _dependencies;
_dependencies = _parseDependencies('dependencies');
@@ -62,6 +106,8 @@ class Pubspec {
return _dependencies;
}
List<PackageDep> _dependencies;
+
+ /// The packages this package depends on when it is the root package.
List<PackageDep> get devDependencies {
if (_devDependencies != null) return _devDependencies;
_devDependencies = _parseDependencies('dev_dependencies');
@@ -71,24 +117,35 @@ class Pubspec {
return _devDependencies;
}
List<PackageDep> _devDependencies;
+
+ /// The dependency constraints that this package overrides when it is the
+ /// root package.
+ ///
+ /// Dependencies here will replace any dependency on a package with the same
+ /// name anywhere in the dependency graph.
List<PackageDep> get dependencyOverrides {
if (_dependencyOverrides != null) return _dependencyOverrides;
_dependencyOverrides = _parseDependencies('dependency_overrides');
return _dependencyOverrides;
}
List<PackageDep> _dependencyOverrides;
+
+ /// The configurations of the transformers to use for this package.
List<Set<TransformerConfig>> get transformers {
if (_transformers != null) return _transformers;
+
var transformers = fields['transformers'];
if (transformers == null) {
_transformers = [];
return _transformers;
}
+
if (transformers is! List) {
_error(
'"transformers" field must be a list.',
fields.nodes['transformers'].span);
}
+
var i = 0;
_transformers = transformers.nodes.map((phase) {
var phaseNodes = phase is YamlList ? phase.nodes : [phase];
@@ -99,6 +156,7 @@ class Pubspec {
'A transformer must be a string or map.',
transformerNode.span);
}
+
var libraryNode;
var configurationNode;
if (transformer is String) {
@@ -113,6 +171,7 @@ class Pubspec {
'A transformer identifier must be a string.',
transformer.nodes.keys.single.span);
}
+
libraryNode = transformer.nodes.keys.single;
configurationNode = transformer.nodes.values.single;
if (configurationNode is! YamlMap) {
@@ -121,12 +180,14 @@ class Pubspec {
configurationNode.span);
}
}
+
var config = _wrapSpanFormatException('transformer config', () {
return new TransformerConfig.parse(
libraryNode.value,
libraryNode.span,
configurationNode);
});
+
var package = config.id.package;
if (package != name &&
!config.id.isBuiltInTransformer &&
@@ -135,37 +196,54 @@ class Pubspec {
!dependencyOverrides.any((ref) => ref.name == package)) {
_error('"$package" is not a dependency.', libraryNode.span);
}
+
return config;
}).toSet();
}).toList();
+
return _transformers;
}
List<Set<TransformerConfig>> _transformers;
+
+ /// The environment-related metadata.
PubspecEnvironment get environment {
if (_environment != null) return _environment;
+
var yaml = fields['environment'];
if (yaml == null) {
_environment = new PubspecEnvironment(VersionConstraint.any);
return _environment;
}
+
if (yaml is! Map) {
_error(
'"environment" field must be a map.',
fields.nodes['environment'].span);
}
+
_environment =
new PubspecEnvironment(_parseVersionConstraint(yaml.nodes['sdk']));
return _environment;
}
PubspecEnvironment _environment;
+
+ /// The URL of the server that the package should default to being published
+ /// to, "none" if the package should not be published, or `null` if it should
+ /// be published to the default server.
+ ///
+ /// If this does return a URL string, it will be a valid parseable URL.
String get publishTo {
if (_parsedPublishTo) return _publishTo;
+
var publishTo = fields['publish_to'];
if (publishTo != null) {
var span = fields.nodes['publish_to'].span;
+
if (publishTo is! String) {
_error('"publish_to" field must be a string.', span);
}
+
+ // It must be "none" or a valid URL.
if (publishTo != "none") {
_wrapFormatException(
'"publish_to" field',
@@ -173,27 +251,45 @@ class Pubspec {
() => Uri.parse(publishTo));
}
}
+
_parsedPublishTo = true;
_publishTo = publishTo;
return _publishTo;
}
bool _parsedPublishTo = false;
String _publishTo;
+
+ /// The executables that should be placed on the user's PATH when this
+ /// package is globally activated.
+ ///
+ /// It is a map of strings to string. Each key is the name of the command
+ /// that will be placed on the user's PATH. The value is the name of the
+ /// .dart script (without extension) in the package's `bin` directory that
+ /// should be run for that command. Both key and value must be "simple"
+ /// strings: alphanumerics, underscores and hypens only. If a value is
+ /// omitted, it is inferred to use the same name as the key.
Map<String, String> get executables {
if (_executables != null) return _executables;
+
_executables = {};
var yaml = fields['executables'];
if (yaml == null) return _executables;
+
if (yaml is! Map) {
_error(
'"executables" field must be a map.',
fields.nodes['executables'].span);
}
+
yaml.nodes.forEach((key, value) {
- validateName(name, description) {}
+ // Don't allow path separators or other stuff meaningful to the shell.
+ validateName(name, description) {
+ }
+
if (key.value is! String) {
_error('"executables" keys must be strings.', key.span);
}
+
final keyPattern = new RegExp(r"^[a-zA-Z0-9_-]+$");
if (!keyPattern.hasMatch(key.value)) {
_error(
@@ -201,25 +297,40 @@ class Pubspec {
'numbers, hyphens and underscores.',
key.span);
}
+
if (value.value == null) {
value = key;
} else if (value.value is! String) {
_error('"executables" values must be strings or null.', value.span);
}
+
final valuePattern = new RegExp(r"[/\\]");
if (valuePattern.hasMatch(value.value)) {
_error(
'"executables" values may not contain path separators.',
value.span);
}
+
_executables[key.value] = value.value;
});
+
return _executables;
}
Map<String, String> _executables;
+
+ /// Whether the package is private and cannot be published.
+ ///
+ /// This is specified in the pubspec by setting "publish_to" to "none".
bool get isPrivate => publishTo == "none";
+
+ /// Whether or not the pubspec has no contents.
bool get isEmpty =>
name == null && version == Version.none && dependencies.isEmpty;
+
+ /// Loads the pubspec for a package located in [packageDir].
+ ///
+ /// If [expectedName] is passed and the pubspec doesn't have a matching name
+ /// field, this will throw a [PubspecError].
factory Pubspec.load(String packageDir, SourceRegistry sources,
{String expectedName}) {
var pubspecPath = path.join(packageDir, 'pubspec.yaml');
@@ -229,12 +340,14 @@ class Pubspec {
'Could not find a file named "pubspec.yaml" in "$packageDir".',
pubspecPath);
}
+
return new Pubspec.parse(
readTextFile(pubspecPath),
sources,
expectedName: expectedName,
location: pubspecUri);
}
+
Pubspec(this._name, {Version version, Iterable<PackageDep> dependencies,
Iterable<PackageDep> devDependencies, Iterable<PackageDep> dependencyOverrides,
VersionConstraint sdkConstraint,
@@ -254,6 +367,7 @@ class Pubspec {
transformers.map((phase) => phase.toSet()).toList(),
fields = fields == null ? new YamlMap() : new YamlMap.wrap(fields),
_sources = sources;
+
Pubspec.empty()
: _sources = null,
_name = null,
@@ -263,17 +377,33 @@ class Pubspec {
_environment = new PubspecEnvironment(),
_transformers = <Set<TransformerConfig>>[],
fields = new YamlMap();
+
+ /// Returns a Pubspec object for an already-parsed map representing its
+ /// contents.
+ ///
+ /// If [expectedName] is passed and the pubspec doesn't have a matching name
+ /// field, this will throw a [PubspecError].
+ ///
+ /// [location] is the location from which this pubspec was loaded.
Pubspec.fromMap(Map fields, this._sources, {String expectedName,
Uri location})
: fields = fields is YamlMap ?
fields :
new YamlMap.wrap(fields, sourceUrl: location) {
+ // If [expectedName] is passed, ensure that the actual 'name' field exists
+ // and matches the expectation.
if (expectedName == null) return;
if (name == expectedName) return;
+
throw new PubspecException(
'"name" field doesn\'t match expected name ' '"$expectedName".',
this.fields.nodes["name"].span);
}
+
+ /// Parses the pubspec stored at [filePath] whose text is [contents].
+ ///
+ /// If the pubspec doesn't define a version for itself, it defaults to
+ /// [Version.none].
factory Pubspec.parse(String contents, SourceRegistry sources,
{String expectedName, Uri location}) {
var pubspecNode = loadYamlNode(contents, sourceUrl: location);
@@ -284,12 +414,17 @@ class Pubspec {
'The pubspec must be a YAML mapping.',
pubspecNode.span);
}
+
return new Pubspec.fromMap(
pubspecNode,
sources,
expectedName: expectedName,
location: location);
}
+
+ /// Returns a list of most errors in this pubspec.
+ ///
+ /// This will return at most one error for each field.
List<PubspecException> get allErrors {
var errors = <PubspecException>[];
_getError(fn()) {
@@ -299,6 +434,7 @@ class Pubspec {
errors.add(e);
}
}
+
_getError(() => this.name);
_getError(() => this.version);
_getError(() => this.dependencies);
@@ -308,26 +444,36 @@ class Pubspec {
_getError(() => this.publishTo);
return errors;
}
+
+ /// Parses the dependency field named [field], and returns the corresponding
+ /// list of dependencies.
List<PackageDep> _parseDependencies(String field) {
var dependencies = <PackageDep>[];
+
var yaml = fields[field];
+ // Allow an empty dependencies key.
if (yaml == null) return dependencies;
+
if (yaml is! Map) {
_error('"$field" field must be a map.', fields.nodes[field].span);
}
+
var nonStringNode =
yaml.nodes.keys.firstWhere((e) => e.value is! String, orElse: () => null);
if (nonStringNode != null) {
_error('A dependency name must be a string.', nonStringNode.span);
}
+
yaml.nodes.forEach((nameNode, specNode) {
var name = nameNode.value;
var spec = specNode.value;
if (fields['name'] != null && name == this.name) {
_error('A package may not list itself as a dependency.', nameNode.span);
}
+
var descriptionNode;
var sourceName;
+
var versionConstraint = new VersionRange();
if (spec == null) {
descriptionNode = nameNode;
@@ -337,68 +483,95 @@ class Pubspec {
sourceName = _sources.defaultSource.name;
versionConstraint = _parseVersionConstraint(specNode);
} else if (spec is Map) {
+ // Don't write to the immutable YAML map.
spec = new Map.from(spec);
+
if (spec.containsKey('version')) {
spec.remove('version');
versionConstraint =
_parseVersionConstraint(specNode.nodes['version']);
}
+
var sourceNames = spec.keys.toList();
if (sourceNames.length > 1) {
_error('A dependency may only have one source.', specNode.span);
}
+
sourceName = sourceNames.single;
if (sourceName is! String) {
_error(
'A source name must be a string.',
specNode.nodes.keys.single.span);
}
+
descriptionNode = specNode.nodes[sourceName];
} else {
_error(
'A dependency specification must be a string or a mapping.',
specNode.span);
}
+
+ // Let the source validate the description.
var description =
_wrapFormatException('description', descriptionNode.span, () {
var pubspecPath;
if (_location != null && _isFileUri(_location)) {
pubspecPath = path.fromUri(_location);
}
+
return _sources[sourceName].parseDescription(
pubspecPath,
descriptionNode.value,
fromLockFile: false);
});
+
dependencies.add(
new PackageDep(name, sourceName, versionConstraint, description));
});
+
return dependencies;
}
+
+ /// Parses [node] to a [VersionConstraint].
VersionConstraint _parseVersionConstraint(YamlNode node) {
if (node.value == null) return VersionConstraint.any;
if (node.value is! String) {
_error('A version constraint must be a string.', node.span);
}
+
return _wrapFormatException(
'version constraint',
node.span,
() => new VersionConstraint.parse(node.value));
}
+
+ /// Makes sure the same package doesn't appear as both a regular and dev
+ /// dependency.
void _checkDependencyOverlap(List<PackageDep> dependencies,
List<PackageDep> devDependencies) {
var dependencyNames = dependencies.map((dep) => dep.name).toSet();
var collisions =
dependencyNames.intersection(devDependencies.map((dep) => dep.name).toSet());
if (collisions.isEmpty) return;
+
var span = fields["dependencies"].nodes.keys.firstWhere(
(key) => collisions.contains(key.value)).span;
+
+ // TODO(nweiz): associate source range info with PackageDeps and use it
+ // here.
_error(
'${pluralize('Package', collisions.length)} '
'${toSentence(collisions.map((package) => '"$package"'))} cannot '
'appear in both "dependencies" and "dev_dependencies".',
span);
}
+
+ /// Runs [fn] and wraps any [FormatException] it throws in a
+ /// [PubspecException].
+ ///
+ /// [description] should be a noun phrase that describes whatever's being
+ /// parsed or processed by [fn]. [span] should be the location of whatever's
+ /// being processed within the pubspec.
_wrapFormatException(String description, SourceSpan span, fn()) {
try {
return fn();
@@ -406,6 +579,7 @@ class Pubspec {
_error('Invalid $description: ${e.message}', span);
}
}
+
_wrapSpanFormatException(String description, fn()) {
try {
return fn();
@@ -413,21 +587,43 @@ class Pubspec {
_error('Invalid $description: ${e.message}', e.span);
}
}
+
+ /// Throws a [PubspecException] with the given message.
void _error(String message, SourceSpan span) {
var name;
try {
name = this.name;
- } on PubspecException catch (_) {}
+ } on PubspecException catch (_) {
+ // [name] is null.
+ }
+
throw new PubspecException(message, span);
}
}
+
+/// The environment-related metadata in the pubspec.
+///
+/// Corresponds to the data under the "environment:" key in the pubspec.
class PubspecEnvironment {
+ /// The version constraint specifying which SDK versions this package works
+ /// with.
final VersionConstraint sdkVersion;
+
PubspecEnvironment([VersionConstraint sdk])
: sdkVersion = sdk != null ? sdk : VersionConstraint.any;
}
+
+/// An exception thrown when parsing a pubspec.
+///
+/// These exceptions are often thrown lazily while accessing pubspec properties.
class PubspecException extends SourceSpanFormatException implements
ApplicationException {
- PubspecException(String message, SourceSpan span) : super(message, span);
+ PubspecException(String message, SourceSpan span)
+ : super(message, span);
}
+
+/// Returns whether [uri] is a file URI.
+///
+/// This is slightly more complicated than just checking if the scheme is
+/// 'file', since relative URIs also refer to the filesystem on the VM.
bool _isFileUri(Uri uri) => uri.scheme == 'file' || uri.scheme == '';
« 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