From 0dcfcab21596cbe527e4348dcfa8856bdc61b7e2 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" Date: Sat, 26 Jan 2013 02:25:43 +0000 Subject: [PATCH 001/179] Restructure YAML package suitable for pub lish After this I can use tools/publish_pkg.py upload script to fix dartbug.com/4126 Review URL: https://codereview.chromium.org//11622011 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@17685 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/README.md | 24 + pkgs/yaml/lib/composer.dart | 173 +++ pkgs/yaml/lib/constructor.dart | 56 + pkgs/yaml/lib/deep_equals.dart | 72 ++ pkgs/yaml/lib/model.dart | 234 ++++ pkgs/yaml/lib/parser.dart | 1939 ++++++++++++++++++++++++++++++++ pkgs/yaml/lib/visitor.dart | 27 + pkgs/yaml/lib/yaml.dart | 75 ++ pkgs/yaml/lib/yaml_map.dart | 110 ++ pkgs/yaml/pubspec.yaml | 7 + pkgs/yaml/test/yaml_test.dart | 1879 +++++++++++++++++++++++++++++++ 11 files changed, 4596 insertions(+) create mode 100644 pkgs/yaml/README.md create mode 100644 pkgs/yaml/lib/composer.dart create mode 100644 pkgs/yaml/lib/constructor.dart create mode 100644 pkgs/yaml/lib/deep_equals.dart create mode 100644 pkgs/yaml/lib/model.dart create mode 100644 pkgs/yaml/lib/parser.dart create mode 100644 pkgs/yaml/lib/visitor.dart create mode 100644 pkgs/yaml/lib/yaml.dart create mode 100644 pkgs/yaml/lib/yaml_map.dart create mode 100644 pkgs/yaml/pubspec.yaml create mode 100644 pkgs/yaml/test/yaml_test.dart diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md new file mode 100644 index 000000000..ad7678fc8 --- /dev/null +++ b/pkgs/yaml/README.md @@ -0,0 +1,24 @@ +A parser for [YAML](http://www.yaml.org/). + +Use `loadYaml` to load a single document, or `loadYamlStream` to load a +stream of documents. For example: + + import 'package:yaml/yaml.dart'; + main() { + var doc = loadYaml("YAML: YAML Ain't Markup Language"); + print(doc['YAML']); + } + +This library currently doesn't support dumping to YAML. You should use +`stringify` from `dart:json` instead: + + import 'dart:json' as json; + import 'package:yaml/yaml.dart'; + main() { + var doc = loadYaml("YAML: YAML Ain't Markup Language"); + print(json.stringify(doc)); + } + +The source code for this package is at . +Please file issues at . Other questions or comments can be +directed to the Dart mailing list at . diff --git a/pkgs/yaml/lib/composer.dart b/pkgs/yaml/lib/composer.dart new file mode 100644 index 000000000..e9c187969 --- /dev/null +++ b/pkgs/yaml/lib/composer.dart @@ -0,0 +1,173 @@ +// 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. + +part of yaml; + +/// Takes a parsed YAML document (what the spec calls the "serialization tree") +/// and resolves aliases, resolves tags, and parses scalars to produce the +/// "representation graph". +class _Composer extends _Visitor { + /// The root node of the serialization tree. + _Node root; + + /// Map from anchor names to the most recent representation graph node with + /// that anchor. + Map anchors; + + /// The next id to use for the represenation graph's anchors. The spec doesn't + /// use anchors in the representation graph, but we do so that the constructor + /// can ensure that the same node in the representation graph produces the + /// same native object. + int idCounter; + + _Composer(this.root) : this.anchors = {}, this.idCounter = 0; + + /// Runs the Composer to produce a representation graph. + _Node compose() => root.visit(this); + + /// Returns the anchor to which an alias node refers. + _Node visitAlias(_AliasNode alias) { + if (!anchors.containsKey(alias.anchor)) { + throw new YamlException("no anchor for alias ${alias.anchor}"); + } + return anchors[alias.anchor]; + } + + /// Parses a scalar node according to its tag, or auto-detects the type if no + /// tag exists. Currently this only supports the YAML core type schema. + _Node visitScalar(_ScalarNode scalar) { + if (scalar.tag.name == "!") { + return setAnchor(scalar, parseString(scalar.content)); + } else if (scalar.tag.name == "?") { + for (var fn in [parseNull, parseBool, parseInt, parseFloat]) { + var result = fn(scalar.content); + if (result != null) return result; + } + return setAnchor(scalar, parseString(scalar.content)); + } + + // TODO(nweiz): support the full YAML type repository + var tagParsers = { + 'null': parseNull, 'bool': parseBool, 'int': parseInt, + 'float': parseFloat, 'str': parseString + }; + + for (var key in tagParsers.keys) { + if (scalar.tag.name != _Tag.yaml(key)) continue; + var result = tagParsers[key](scalar.content); + if (result != null) return setAnchor(scalar, result); + throw new YamlException('invalid literal for $key: "${scalar.content}"'); + } + + throw new YamlException('undefined tag: "${scalar.tag.name}"'); + } + + /// Assigns a tag to the sequence and recursively composes its contents. + _Node visitSequence(_SequenceNode seq) { + var tagName = seq.tag.name; + if (tagName != "!" && tagName != "?" && tagName != _Tag.yaml("seq")) { + throw new YamlException("invalid tag for sequence: ${tagName}"); + } + + var result = setAnchor(seq, new _SequenceNode(_Tag.yaml("seq"), null)); + result.content = super.visitSequence(seq); + return result; + } + + /// Assigns a tag to the mapping and recursively composes its contents. + _Node visitMapping(_MappingNode map) { + var tagName = map.tag.name; + if (tagName != "!" && tagName != "?" && tagName != _Tag.yaml("map")) { + throw new YamlException("invalid tag for mapping: ${tagName}"); + } + + var result = setAnchor(map, new _MappingNode(_Tag.yaml("map"), null)); + result.content = super.visitMapping(map); + return result; + } + + /// If the serialization tree node [anchored] has an anchor, records that + /// that anchor is pointing to the representation graph node [result]. + _Node setAnchor(_Node anchored, _Node result) { + if (anchored.anchor == null) return result; + result.anchor = '${idCounter++}'; + anchors[anchored.anchor] = result; + return result; + } + + /// Parses a null scalar. + _ScalarNode parseNull(String content) { + if (!new RegExp("^(null|Null|NULL|~|)\$").hasMatch(content)) return null; + return new _ScalarNode(_Tag.yaml("null"), value: null); + } + + /// Parses a boolean scalar. + _ScalarNode parseBool(String content) { + var match = new RegExp("^(?:(true|True|TRUE)|(false|False|FALSE))\$"). + firstMatch(content); + if (match == null) return null; + return new _ScalarNode(_Tag.yaml("bool"), value: match.group(1) != null); + } + + /// Parses an integer scalar. + _ScalarNode parseInt(String content) { + var match = new RegExp("^[-+]?[0-9]+\$").firstMatch(content); + if (match != null) { + return new _ScalarNode(_Tag.yaml("int"), + value: int.parse(match.group(0))); + } + + match = new RegExp("^0o([0-7]+)\$").firstMatch(content); + if (match != null) { + // TODO(nweiz): clean this up when Dart can parse an octal string + var n = 0; + for (var c in match.group(1).charCodes) { + n *= 8; + n += c - 48; + } + return new _ScalarNode(_Tag.yaml("int"), value: n); + } + + match = new RegExp("^0x[0-9a-fA-F]+\$").firstMatch(content); + if (match != null) { + return new _ScalarNode(_Tag.yaml("int"), + value: int.parse(match.group(0))); + } + + return null; + } + + /// Parses a floating-point scalar. + _ScalarNode parseFloat(String content) { + var match = new RegExp( + "^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?\$"). + firstMatch(content); + if (match != null) { + // YAML allows floats of the form "0.", but Dart does not. Fix up those + // floats by removing the trailing dot. + var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), ""); + return new _ScalarNode(_Tag.yaml("float"), + value: double.parse(matchStr)); + } + + match = new RegExp("^([+-]?)\.(inf|Inf|INF)\$").firstMatch(content); + if (match != null) { + var infinityStr = match.group(1) == "-" ? "-Infinity" : "Infinity"; + return new _ScalarNode(_Tag.yaml("float"), + value: double.parse(infinityStr)); + } + + match = new RegExp("^\.(nan|NaN|NAN)\$").firstMatch(content); + if (match != null) { + return new _ScalarNode(_Tag.yaml("float"), + value: double.parse("NaN")); + } + + return null; + } + + /// Parses a string scalar. + _ScalarNode parseString(String content) => + new _ScalarNode(_Tag.yaml("str"), value: content); +} diff --git a/pkgs/yaml/lib/constructor.dart b/pkgs/yaml/lib/constructor.dart new file mode 100644 index 000000000..73a62a86f --- /dev/null +++ b/pkgs/yaml/lib/constructor.dart @@ -0,0 +1,56 @@ +// 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. + +part of yaml; + +/// Takes a parsed and composed YAML document (what the spec calls the +/// "representation graph") and creates native Dart objects that represent that +/// document. +class _Constructor extends _Visitor { + /// The root node of the representation graph. + _Node root; + + /// Map from anchor names to the most recent Dart node with that anchor. + Map anchors; + + _Constructor(this.root) : this.anchors = {}; + + /// Runs the Constructor to produce a Dart object. + construct() => root.visit(this); + + /// Returns the value of a scalar. + visitScalar(_ScalarNode scalar) => scalar.value; + + /// Converts a sequence into a List of Dart objects. + visitSequence(_SequenceNode seq) { + var anchor = getAnchor(seq); + if (anchor != null) return anchor; + var dartSeq = setAnchor(seq, []); + dartSeq.addAll(super.visitSequence(seq)); + return dartSeq; + } + + /// Converts a mapping into a Map of Dart objects. + visitMapping(_MappingNode map) { + var anchor = getAnchor(map); + if (anchor != null) return anchor; + var dartMap = setAnchor(map, new YamlMap()); + super.visitMapping(map).forEach((k, v) { dartMap[k] = v; }); + return dartMap; + } + + /// Returns the Dart object that already represents [anchored], if such a + /// thing exists. + getAnchor(_Node anchored) { + if (anchored.anchor == null) return null; + if (anchors.containsKey(anchored.anchor)) return anchors[anchored.anchor]; + } + + /// Records that [value] is the Dart object representing [anchored]. + setAnchor(_Node anchored, value) { + if (anchored.anchor == null) return value; + anchors[anchored.anchor] = value; + return value; + } +} diff --git a/pkgs/yaml/lib/deep_equals.dart b/pkgs/yaml/lib/deep_equals.dart new file mode 100644 index 000000000..bce4aadf2 --- /dev/null +++ b/pkgs/yaml/lib/deep_equals.dart @@ -0,0 +1,72 @@ +// 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 deep_equals; + +/// Returns whether two objects are structurally equivalent. This considers NaN +/// values to be equivalent. It also handles self-referential structures. +bool deepEquals(obj1, obj2, [List parents1, List parents2]) { + if (identical(obj1, obj2)) return true; + if (parents1 == null) { + parents1 = []; + parents2 = []; + } + + // parents1 and parents2 are guaranteed to be the same size. + for (var i = 0; i < parents1.length; i++) { + var loop1 = identical(obj1, parents1[i]); + var loop2 = identical(obj2, parents2[i]); + // If both structures loop in the same place, they're equal at that point in + // the structure. If one loops and the other doesn't, they're not equal. + if (loop1 && loop2) return true; + if (loop1 || loop2) return false; + } + + parents1.add(obj1); + parents2.add(obj2); + try { + if (obj1 is List && obj2 is List) { + return _listEquals(obj1, obj2, parents1, parents2); + } else if (obj1 is Map && obj2 is Map) { + return _mapEquals(obj1, obj2, parents1, parents2); + } else if (obj1 is double && obj2 is double) { + return _doubleEquals(obj1, obj2); + } else { + return obj1 == obj2; + } + } finally { + parents1.removeLast(); + parents2.removeLast(); + } +} + +/// Returns whether [list1] and [list2] are structurally equal. +bool _listEquals(List list1, List list2, List parents1, List parents2) { + if (list1.length != list2.length) return false; + + for (var i = 0; i < list1.length; i++) { + if (!deepEquals(list1[i], list2[i], parents1, parents2)) return false; + } + + return true; +} + +/// Returns whether [map1] and [map2] are structurally equal. +bool _mapEquals(Map map1, Map map2, List parents1, List parents2) { + if (map1.length != map2.length) return false; + + for (var key in map1.keys) { + if (!map2.containsKey(key)) return false; + if (!deepEquals(map1[key], map2[key], parents1, parents2)) return false; + } + + return true; +} + +/// Returns whether two doubles are equivalent. This differs from `d1 == d2` in +/// that it considers NaN to be equal to itself. +bool _doubleEquals(double d1, double d2) { + if (d1.isNaN && d2.isNaN) return true; + return d1 == d2; +} diff --git a/pkgs/yaml/lib/model.dart b/pkgs/yaml/lib/model.dart new file mode 100644 index 000000000..8c111afe3 --- /dev/null +++ b/pkgs/yaml/lib/model.dart @@ -0,0 +1,234 @@ +// 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. + +part of yaml; + +// This file contains the node classes for the internal representations of YAML +// documents. These nodes are used for both the serialization tree and the +// representation graph. + +/// A tag that indicates the type of a YAML node. +class _Tag { + // TODO(nweiz): it would better match the semantics of the spec if there were + // a singleton instance of this class for each tag. + + static const SCALAR_KIND = 0; + static const SEQUENCE_KIND = 1; + static const MAPPING_KIND = 2; + + static const String YAML_URI_PREFIX = 'tag:yaml.org,2002:'; + + /// The name of the tag, either a URI or a local tag beginning with "!". + final String name; + + /// The kind of the tag: SCALAR_KIND, SEQUENCE_KIND, or MAPPING_KIND. + final int kind; + + _Tag(this.name, this.kind); + + _Tag.scalar(String name) : this(name, SCALAR_KIND); + _Tag.sequence(String name) : this(name, SEQUENCE_KIND); + _Tag.mapping(String name) : this(name, MAPPING_KIND); + + /// Returns the standard YAML tag URI for [type]. + static String yaml(String type) => "tag:yaml.org,2002:$type"; + + /// Two tags are equal if their URIs are equal. + operator ==(other) { + if (other is! _Tag) return false; + return name == other.name; + } + + String toString() { + if (name.startsWith(YAML_URI_PREFIX)) { + return '!!${name.substring(YAML_URI_PREFIX.length)}'; + } else { + return '!<$name>'; + } + } + + int get hashCode => name.hashCode; +} + +/// The abstract class for YAML nodes. +abstract class _Node { + /// Every YAML node has a tag that describes its type. + _Tag tag; + + /// Any YAML node can have an anchor associated with it. + String anchor; + + _Node(this.tag, [this.anchor]); + + bool operator ==(other) { + if (other is! _Node) return false; + return tag == other.tag; + } + + int get hashCode => _hashCode([tag, anchor]); + + visit(_Visitor v); +} + +/// A sequence node represents an ordered list of nodes. +class _SequenceNode extends _Node { + /// The nodes in the sequence. + List<_Node> content; + + _SequenceNode(String tagName, this.content) + : super(new _Tag.sequence(tagName)); + + /// Two sequences are equal if their tags and contents are equal. + bool operator ==(other) { + // Should be super != other; bug 2554 + if (!(super == other) || other is! _SequenceNode) return false; + if (content.length != other.content.length) return false; + for (var i = 0; i < content.length; i++) { + if (content[i] != other.content[i]) return false; + } + return true; + } + + String toString() => + '$tag [${Strings.join(content.mappedBy((e) => '$e'), ', ')}]'; + + int get hashCode => super.hashCode ^ _hashCode(content); + + visit(_Visitor v) => v.visitSequence(this); +} + +/// An alias node is a reference to an anchor. +class _AliasNode extends _Node { + _AliasNode(String anchor) : super(new _Tag.scalar(_Tag.yaml("str")), anchor); + + visit(_Visitor v) => v.visitAlias(this); +} + +/// A scalar node represents all YAML nodes that have a single value. +class _ScalarNode extends _Node { + /// The string value of the scalar node, if it was created by the parser. + final String _content; + + /// The Dart value of the scalar node, if it was created by the composer. + final value; + + /// Creates a new Scalar node. + /// + /// Exactly one of [content] and [value] should be specified. Content should + /// be specified for a newly-parsed scalar that hasn't yet been composed. + /// Value should be specified for a composed scalar, although `null` is a + /// valid value. + _ScalarNode(String tagName, {String content, this.value}) + : _content = content, + super(new _Tag.scalar(tagName)); + + /// Two scalars are equal if their string representations are equal. + bool operator ==(other) { + // Should be super != other; bug 2554 + if (!(super == other) || other is! _ScalarNode) return false; + return content == other.content; + } + + /// Returns the string representation of the scalar. After composition, this + /// is equal to the canonical serialization of the value of the scalar. + String get content => _content != null ? _content : canonicalContent; + + /// Returns the canonical serialization of the value of the scalar. If the + /// value isn't given, the result of this will be "null". + String get canonicalContent { + if (value == null || value is bool || value is int) return '$value'; + + if (value is num) { + // 20 is the maximum value for this argument, which we use since YAML + // doesn't specify a maximum. + return value.toStringAsExponential(20). + replaceFirst(new RegExp("0+e"), "e"); + } + + if (value is String) { + // TODO(nweiz): This could be faster if we used a RegExp to check for + // special characters and short-circuited if they didn't exist. + + var escapedValue = value.charCodes.mappedBy((c) { + switch (c) { + case _Parser.TAB: return "\\t"; + case _Parser.LF: return "\\n"; + case _Parser.CR: return "\\r"; + case _Parser.DOUBLE_QUOTE: return '\\"'; + case _Parser.NULL: return "\\0"; + case _Parser.BELL: return "\\a"; + case _Parser.BACKSPACE: return "\\b"; + case _Parser.VERTICAL_TAB: return "\\v"; + case _Parser.FORM_FEED: return "\\f"; + case _Parser.ESCAPE: return "\\e"; + case _Parser.BACKSLASH: return "\\\\"; + case _Parser.NEL: return "\\N"; + case _Parser.NBSP: return "\\_"; + case _Parser.LINE_SEPARATOR: return "\\L"; + case _Parser.PARAGRAPH_SEPARATOR: return "\\P"; + default: + if (c < 0x20 || (c >= 0x7f && c < 0x100)) { + return "\\x${zeroPad(c.toRadixString(16).toUpperCase(), 2)}"; + } else if (c >= 0x100 && c < 0x10000) { + return "\\u${zeroPad(c.toRadixString(16).toUpperCase(), 4)}"; + } else if (c >= 0x10000) { + return "\\u${zeroPad(c.toRadixString(16).toUpperCase(), 8)}"; + } else { + return new String.fromCharCodes([c]); + } + } + }); + return '"${Strings.join(escapedValue, '')}"'; + } + + throw new YamlException("unknown scalar value: $value"); + } + + String toString() => '$tag "$content"'; + + /// Left-pads [str] with zeros so that it's at least [length] characters + /// long. + String zeroPad(String str, int length) { + assert(length >= str.length); + var prefix = []; + prefix.insertRange(0, length - str.length, '0'); + return '${Strings.join(prefix, '')}$str'; + } + + int get hashCode => super.hashCode ^ content.hashCode; + + visit(_Visitor v) => v.visitScalar(this); +} + +/// A mapping node represents an unordered map of nodes to nodes. +class _MappingNode extends _Node { + /// The node map. + Map<_Node, _Node> content; + + _MappingNode(String tagName, this.content) + : super(new _Tag.mapping(tagName)); + + /// Two mappings are equal if their tags and contents are equal. + bool operator ==(other) { + // Should be super != other; bug 2554 + if (!(super == other) || other is! _MappingNode) return false; + if (content.length != other.content.length) return false; + for (var key in content.keys) { + if (!other.content.containsKey(key)) return false; + if (content[key] != other.content[key]) return false; + } + return true; + } + + String toString() { + var strContent = content.keys + .mappedBy((k) => '${k}: ${content[k]}') + .join(', '); + return '$tag {$strContent}'; + } + + int get hashCode => super.hashCode ^ _hashCode(content); + + visit(_Visitor v) => v.visitMapping(this); +} diff --git a/pkgs/yaml/lib/parser.dart b/pkgs/yaml/lib/parser.dart new file mode 100644 index 000000000..f2f255e76 --- /dev/null +++ b/pkgs/yaml/lib/parser.dart @@ -0,0 +1,1939 @@ +// 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. + +part of yaml; + +/// Translates a string of characters into a YAML serialization tree. +/// +/// This parser is designed to closely follow the spec. All productions in the +/// spec are numbered, and the corresponding methods in the parser have the same +/// numbers. This is certainly not the most efficient way of parsing YAML, but +/// it is the easiest to write and read in the context of the spec. +/// +/// Methods corresponding to productions are also named as in the spec, +/// translating the name of the method (although not the annotation characters) +/// into camel-case for dart style.. For example, the spec has a production +/// named `nb-ns-plain-in-line`, and the method implementing it is named +/// `nb_ns_plainInLine`. The exception to that rule is methods that just +/// recognize character classes; these are named `is*`. +class _Parser { + static const TAB = 0x9; + static const LF = 0xA; + static const CR = 0xD; + static const SP = 0x20; + static const TILDE = 0x7E; + static const NEL = 0x85; + static const PLUS = 0x2B; + static const HYPHEN = 0x2D; + static const QUESTION_MARK = 0x3F; + static const COLON = 0x3A; + static const COMMA = 0x2C; + static const LEFT_BRACKET = 0x5B; + static const RIGHT_BRACKET = 0x5D; + static const LEFT_BRACE = 0x7B; + static const RIGHT_BRACE = 0x7D; + static const HASH = 0x23; + static const AMPERSAND = 0x26; + static const ASTERISK = 0x2A; + static const EXCLAMATION = 0x21; + static const VERTICAL_BAR = 0x7C; + static const GREATER_THAN = 0x3E; + static const SINGLE_QUOTE = 0x27; + static const DOUBLE_QUOTE = 0x22; + static const PERCENT = 0x25; + static const AT = 0x40; + static const GRAVE_ACCENT = 0x60; + + static const NULL = 0x0; + static const BELL = 0x7; + static const BACKSPACE = 0x8; + static const VERTICAL_TAB = 0xB; + static const FORM_FEED = 0xC; + static const ESCAPE = 0x1B; + static const SLASH = 0x2F; + static const BACKSLASH = 0x5C; + static const UNDERSCORE = 0x5F; + static const NBSP = 0xA0; + static const LINE_SEPARATOR = 0x2028; + static const PARAGRAPH_SEPARATOR = 0x2029; + + static const NUMBER_0 = 0x30; + static const NUMBER_9 = 0x39; + + static const LETTER_A = 0x61; + static const LETTER_B = 0x62; + static const LETTER_E = 0x65; + static const LETTER_F = 0x66; + static const LETTER_N = 0x6E; + static const LETTER_R = 0x72; + static const LETTER_T = 0x74; + static const LETTER_U = 0x75; + static const LETTER_V = 0x76; + static const LETTER_X = 0x78; + + static const LETTER_CAP_A = 0x41; + static const LETTER_CAP_F = 0x46; + static const LETTER_CAP_L = 0x4C; + static const LETTER_CAP_N = 0x4E; + static const LETTER_CAP_P = 0x50; + static const LETTER_CAP_U = 0x55; + static const LETTER_CAP_X = 0x58; + + static const C_SEQUENCE_ENTRY = 4; + static const C_MAPPING_KEY = 5; + static const C_MAPPING_VALUE = 6; + static const C_COLLECT_ENTRY = 7; + static const C_SEQUENCE_START = 8; + static const C_SEQUENCE_END = 9; + static const C_MAPPING_START = 10; + static const C_MAPPING_END = 11; + static const C_COMMENT = 12; + static const C_ANCHOR = 13; + static const C_ALIAS = 14; + static const C_TAG = 15; + static const C_LITERAL = 16; + static const C_FOLDED = 17; + static const C_SINGLE_QUOTE = 18; + static const C_DOUBLE_QUOTE = 19; + static const C_DIRECTIVE = 20; + static const C_RESERVED = 21; + + static const BLOCK_OUT = 0; + static const BLOCK_IN = 1; + static const FLOW_OUT = 2; + static const FLOW_IN = 3; + static const BLOCK_KEY = 4; + static const FLOW_KEY = 5; + + static const CHOMPING_STRIP = 0; + static const CHOMPING_KEEP = 1; + static const CHOMPING_CLIP = 2; + + /// The source string being parsed. + final String s; + + /// The current position in the source string. + int pos = 0; + + /// The length of the string being parsed. + final int len; + + /// The current (0-based) line in the source string. + int line = 0; + + /// The current (0-based) column in the source string. + int column = 0; + + /// Whether we're parsing a bare document (that is, one that doesn't begin + /// with `---`). Bare documents don't allow `%` immediately following + /// newlines. + bool inBareDocument = false; + + /// The line number of the farthest position that has been parsed successfully + /// before backtracking. Used for error reporting. + int farthestLine = 0; + + /// The column number of the farthest position that has been parsed + /// successfully before backtracking. Used for error reporting. + int farthestColumn = 0; + + /// The farthest position in the source string that has been parsed + /// successfully before backtracking. Used for error reporting. + int farthestPos = 0; + + /// The name of the context of the farthest position that has been parsed + /// successfully before backtracking. Used for error reporting. + String farthestContext = "document"; + + /// A stack of the names of parse contexts. Used for error reporting. + List contextStack; + + /// Annotations attached to ranges of the source string that add extra + /// information to any errors that occur in the annotated range. + _RangeMap errorAnnotations; + + /// The buffer containing the string currently being captured. + StringBuffer capturedString; + + /// The beginning of the current section of the captured string. + int captureStart; + + /// Whether the current string capture is being overridden. + bool capturingAs = false; + + _Parser(String s) + : this.s = s, + len = s.length, + contextStack = ["document"], + errorAnnotations = new _RangeMap(); + + /// Return the character at the current position, then move that position + /// forward one character. Also updates the current line and column numbers. + int next() { + if (pos == len) return -1; + var char = s.charCodeAt(pos++); + if (isBreak(char)) { + line++; + column = 0; + } else { + column++; + } + + if (farthestLine < line) { + farthestLine = line; + farthestColumn = column; + farthestContext = contextStack.last; + } else if (farthestLine == line && farthestColumn < column) { + farthestColumn = column; + farthestContext = contextStack.last; + } + farthestPos = pos; + + return char; + } + + /// Returns the character at the current position, or the character [i] + /// characters after the current position. + /// + /// Returns -1 if this would return a character after the end or before the + /// beginning of the input string. + int peek([int i = 0]) { + var peekPos = pos + i; + return (peekPos >= len || peekPos < 0) ? -1 : s.charCodeAt(peekPos); + } + + /// The truthiness operator. Returns `false` if [obj] is `null` or `false`, + /// `true` otherwise. + bool truth(obj) => obj != null && obj != false; + + /// Consumes the current character if it matches [matcher]. Returns the result + /// of [matcher]. + bool consume(bool matcher(int)) { + if (matcher(peek())) { + next(); + return true; + } + return false; + } + + /// Consumes the current character if it equals [char]. + bool consumeChar(int char) => consume((c) => c == char); + + /// Calls [consumer] until it returns a falsey value. Returns a list of all + /// truthy return values of [consumer], or null if it didn't consume anything. + /// + /// Conceptually, repeats a production one or more times. + List oneOrMore(consumer()) { + var first = consumer(); + if (!truth(first)) return null; + var out = [first]; + while (true) { + var el = consumer(); + if (!truth(el)) return out; + out.add(el); + } + return null; // Unreachable. + } + + /// Calls [consumer] until it returns a falsey value. Returns a list of all + /// truthy return values of [consumer], or the empty list if it didn't consume + /// anything. + /// + /// Conceptually, repeats a production any number of times. + List zeroOrMore(consumer()) { + var out = []; + var oldPos = pos; + while (true) { + var el = consumer(); + if (!truth(el) || oldPos == pos) return out; + oldPos = pos; + out.add(el); + } + return null; // Unreachable. + } + + /// Just calls [consumer] and returns its result. Used to make it explicit + /// that a production is intended to be optional. + zeroOrOne(consumer()) => consumer(); + + /// Calls each function in [consumers] until one returns a truthy value, then + /// returns that. + or(List consumers) { + for (var c in consumers) { + var res = c(); + if (truth(res)) return res; + } + return null; + } + + /// Calls [consumer] and returns its result, but rolls back the parser state + /// if [consumer] returns a falsey value. + transaction(consumer()) { + var oldPos = pos; + var oldLine = line; + var oldColumn = column; + var oldCaptureStart = captureStart; + String capturedSoFar = capturedString == null ? null : + capturedString.toString(); + var res = consumer(); + if (truth(res)) return res; + + pos = oldPos; + line = oldLine; + column = oldColumn; + captureStart = oldCaptureStart; + capturedString = capturedSoFar == null ? null : + new StringBuffer(capturedSoFar); + return res; + } + + /// Consumes [n] characters matching [matcher], or none if there isn't a + /// complete match. The first argument to [matcher] is the character code, the + /// second is the index (from 0 to [n] - 1). + /// + /// Returns whether or not the characters were consumed. + bool nAtOnce(int n, bool matcher(int c, int i)) => transaction(() { + for (int i = 0; i < n; i++) { + if (!consume((c) => matcher(c, i))) return false; + } + return true; + }); + + /// Consumes the exact characters in [str], or nothing. + /// + /// Returns whether or not the string was consumed. + bool rawString(String str) => + nAtOnce(str.length, (c, i) => str.charCodeAt(i) == c); + + /// Consumes and returns a string of characters matching [matcher], or null if + /// there are no such characters. + String stringOf(bool matcher(int)) => + captureString(() => oneOrMore(() => consume(matcher))); + + /// Calls [consumer] and returns the string that was consumed while doing so, + /// or null if [consumer] returned a falsey value. Automatically wraps + /// [consumer] in `transaction`. + String captureString(consumer()) { + // captureString calls may not be nested + assert(capturedString == null); + + captureStart = pos; + capturedString = new StringBuffer(); + var res = transaction(consumer); + if (!truth(res)) { + captureStart = null; + capturedString = null; + return null; + } + + flushCapture(); + var result = capturedString.toString(); + captureStart = null; + capturedString = null; + return result; + } + + captureAs(String replacement, consumer()) => + captureAndTransform(consumer, (_) => replacement); + + captureAndTransform(consumer(), String transformation(String captured)) { + if (capturedString == null) return consumer(); + if (capturingAs) return consumer(); + + flushCapture(); + capturingAs = true; + var res = consumer(); + capturingAs = false; + if (!truth(res)) return res; + + capturedString.add(transformation(s.substring(captureStart, pos))); + captureStart = pos; + return res; + } + + void flushCapture() { + capturedString.add(s.substring(captureStart, pos)); + captureStart = pos; + } + + /// Adds a tag and an anchor to [node], if they're defined. + _Node addProps(_Node node, _Pair<_Tag, String> props) { + if (props == null || node == null) return node; + if (truth(props.first)) node.tag = props.first; + if (truth(props.last)) node.anchor = props.last; + return node; + } + + /// Creates a MappingNode from [pairs]. + _MappingNode map(List<_Pair<_Node, _Node>> pairs) { + var content = new Map<_Node, _Node>(); + pairs.forEach((pair) => content[pair.first] = pair.last); + return new _MappingNode("?", content); + } + + /// Runs [fn] in a context named [name]. Used for error reporting. + context(String name, fn()) { + try { + contextStack.add(name); + return fn(); + } finally { + var popped = contextStack.removeLast(); + assert(popped == name); + } + } + + /// Adds [message] as extra information to any errors that occur between the + /// current position and the position of the cursor after running [fn]. The + /// cursor is reset after [fn] is run. + annotateError(String message, fn()) { + var start = pos; + var end; + transaction(() { + fn(); + end = pos; + return false; + }); + errorAnnotations[new _Range(start, end)] = message; + } + + /// Throws an error with additional context information. + error(String message) { + // Line and column should be one-based. + throw new SyntaxError(line + 1, column + 1, + "$message (in $farthestContext)"); + } + + /// If [result] is falsey, throws an error saying that [expected] was + /// expected. + expect(result, String expected) { + if (truth(result)) return result; + error("expected $expected"); + } + + /// Throws an error saying that the parse failed. Uses [farthestLine], + /// [farthestColumn], and [farthestContext] to provide additional information. + parseFailed() { + var message = "invalid YAML in $farthestContext"; + var extraError = errorAnnotations[farthestPos]; + if (extraError != null) message = "$message ($extraError)"; + throw new SyntaxError(farthestLine + 1, farthestColumn + 1, message); + } + + /// Returns the number of spaces after the current position. + int countIndentation() { + var i = 0; + while (peek(i) == SP) i++; + return i; + } + + /// Returns the indentation for a block scalar. + int blockScalarAdditionalIndentation(_BlockHeader header, int indent) { + if (!header.autoDetectIndent) return header.additionalIndent; + + var maxSpaces = 0; + var maxSpacesLine = 0; + var spaces = 0; + transaction(() { + do { + spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length; + if (spaces > maxSpaces) { + maxSpaces = spaces; + maxSpacesLine = line; + } + } while (b_break()); + return false; + }); + + // If the next non-empty line isn't indented further than the start of the + // block scalar, that means the scalar is going to be empty. Returning any + // value > 0 will cause the parser not to consume any text. + if (spaces <= indent) return 1; + + // It's an error for a leading empty line to be indented more than the first + // non-empty line. + if (maxSpaces > spaces) { + throw new SyntaxError(maxSpacesLine + 1, maxSpaces, + "Leading empty lines may not be indented more than the first " + "non-empty line."); + } + + return spaces - indent; + } + + /// Returns whether the current position is at the beginning of a line. + bool get atStartOfLine => column == 0; + + /// Returns whether the current position is at the end of the input. + bool get atEndOfFile => pos == len; + + /// Given an indicator character, returns the type of that indicator (or null + /// if the indicator isn't found. + int indicatorType(int char) { + switch (char) { + case HYPHEN: return C_SEQUENCE_ENTRY; + case QUESTION_MARK: return C_MAPPING_KEY; + case COLON: return C_MAPPING_VALUE; + case COMMA: return C_COLLECT_ENTRY; + case LEFT_BRACKET: return C_SEQUENCE_START; + case RIGHT_BRACKET: return C_SEQUENCE_END; + case LEFT_BRACE: return C_MAPPING_START; + case RIGHT_BRACE: return C_MAPPING_END; + case HASH: return C_COMMENT; + case AMPERSAND: return C_ANCHOR; + case ASTERISK: return C_ALIAS; + case EXCLAMATION: return C_TAG; + case VERTICAL_BAR: return C_LITERAL; + case GREATER_THAN: return C_FOLDED; + case SINGLE_QUOTE: return C_SINGLE_QUOTE; + case DOUBLE_QUOTE: return C_DOUBLE_QUOTE; + case PERCENT: return C_DIRECTIVE; + case AT: + case GRAVE_ACCENT: + return C_RESERVED; + default: return null; + } + } + + // 1 + bool isPrintable(int char) { + return char == TAB || + char == LF || + char == CR || + (char >= SP && char <= TILDE) || + char == NEL || + (char >= 0xA0 && char <= 0xD7FF) || + (char >= 0xE000 && char <= 0xFFFD) || + (char >= 0x10000 && char <= 0x10FFFF); + } + + // 2 + bool isJson(int char) => char == TAB || (char >= SP && char <= 0x10FFFF); + + // 22 + bool c_indicator(int type) => consume((c) => indicatorType(c) == type); + + // 23 + bool isFlowIndicator(int char) { + var indicator = indicatorType(char); + return indicator == C_COLLECT_ENTRY || + indicator == C_SEQUENCE_START || + indicator == C_SEQUENCE_END || + indicator == C_MAPPING_START || + indicator == C_MAPPING_END; + } + + // 26 + bool isBreak(int char) => char == LF || char == CR; + + // 27 + bool isNonBreak(int char) => isPrintable(char) && !isBreak(char); + + // 28 + bool b_break() { + if (consumeChar(CR)) { + zeroOrOne(() => consumeChar(LF)); + return true; + } + return consumeChar(LF); + } + + // 29 + bool b_asLineFeed() => captureAs("\n", () => b_break()); + + // 30 + bool b_nonContent() => captureAs("", () => b_break()); + + // 33 + bool isSpace(int char) => char == SP || char == TAB; + + // 34 + bool isNonSpace(int char) => isNonBreak(char) && !isSpace(char); + + // 35 + bool isDecDigit(int char) => char >= NUMBER_0 && char <= NUMBER_9; + + // 36 + bool isHexDigit(int char) { + return isDecDigit(char) || + (char >= LETTER_A && char <= LETTER_F) || + (char >= LETTER_CAP_A && char <= LETTER_CAP_F); + } + + // 41 + bool c_escape() => captureAs("", () => consumeChar(BACKSLASH)); + + // 42 + bool ns_escNull() => captureAs("\x00", () => consumeChar(NUMBER_0)); + + // 43 + bool ns_escBell() => captureAs("\x07", () => consumeChar(LETTER_A)); + + // 44 + bool ns_escBackspace() => captureAs("\b", () => consumeChar(LETTER_B)); + + // 45 + bool ns_escHorizontalTab() => captureAs("\t", () { + return consume((c) => c == LETTER_T || c == TAB); + }); + + // 46 + bool ns_escLineFeed() => captureAs("\n", () => consumeChar(LETTER_N)); + + // 47 + bool ns_escVerticalTab() => captureAs("\v", () => consumeChar(LETTER_V)); + + // 48 + bool ns_escFormFeed() => captureAs("\f", () => consumeChar(LETTER_F)); + + // 49 + bool ns_escCarriageReturn() => captureAs("\r", () => consumeChar(LETTER_R)); + + // 50 + bool ns_escEscape() => captureAs("\x1B", () => consumeChar(LETTER_E)); + + // 51 + bool ns_escSpace() => consumeChar(SP); + + // 52 + bool ns_escDoubleQuote() => consumeChar(DOUBLE_QUOTE); + + // 53 + bool ns_escSlash() => consumeChar(SLASH); + + // 54 + bool ns_escBackslash() => consumeChar(BACKSLASH); + + // 55 + bool ns_escNextLine() => captureAs("\x85", () => consumeChar(LETTER_CAP_N)); + + // 56 + bool ns_escNonBreakingSpace() => + captureAs("\xA0", () => consumeChar(UNDERSCORE)); + + // 57 + bool ns_escLineSeparator() => + captureAs("\u2028", () => consumeChar(LETTER_CAP_L)); + + // 58 + bool ns_escParagraphSeparator() => + captureAs("\u2029", () => consumeChar(LETTER_CAP_P)); + + // 59 + bool ns_esc8Bit() => ns_escNBit(LETTER_X, 2); + + // 60 + bool ns_esc16Bit() => ns_escNBit(LETTER_U, 4); + + // 61 + bool ns_esc32Bit() => ns_escNBit(LETTER_CAP_U, 8); + + // Helper method for 59 - 61 + bool ns_escNBit(int char, int digits) { + if (!captureAs('', () => consumeChar(char))) return false; + var captured = captureAndTransform( + () => nAtOnce(digits, (c, _) => isHexDigit(c)), + (hex) => new String.fromCharCodes([int.parse("0x$hex")])); + return expect(captured, "$digits hexidecimal digits"); + } + + // 62 + bool c_ns_escChar() => context('escape sequence', () => transaction(() { + if (!truth(c_escape())) return false; + return truth(or([ + ns_escNull, ns_escBell, ns_escBackspace, ns_escHorizontalTab, + ns_escLineFeed, ns_escVerticalTab, ns_escFormFeed, ns_escCarriageReturn, + ns_escEscape, ns_escSpace, ns_escDoubleQuote, ns_escSlash, + ns_escBackslash, ns_escNextLine, ns_escNonBreakingSpace, + ns_escLineSeparator, ns_escParagraphSeparator, ns_esc8Bit, ns_esc16Bit, + ns_esc32Bit + ])); + })); + + // 63 + bool s_indent(int indent) { + var result = nAtOnce(indent, (c, i) => c == SP); + if (peek() == TAB) { + annotateError("tab characters are not allowed as indentation in YAML", + () => zeroOrMore(() => consume(isSpace))); + } + return result; + } + + // 64 + bool s_indentLessThan(int indent) { + for (int i = 0; i < indent - 1; i++) { + if (!consumeChar(SP)) { + if (peek() == TAB) { + annotateError("tab characters are not allowed as indentation in YAML", + () { + for (; i < indent - 1; i++) { + if (!consume(isSpace)) break; + } + }); + } + break; + } + } + return true; + } + + // 65 + bool s_indentLessThanOrEqualTo(int indent) => s_indentLessThan(indent + 1); + + // 66 + bool s_separateInLine() => transaction(() { + return captureAs('', () => + truth(oneOrMore(() => consume(isSpace))) || atStartOfLine); + }); + + // 67 + bool s_linePrefix(int indent, int ctx) => captureAs("", () { + switch (ctx) { + case BLOCK_OUT: + case BLOCK_IN: + return s_blockLinePrefix(indent); + case FLOW_OUT: + case FLOW_IN: + return s_flowLinePrefix(indent); + } + }); + + // 68 + bool s_blockLinePrefix(int indent) => s_indent(indent); + + // 69 + bool s_flowLinePrefix(int indent) => captureAs('', () { + if (!truth(s_indent(indent))) return false; + zeroOrOne(s_separateInLine); + return true; + }); + + // 70 + bool l_empty(int indent, int ctx) => transaction(() { + var start = or([ + () => s_linePrefix(indent, ctx), + () => s_indentLessThan(indent) + ]); + if (!truth(start)) return false; + return b_asLineFeed(); + }); + + // 71 + bool b_asSpace() => captureAs(" ", () => consume(isBreak)); + + // 72 + bool b_l_trimmed(int indent, int ctx) => transaction(() { + if (!truth(b_nonContent())) return false; + return truth(oneOrMore(() => captureAs("\n", () => l_empty(indent, ctx)))); + }); + + // 73 + bool b_l_folded(int indent, int ctx) => + or([() => b_l_trimmed(indent, ctx), b_asSpace]); + + // 74 + bool s_flowFolded(int indent) => transaction(() { + zeroOrOne(s_separateInLine); + if (!truth(b_l_folded(indent, FLOW_IN))) return false; + return s_flowLinePrefix(indent); + }); + + // 75 + bool c_nb_commentText() { + if (!truth(c_indicator(C_COMMENT))) return false; + zeroOrMore(() => consume(isNonBreak)); + return true; + } + + // 76 + bool b_comment() => atEndOfFile || b_nonContent(); + + // 77 + bool s_b_comment() { + if (truth(s_separateInLine())) { + zeroOrOne(c_nb_commentText); + } + return b_comment(); + } + + // 78 + bool l_comment() => transaction(() { + if (!truth(s_separateInLine())) return false; + zeroOrOne(c_nb_commentText); + return b_comment(); + }); + + // 79 + bool s_l_comments() { + if (!truth(s_b_comment()) && !atStartOfLine) return false; + zeroOrMore(l_comment); + return true; + } + + // 80 + bool s_separate(int indent, int ctx) { + switch (ctx) { + case BLOCK_OUT: + case BLOCK_IN: + case FLOW_OUT: + case FLOW_IN: + return s_separateLines(indent); + case BLOCK_KEY: + case FLOW_KEY: + return s_separateInLine(); + default: throw 'invalid context "$ctx"'; + } + } + + // 81 + bool s_separateLines(int indent) { + return transaction(() => s_l_comments() && s_flowLinePrefix(indent)) || + s_separateInLine(); + } + + // 82 + bool l_directive() => false; // TODO(nweiz): implement + + // 96 + _Pair<_Tag, String> c_ns_properties(int indent, int ctx) { + var tag, anchor; + tag = c_ns_tagProperty(); + if (truth(tag)) { + anchor = transaction(() { + if (!truth(s_separate(indent, ctx))) return null; + return c_ns_anchorProperty(); + }); + return new _Pair<_Tag, String>(tag, anchor); + } + + anchor = c_ns_anchorProperty(); + if (truth(anchor)) { + tag = transaction(() { + if (!truth(s_separate(indent, ctx))) return null; + return c_ns_tagProperty(); + }); + return new _Pair<_Tag, String>(tag, anchor); + } + + return null; + } + + // 97 + _Tag c_ns_tagProperty() => null; // TODO(nweiz): implement + + // 101 + String c_ns_anchorProperty() => null; // TODO(nweiz): implement + + // 102 + bool isAnchorChar(int char) => isNonSpace(char) && !isFlowIndicator(char); + + // 103 + String ns_anchorName() => + captureString(() => oneOrMore(() => consume(isAnchorChar))); + + // 104 + _Node c_ns_aliasNode() { + if (!truth(c_indicator(C_ALIAS))) return null; + var name = expect(ns_anchorName(), 'anchor name'); + return new _AliasNode(name); + } + + // 105 + _ScalarNode e_scalar() => new _ScalarNode("?", content: ""); + + // 106 + _ScalarNode e_node() => e_scalar(); + + // 107 + bool nb_doubleChar() => or([ + c_ns_escChar, + () => consume((c) => isJson(c) && c != BACKSLASH && c != DOUBLE_QUOTE) + ]); + + // 108 + bool ns_doubleChar() => !isSpace(peek()) && truth(nb_doubleChar()); + + // 109 + _Node c_doubleQuoted(int indent, int ctx) => context('string', () { + return transaction(() { + if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; + var contents = nb_doubleText(indent, ctx); + if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; + return new _ScalarNode("!", content: contents); + }); + }); + + // 110 + String nb_doubleText(int indent, int ctx) => captureString(() { + switch (ctx) { + case FLOW_OUT: + case FLOW_IN: + nb_doubleMultiLine(indent); + break; + case BLOCK_KEY: + case FLOW_KEY: + nb_doubleOneLine(); + break; + } + return true; + }); + + // 111 + void nb_doubleOneLine() { + zeroOrMore(nb_doubleChar); + } + + // 112 + bool s_doubleEscaped(int indent) => transaction(() { + zeroOrMore(() => consume(isSpace)); + if (!captureAs("", () => consumeChar(BACKSLASH))) return false; + if (!truth(b_nonContent())) return false; + zeroOrMore(() => captureAs("\n", () => l_empty(indent, FLOW_IN))); + return s_flowLinePrefix(indent); + }); + + // 113 + bool s_doubleBreak(int indent) => or([ + () => s_doubleEscaped(indent), + () => s_flowFolded(indent) + ]); + + // 114 + void nb_ns_doubleInLine() { + zeroOrMore(() => transaction(() { + zeroOrMore(() => consume(isSpace)); + return ns_doubleChar(); + })); + } + + // 115 + bool s_doubleNextLine(int indent) { + if (!truth(s_doubleBreak(indent))) return false; + zeroOrOne(() { + if (!truth(ns_doubleChar())) return; + nb_ns_doubleInLine(); + or([ + () => s_doubleNextLine(indent), + () => zeroOrMore(() => consume(isSpace)) + ]); + }); + return true; + } + + // 116 + void nb_doubleMultiLine(int indent) { + nb_ns_doubleInLine(); + or([ + () => s_doubleNextLine(indent), + () => zeroOrMore(() => consume(isSpace)) + ]); + } + + // 117 + bool c_quotedQuote() => captureAs("'", () => rawString("''")); + + // 118 + bool nb_singleChar() => or([ + c_quotedQuote, + () => consume((c) => isJson(c) && c != SINGLE_QUOTE) + ]); + + // 119 + bool ns_singleChar() => !isSpace(peek()) && truth(nb_singleChar()); + + // 120 + _Node c_singleQuoted(int indent, int ctx) => context('string', () { + return transaction(() { + if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; + var contents = nb_singleText(indent, ctx); + if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; + return new _ScalarNode("!", content: contents); + }); + }); + + // 121 + String nb_singleText(int indent, int ctx) => captureString(() { + switch (ctx) { + case FLOW_OUT: + case FLOW_IN: + nb_singleMultiLine(indent); + break; + case BLOCK_KEY: + case FLOW_KEY: + nb_singleOneLine(indent); + break; + } + return true; + }); + + // 122 + void nb_singleOneLine(int indent) { + zeroOrMore(nb_singleChar); + } + + // 123 + void nb_ns_singleInLine() { + zeroOrMore(() => transaction(() { + zeroOrMore(() => consume(isSpace)); + return ns_singleChar(); + })); + } + + // 124 + bool s_singleNextLine(int indent) { + if (!truth(s_flowFolded(indent))) return false; + zeroOrOne(() { + if (!truth(ns_singleChar())) return; + nb_ns_singleInLine(); + or([ + () => s_singleNextLine(indent), + () => zeroOrMore(() => consume(isSpace)) + ]); + }); + return true; + } + + // 125 + void nb_singleMultiLine(int indent) { + nb_ns_singleInLine(); + or([ + () => s_singleNextLine(indent), + () => zeroOrMore(() => consume(isSpace)) + ]); + } + + // 126 + bool ns_plainFirst(int ctx) { + var char = peek(); + var indicator = indicatorType(char); + if (indicator == C_RESERVED) { + error("reserved indicators can't start a plain scalar"); + } + var match = (isNonSpace(char) && indicator == null) || + ((indicator == C_MAPPING_KEY || + indicator == C_MAPPING_VALUE || + indicator == C_SEQUENCE_ENTRY) && + isPlainSafe(ctx, peek(1))); + + if (match) next(); + return match; + } + + // 127 + bool isPlainSafe(int ctx, int char) { + switch (ctx) { + case FLOW_OUT: + case BLOCK_KEY: + // 128 + return isNonSpace(char); + case FLOW_IN: + case FLOW_KEY: + // 129 + return isNonSpace(char) && !isFlowIndicator(char); + default: throw 'invalid context "$ctx"'; + } + } + + // 130 + bool ns_plainChar(int ctx) { + var char = peek(); + var indicator = indicatorType(char); + var safeChar = isPlainSafe(ctx, char) && indicator != C_MAPPING_VALUE && + indicator != C_COMMENT; + var nonCommentHash = isNonSpace(peek(-1)) && indicator == C_COMMENT; + var nonMappingColon = indicator == C_MAPPING_VALUE && + isPlainSafe(ctx, peek(1)); + var match = safeChar || nonCommentHash || nonMappingColon; + + if (match) next(); + return match; + } + + // 131 + String ns_plain(int indent, int ctx) => context('plain scalar', () { + return captureString(() { + switch (ctx) { + case FLOW_OUT: + case FLOW_IN: + return ns_plainMultiLine(indent, ctx); + case BLOCK_KEY: + case FLOW_KEY: + return ns_plainOneLine(ctx); + default: throw 'invalid context "$ctx"'; + } + }); + }); + + // 132 + void nb_ns_plainInLine(int ctx) { + zeroOrMore(() => transaction(() { + zeroOrMore(() => consume(isSpace)); + return ns_plainChar(ctx); + })); + } + + // 133 + bool ns_plainOneLine(int ctx) { + if (truth(c_forbidden())) return false; + if (!truth(ns_plainFirst(ctx))) return false; + nb_ns_plainInLine(ctx); + return true; + } + + // 134 + bool s_ns_plainNextLine(int indent, int ctx) => transaction(() { + if (!truth(s_flowFolded(indent))) return false; + if (truth(c_forbidden())) return false; + if (!truth(ns_plainChar(ctx))) return false; + nb_ns_plainInLine(ctx); + return true; + }); + + // 135 + bool ns_plainMultiLine(int indent, int ctx) { + if (!truth(ns_plainOneLine(ctx))) return false; + zeroOrMore(() => s_ns_plainNextLine(indent, ctx)); + return true; + } + + // 136 + int inFlow(int ctx) { + switch (ctx) { + case FLOW_OUT: + case FLOW_IN: + return FLOW_IN; + case BLOCK_KEY: + case FLOW_KEY: + return FLOW_KEY; + } + } + + // 137 + _SequenceNode c_flowSequence(int indent, int ctx) => transaction(() { + if (!truth(c_indicator(C_SEQUENCE_START))) return null; + zeroOrOne(() => s_separate(indent, ctx)); + var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx))); + if (!truth(c_indicator(C_SEQUENCE_END))) return null; + return new _SequenceNode("?", new List<_Node>.from(content)); + }); + + // 138 + Collection<_Node> ns_s_flowSeqEntries(int indent, int ctx) { + var first = ns_flowSeqEntry(indent, ctx); + if (!truth(first)) return new Queue<_Node>(); + zeroOrOne(() => s_separate(indent, ctx)); + + var rest; + if (truth(c_indicator(C_COLLECT_ENTRY))) { + zeroOrOne(() => s_separate(indent, ctx)); + rest = zeroOrOne(() => ns_s_flowSeqEntries(indent, ctx)); + } + + if (rest == null) rest = new Queue<_Node>(); + rest.addFirst(first); + + return rest; + } + + // 139 + _Node ns_flowSeqEntry(int indent, int ctx) => or([ + () => ns_flowPair(indent, ctx), + () => ns_flowNode(indent, ctx) + ]); + + // 140 + _Node c_flowMapping(int indent, int ctx) { + if (!truth(c_indicator(C_MAPPING_START))) return null; + zeroOrOne(() => s_separate(indent, ctx)); + var content = zeroOrOne(() => ns_s_flowMapEntries(indent, inFlow(ctx))); + if (!truth(c_indicator(C_MAPPING_END))) return null; + return new _MappingNode("?", content); + } + + // 141 + YamlMap ns_s_flowMapEntries(int indent, int ctx) { + var first = ns_flowMapEntry(indent, ctx); + if (!truth(first)) return new YamlMap(); + zeroOrOne(() => s_separate(indent, ctx)); + + var rest; + if (truth(c_indicator(C_COLLECT_ENTRY))) { + zeroOrOne(() => s_separate(indent, ctx)); + rest = ns_s_flowMapEntries(indent, ctx); + } + + if (rest == null) rest = new YamlMap(); + + // TODO(nweiz): Duplicate keys should be an error. This includes keys with + // different representations but the same value (e.g. 10 vs 0xa). To make + // this user-friendly we'll probably also want to associate nodes with a + // source range. + if (!rest.containsKey(first.first)) rest[first.first] = first.last; + + return rest; + } + + // 142 + _Pair<_Node, _Node> ns_flowMapEntry(int indent, int ctx) => or([ + () => transaction(() { + if (!truth(c_indicator(C_MAPPING_KEY))) return false; + if (!truth(s_separate(indent, ctx))) return false; + return ns_flowMapExplicitEntry(indent, ctx); + }), + () => ns_flowMapImplicitEntry(indent, ctx) + ]); + + // 143 + _Pair<_Node, _Node> ns_flowMapExplicitEntry(int indent, int ctx) => or([ + () => ns_flowMapImplicitEntry(indent, ctx), + () => new _Pair<_Node, _Node>(e_node(), e_node()) + ]); + + // 144 + _Pair<_Node, _Node> ns_flowMapImplicitEntry(int indent, int ctx) => or([ + () => ns_flowMapYamlKeyEntry(indent, ctx), + () => c_ns_flowMapEmptyKeyEntry(indent, ctx), + () => c_ns_flowMapJsonKeyEntry(indent, ctx) + ]); + + // 145 + _Pair<_Node, _Node> ns_flowMapYamlKeyEntry(int indent, int ctx) { + var key = ns_flowYamlNode(indent, ctx); + if (!truth(key)) return null; + var value = or([ + () => transaction(() { + zeroOrOne(() => s_separate(indent, ctx)); + return c_ns_flowMapSeparateValue(indent, ctx); + }), + e_node + ]); + return new _Pair<_Node, _Node>(key, value); + } + + // 146 + _Pair<_Node, _Node> c_ns_flowMapEmptyKeyEntry(int indent, int ctx) { + var value = c_ns_flowMapSeparateValue(indent, ctx); + if (!truth(value)) return null; + return new _Pair<_Node, _Node>(e_node(), value); + } + + // 147 + _Node c_ns_flowMapSeparateValue(int indent, int ctx) => transaction(() { + if (!truth(c_indicator(C_MAPPING_VALUE))) return null; + if (isPlainSafe(ctx, peek())) return null; + + return or([ + () => transaction(() { + if (!s_separate(indent, ctx)) return null; + return ns_flowNode(indent, ctx); + }), + e_node + ]); + }); + + // 148 + _Pair<_Node, _Node> c_ns_flowMapJsonKeyEntry(int indent, int ctx) { + var key = c_flowJsonNode(indent, ctx); + if (!truth(key)) return null; + var value = or([ + () => transaction(() { + zeroOrOne(() => s_separate(indent, ctx)); + return c_ns_flowMapAdjacentValue(indent, ctx); + }), + e_node + ]); + return new _Pair<_Node, _Node>(key, value); + } + + // 149 + _Node c_ns_flowMapAdjacentValue(int indent, int ctx) { + if (!truth(c_indicator(C_MAPPING_VALUE))) return null; + return or([ + () => transaction(() { + zeroOrOne(() => s_separate(indent, ctx)); + return ns_flowNode(indent, ctx); + }), + e_node + ]); + } + + // 150 + _Node ns_flowPair(int indent, int ctx) { + var pair = or([ + () => transaction(() { + if (!truth(c_indicator(C_MAPPING_KEY))) return null; + if (!truth(s_separate(indent, ctx))) return null; + return ns_flowMapExplicitEntry(indent, ctx); + }), + () => ns_flowPairEntry(indent, ctx) + ]); + if (!truth(pair)) return null; + + return map([pair]); + } + + // 151 + _Pair<_Node, _Node> ns_flowPairEntry(int indent, int ctx) => or([ + () => ns_flowPairYamlKeyEntry(indent, ctx), + () => c_ns_flowMapEmptyKeyEntry(indent, ctx), + () => c_ns_flowPairJsonKeyEntry(indent, ctx) + ]); + + // 152 + _Pair<_Node, _Node> ns_flowPairYamlKeyEntry(int indent, int ctx) => + transaction(() { + var key = ns_s_implicitYamlKey(FLOW_KEY); + if (!truth(key)) return null; + var value = c_ns_flowMapSeparateValue(indent, ctx); + if (!truth(value)) return null; + return new _Pair<_Node, _Node>(key, value); + }); + + // 153 + _Pair<_Node, _Node> c_ns_flowPairJsonKeyEntry(int indent, int ctx) => + transaction(() { + var key = c_s_implicitJsonKey(FLOW_KEY); + if (!truth(key)) return null; + var value = c_ns_flowMapAdjacentValue(indent, ctx); + if (!truth(value)) return null; + return new _Pair<_Node, _Node>(key, value); + }); + + // 154 + _Node ns_s_implicitYamlKey(int ctx) => transaction(() { + // TODO(nweiz): this is supposed to be limited to 1024 characters. + + // The indentation parameter is "null" since it's unused in this path + var node = ns_flowYamlNode(null, ctx); + if (!truth(node)) return null; + zeroOrOne(s_separateInLine); + return node; + }); + + // 155 + _Node c_s_implicitJsonKey(int ctx) => transaction(() { + // TODO(nweiz): this is supposed to be limited to 1024 characters. + + // The indentation parameter is "null" since it's unused in this path + var node = c_flowJsonNode(null, ctx); + if (!truth(node)) return null; + zeroOrOne(s_separateInLine); + return node; + }); + + // 156 + _Node ns_flowYamlContent(int indent, int ctx) { + var str = ns_plain(indent, ctx); + if (!truth(str)) return null; + return new _ScalarNode("?", content: str); + } + + // 157 + _Node c_flowJsonContent(int indent, int ctx) => or([ + () => c_flowSequence(indent, ctx), + () => c_flowMapping(indent, ctx), + () => c_singleQuoted(indent, ctx), + () => c_doubleQuoted(indent, ctx) + ]); + + // 158 + _Node ns_flowContent(int indent, int ctx) => or([ + () => ns_flowYamlContent(indent, ctx), + () => c_flowJsonContent(indent, ctx) + ]); + + // 159 + _Node ns_flowYamlNode(int indent, int ctx) => or([ + c_ns_aliasNode, + () => ns_flowYamlContent(indent, ctx), + () { + var props = c_ns_properties(indent, ctx); + if (!truth(props)) return null; + var node = or([ + () => transaction(() { + if (!truth(s_separate(indent, ctx))) return null; + return ns_flowYamlContent(indent, ctx); + }), + e_scalar + ]); + return addProps(node, props); + } + ]); + + // 160 + _Node c_flowJsonNode(int indent, int ctx) => transaction(() { + var props; + zeroOrOne(() => transaction(() { + props = c_ns_properties(indent, ctx); + if (!truth(props)) return null; + return s_separate(indent, ctx); + })); + + return addProps(c_flowJsonContent(indent, ctx), props); + }); + + // 161 + _Node ns_flowNode(int indent, int ctx) => or([ + c_ns_aliasNode, + () => ns_flowContent(indent, ctx), + () => transaction(() { + var props = c_ns_properties(indent, ctx); + if (!truth(props)) return null; + var node = or([ + () => transaction(() => s_separate(indent, ctx) ? + ns_flowContent(indent, ctx) : null), + e_scalar]); + return addProps(node, props); + }) + ]); + + // 162 + _BlockHeader c_b_blockHeader() => transaction(() { + var indentation = c_indentationIndicator(); + var chomping = c_chompingIndicator(); + if (!truth(indentation)) indentation = c_indentationIndicator(); + if (!truth(s_b_comment())) return null; + + return new _BlockHeader(indentation, chomping); + }); + + // 163 + int c_indentationIndicator() { + if (!isDecDigit(peek())) return null; + return next() - NUMBER_0; + } + + // 164 + int c_chompingIndicator() { + switch (peek()) { + case HYPHEN: + next(); + return CHOMPING_STRIP; + case PLUS: + next(); + return CHOMPING_KEEP; + default: + return CHOMPING_CLIP; + } + } + + // 165 + bool b_chompedLast(int chomping) { + if (atEndOfFile) return true; + switch (chomping) { + case CHOMPING_STRIP: + return b_nonContent(); + case CHOMPING_CLIP: + case CHOMPING_KEEP: + return b_asLineFeed(); + } + } + + // 166 + void l_chompedEmpty(int indent, int chomping) { + switch (chomping) { + case CHOMPING_STRIP: + case CHOMPING_CLIP: + l_stripEmpty(indent); + break; + case CHOMPING_KEEP: + l_keepEmpty(indent); + break; + } + } + + // 167 + void l_stripEmpty(int indent) { + captureAs('', () { + zeroOrMore(() => transaction(() { + if (!truth(s_indentLessThanOrEqualTo(indent))) return false; + return b_nonContent(); + })); + zeroOrOne(() => l_trailComments(indent)); + return true; + }); + } + + // 168 + void l_keepEmpty(int indent) { + zeroOrMore(() => captureAs('\n', () => l_empty(indent, BLOCK_IN))); + zeroOrOne(() => captureAs('', () => l_trailComments(indent))); + } + + // 169 + bool l_trailComments(int indent) => transaction(() { + if (!truth(s_indentLessThanOrEqualTo(indent))) return false; + if (!truth(c_nb_commentText())) return false; + if (!truth(b_comment())) return false; + zeroOrMore(l_comment); + return true; + }); + + // 170 + _Node c_l_literal(int indent) => transaction(() { + if (!truth(c_indicator(C_LITERAL))) return null; + var header = c_b_blockHeader(); + if (!truth(header)) return null; + + var additionalIndent = blockScalarAdditionalIndentation(header, indent); + var content = l_literalContent(indent + additionalIndent, header.chomping); + if (!truth(content)) return null; + + return new _ScalarNode("!", content: content); + }); + + // 171 + bool l_nb_literalText(int indent) => transaction(() { + zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN))); + if (!truth(captureAs("", () => s_indent(indent)))) return false; + return truth(oneOrMore(() => consume(isNonBreak))); + }); + + // 172 + bool b_nb_literalNext(int indent) => transaction(() { + if (!truth(b_asLineFeed())) return false; + return l_nb_literalText(indent); + }); + + // 173 + String l_literalContent(int indent, int chomping) => captureString(() { + transaction(() { + if (!truth(l_nb_literalText(indent))) return false; + zeroOrMore(() => b_nb_literalNext(indent)); + return b_chompedLast(chomping); + }); + l_chompedEmpty(indent, chomping); + return true; + }); + + // 174 + _Node c_l_folded(int indent) => transaction(() { + if (!truth(c_indicator(C_FOLDED))) return null; + var header = c_b_blockHeader(); + if (!truth(header)) return null; + + var additionalIndent = blockScalarAdditionalIndentation(header, indent); + var content = l_foldedContent(indent + additionalIndent, header.chomping); + if (!truth(content)) return null; + + return new _ScalarNode("!", content: content); + }); + + // 175 + bool s_nb_foldedText(int indent) => transaction(() { + if (!truth(captureAs('', () => s_indent(indent)))) return false; + if (!truth(consume(isNonSpace))) return false; + zeroOrMore(() => consume(isNonBreak)); + return true; + }); + + // 176 + bool l_nb_foldedLines(int indent) { + if (!truth(s_nb_foldedText(indent))) return false; + zeroOrMore(() => transaction(() { + if (!truth(b_l_folded(indent, BLOCK_IN))) return false; + return s_nb_foldedText(indent); + })); + return true; + } + + // 177 + bool s_nb_spacedText(int indent) => transaction(() { + if (!truth(captureAs('', () => s_indent(indent)))) return false; + if (!truth(consume(isSpace))) return false; + zeroOrMore(() => consume(isNonBreak)); + return true; + }); + + // 178 + bool b_l_spaced(int indent) { + if (!truth(b_asLineFeed())) return false; + zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN))); + return true; + } + + // 179 + bool l_nb_spacedLines(int indent) { + if (!truth(s_nb_spacedText(indent))) return false; + zeroOrMore(() => transaction(() { + if (!truth(b_l_spaced(indent))) return false; + return s_nb_spacedText(indent); + })); + return true; + } + + // 180 + bool l_nb_sameLines(int indent) => transaction(() { + zeroOrMore(() => captureAs('\n', () => l_empty(indent, BLOCK_IN))); + return or([ + () => l_nb_foldedLines(indent), + () => l_nb_spacedLines(indent) + ]); + }); + + // 181 + bool l_nb_diffLines(int indent) { + if (!truth(l_nb_sameLines(indent))) return false; + zeroOrMore(() => transaction(() { + if (!truth(b_asLineFeed())) return false; + return l_nb_sameLines(indent); + })); + return true; + } + + // 182 + String l_foldedContent(int indent, int chomping) => captureString(() { + transaction(() { + if (!truth(l_nb_diffLines(indent))) return false; + return b_chompedLast(chomping); + }); + l_chompedEmpty(indent, chomping); + return true; + }); + + // 183 + _SequenceNode l_blockSequence(int indent) => context('sequence', () { + var additionalIndent = countIndentation() - indent; + if (additionalIndent <= 0) return null; + + var content = oneOrMore(() => transaction(() { + if (!truth(s_indent(indent + additionalIndent))) return null; + return c_l_blockSeqEntry(indent + additionalIndent); + })); + if (!truth(content)) return null; + + return new _SequenceNode("?", content); + }); + + // 184 + _Node c_l_blockSeqEntry(int indent) => transaction(() { + if (!truth(c_indicator(C_SEQUENCE_ENTRY))) return null; + if (isNonSpace(peek())) return null; + + return s_l_blockIndented(indent, BLOCK_IN); + }); + + // 185 + _Node s_l_blockIndented(int indent, int ctx) { + var additionalIndent = countIndentation(); + return or([ + () => transaction(() { + if (!truth(s_indent(additionalIndent))) return null; + return or([ + () => ns_l_compactSequence(indent + 1 + additionalIndent), + () => ns_l_compactMapping(indent + 1 + additionalIndent)]); + }), + () => s_l_blockNode(indent, ctx), + () => s_l_comments() ? e_node() : null]); + } + + // 186 + _Node ns_l_compactSequence(int indent) => context('sequence', () { + var first = c_l_blockSeqEntry(indent); + if (!truth(first)) return null; + + var content = zeroOrMore(() => transaction(() { + if (!truth(s_indent(indent))) return null; + return c_l_blockSeqEntry(indent); + })); + content.insertRange(0, 1, first); + + return new _SequenceNode("?", content); + }); + + // 187 + _Node l_blockMapping(int indent) => context('mapping', () { + var additionalIndent = countIndentation() - indent; + if (additionalIndent <= 0) return null; + + var pairs = oneOrMore(() => transaction(() { + if (!truth(s_indent(indent + additionalIndent))) return null; + return ns_l_blockMapEntry(indent + additionalIndent); + })); + if (!truth(pairs)) return null; + + return map(pairs); + }); + + // 188 + _Pair<_Node, _Node> ns_l_blockMapEntry(int indent) => or([ + () => c_l_blockMapExplicitEntry(indent), + () => ns_l_blockMapImplicitEntry(indent) + ]); + + // 189 + _Pair<_Node, _Node> c_l_blockMapExplicitEntry(int indent) { + var key = c_l_blockMapExplicitKey(indent); + if (!truth(key)) return null; + + var value = or([ + () => l_blockMapExplicitValue(indent), + e_node + ]); + + return new _Pair<_Node, _Node>(key, value); + } + + // 190 + _Node c_l_blockMapExplicitKey(int indent) => transaction(() { + if (!truth(c_indicator(C_MAPPING_KEY))) return null; + return s_l_blockIndented(indent, BLOCK_OUT); + }); + + // 191 + _Node l_blockMapExplicitValue(int indent) => transaction(() { + if (!truth(s_indent(indent))) return null; + if (!truth(c_indicator(C_MAPPING_VALUE))) return null; + return s_l_blockIndented(indent, BLOCK_OUT); + }); + + // 192 + _Pair<_Node, _Node> ns_l_blockMapImplicitEntry(int indent) => transaction(() { + var key = or([ns_s_blockMapImplicitKey, e_node]); + var value = c_l_blockMapImplicitValue(indent); + return truth(value) ? new _Pair<_Node, _Node>(key, value) : null; + }); + + // 193 + _Node ns_s_blockMapImplicitKey() => context('mapping key', () => or([ + () => c_s_implicitJsonKey(BLOCK_KEY), + () => ns_s_implicitYamlKey(BLOCK_KEY) + ])); + + // 194 + _Node c_l_blockMapImplicitValue(int indent) => context('mapping value', () => + transaction(() { + if (!truth(c_indicator(C_MAPPING_VALUE))) return null; + return or([ + () => s_l_blockNode(indent, BLOCK_OUT), + () => s_l_comments() ? e_node() : null + ]); + })); + + // 195 + _Node ns_l_compactMapping(int indent) => context('mapping', () { + var first = ns_l_blockMapEntry(indent); + if (!truth(first)) return null; + + var pairs = zeroOrMore(() => transaction(() { + if (!truth(s_indent(indent))) return null; + return ns_l_blockMapEntry(indent); + })); + pairs.insertRange(0, 1, first); + + return map(pairs); + }); + + // 196 + _Node s_l_blockNode(int indent, int ctx) => or([ + () => s_l_blockInBlock(indent, ctx), + () => s_l_flowInBlock(indent) + ]); + + // 197 + _Node s_l_flowInBlock(int indent) => transaction(() { + if (!truth(s_separate(indent + 1, FLOW_OUT))) return null; + var node = ns_flowNode(indent + 1, FLOW_OUT); + if (!truth(node)) return null; + if (!truth(s_l_comments())) return null; + return node; + }); + + // 198 + _Node s_l_blockInBlock(int indent, int ctx) => or([ + () => s_l_blockScalar(indent, ctx), + () => s_l_blockCollection(indent, ctx) + ]); + + // 199 + _Node s_l_blockScalar(int indent, int ctx) => transaction(() { + if (!truth(s_separate(indent + 1, ctx))) return null; + var props = transaction(() { + var innerProps = c_ns_properties(indent + 1, ctx); + if (!truth(innerProps)) return null; + if (!truth(s_separate(indent + 1, ctx))) return null; + return innerProps; + }); + + var node = or([() => c_l_literal(indent), () => c_l_folded(indent)]); + if (!truth(node)) return null; + return addProps(node, props); + }); + + // 200 + _Node s_l_blockCollection(int indent, int ctx) => transaction(() { + var props = transaction(() { + if (!truth(s_separate(indent + 1, ctx))) return null; + return c_ns_properties(indent + 1, ctx); + }); + + if (!truth(s_l_comments())) return null; + return or([ + () => l_blockSequence(seqSpaces(indent, ctx)), + () => l_blockMapping(indent)]); + }); + + // 201 + int seqSpaces(int indent, int ctx) => ctx == BLOCK_OUT ? indent - 1 : indent; + + // 202 + void l_documentPrefix() { + zeroOrMore(l_comment); + } + + // 203 + bool c_directivesEnd() => rawString("---"); + + // 204 + bool c_documentEnd() => rawString("..."); + + // 205 + bool l_documentSuffix() => transaction(() { + if (!truth(c_documentEnd())) return false; + return s_l_comments(); + }); + + // 206 + bool c_forbidden() { + if (!inBareDocument || !atStartOfLine) return false; + var forbidden = false; + transaction(() { + if (!truth(or([c_directivesEnd, c_documentEnd]))) return; + var char = peek(); + forbidden = isBreak(char) || isSpace(char) || atEndOfFile; + return; + }); + return forbidden; + } + + // 207 + _Node l_bareDocument() { + try { + inBareDocument = true; + return s_l_blockNode(-1, BLOCK_IN); + } finally { + inBareDocument = false; + } + } + + // 208 + _Node l_explicitDocument() { + if (!truth(c_directivesEnd())) return null; + var doc = l_bareDocument(); + if (truth(doc)) return doc; + + doc = e_node(); + s_l_comments(); + return doc; + } + + // 209 + _Node l_directiveDocument() { + if (!truth(oneOrMore(l_directive))) return null; + var doc = l_explicitDocument(); + if (doc != null) return doc; + parseFailed(); + return null; // Unreachable. + } + + // 210 + _Node l_anyDocument() => + or([l_directiveDocument, l_explicitDocument, l_bareDocument]); + + // 211 + List<_Node> l_yamlStream() { + var docs = []; + zeroOrMore(l_documentPrefix); + var first = zeroOrOne(l_anyDocument); + if (!truth(first)) first = e_node(); + docs.add(first); + + zeroOrMore(() { + var doc; + if (truth(oneOrMore(l_documentSuffix))) { + zeroOrMore(l_documentPrefix); + doc = zeroOrOne(l_anyDocument); + } else { + zeroOrMore(l_documentPrefix); + doc = zeroOrOne(l_explicitDocument); + } + if (truth(doc)) docs.add(doc); + return doc; + }); + + if (!atEndOfFile) parseFailed(); + return docs; + } +} + +class SyntaxError extends YamlException { + final int line; + final int column; + + SyntaxError(this.line, this.column, String msg) : super(msg); + + String toString() => "Syntax error on line $line, column $column: $msg"; +} + +/// A pair of values. +class _Pair { + E first; + F last; + + _Pair(this.first, this.last); + + String toString() => '($first, $last)'; +} + +/// The information in the header for a block scalar. +class _BlockHeader { + final int additionalIndent; + final int chomping; + + _BlockHeader(this.additionalIndent, this.chomping); + + bool get autoDetectIndent => additionalIndent == null; +} + +/// A range of characters in the YAML document, from [start] to [end] +/// (inclusive). +class _Range { + /// The first character in the range. + final int start; + + /// The last character in the range. + final int end; + + _Range(this.start, this.end); + + /// Returns whether or not [pos] lies within this range. + bool contains(int pos) => pos >= start && pos <= end; +} + +/// A map that associates [E] values with [_Range]s. It's efficient to create +/// new associations, but finding the value associated with a position is more +/// expensive. +class _RangeMap { + /// The ranges and their associated elements. + final List<_Pair<_Range, E>> contents; + + _RangeMap() : this.contents = <_Pair<_Range, E>>[]; + + /// Returns the value associated with the range in which [pos] lies, or null + /// if there is no such range. If there's more than one such range, the most + /// recently set one is used. + E operator[](int pos) { + // Iterate backwards through contents so the more recent range takes + // precedence. TODO(nweiz): clean this up when issue 2804 is fixed. + for (var i = contents.length - 1; i >= 0; i--) { + var pair = contents[i]; + if (pair.first.contains(pos)) return pair.last; + } + return null; + } + + /// Associates [value] with [range]. + operator[]=(_Range range, E value) => + contents.add(new _Pair<_Range, E>(range, value)); +} diff --git a/pkgs/yaml/lib/visitor.dart b/pkgs/yaml/lib/visitor.dart new file mode 100644 index 000000000..b5c14c949 --- /dev/null +++ b/pkgs/yaml/lib/visitor.dart @@ -0,0 +1,27 @@ +// 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. + +part of yaml; + +/// The visitor pattern for YAML documents. +class _Visitor { + /// Returns [alias]. + visitAlias(_AliasNode alias) => alias; + + /// Returns [scalar]. + visitScalar(_ScalarNode scalar) => scalar; + + /// Visits each node in [seq] and returns a list of the results. + visitSequence(_SequenceNode seq) + => seq.content.mappedBy((e) => e.visit(this)).toList(); + + /// Visits each key and value in [map] and returns a map of the results. + visitMapping(_MappingNode map) { + var out = new YamlMap(); + for (var key in map.content.keys) { + out[key.visit(this)] = map.content[key].visit(this); + } + return out; + } +} diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart new file mode 100644 index 000000000..ef0ac830b --- /dev/null +++ b/pkgs/yaml/lib/yaml.dart @@ -0,0 +1,75 @@ +// 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. + +/// A parser for [YAML](http://www.yaml.org/). +/// +/// Use [loadYaml] to load a single document, or [loadYamlStream] to load a +/// stream of documents. For example: +/// +/// import 'package:yaml/yaml.dart'; +/// main() { +/// var doc = loadYaml("YAML: YAML Ain't Markup Language"); +/// print(doc['YAML']); +/// } +/// +/// This library currently doesn't support dumping to YAML. You should use +/// `stringify` from `dart:json` instead: +/// +/// import 'dart:json' as json; +/// import 'package:yaml/yaml.dart'; +/// main() { +/// var doc = loadYaml("YAML: YAML Ain't Markup Language"); +/// print(json.stringify(doc)); +/// } +library yaml; + +import 'dart:math' as Math; +import 'dart:collection' show Queue; + +import 'deep_equals.dart'; + +part 'yaml_map.dart'; +part 'model.dart'; +part 'parser.dart'; +part 'visitor.dart'; +part 'composer.dart'; +part 'constructor.dart'; + +/// Loads a single document from a YAML string. If the string contains more than +/// one document, this throws an error. +/// +/// The return value is mostly normal Dart objects. However, since YAML mappings +/// support some key types that the default Dart map implementation doesn't +/// (null, NaN, booleans, lists, and maps), all maps in the returned document +/// are YamlMaps. These have a few small behavioral differences from the default +/// Map implementation; for details, see the YamlMap class. +loadYaml(String yaml) { + var stream = loadYamlStream(yaml); + if (stream.length != 1) { + throw new YamlException("Expected 1 document, were ${stream.length}"); + } + return stream[0]; +} + +/// Loads a stream of documents from a YAML string. +/// +/// The return value is mostly normal Dart objects. However, since YAML mappings +/// support some key types that the default Dart map implementation doesn't +/// (null, NaN, booleans, lists, and maps), all maps in the returned document +/// are YamlMaps. These have a few small behavioral differences from the default +/// Map implementation; for details, see the YamlMap class. +List loadYamlStream(String yaml) { + return new _Parser(yaml).l_yamlStream().mappedBy((doc) => + new _Constructor(new _Composer(doc).compose()).construct()) + .toList(); +} + +/// An error thrown by the YAML processor. +class YamlException implements Exception { + String msg; + + YamlException(this.msg); + + String toString() => msg; +} diff --git a/pkgs/yaml/lib/yaml_map.dart b/pkgs/yaml/lib/yaml_map.dart new file mode 100644 index 000000000..65dd11994 --- /dev/null +++ b/pkgs/yaml/lib/yaml_map.dart @@ -0,0 +1,110 @@ +// 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. + +part of yaml; + +/// This class wraps behaves almost identically to the normal Dart Map +/// implementation, with the following differences: +/// +/// * It allows null, NaN, boolean, list, and map keys. +/// * It defines `==` structurally. That is, `yamlMap1 == yamlMap2` if they +/// have the same contents. +/// * It has a compatible [hashCode] method. +class YamlMap implements Map { + Map _map; + + YamlMap() : _map = new Map(); + + YamlMap.from(Map map) : _map = new Map.from(map); + + YamlMap._wrap(this._map); + + bool containsValue(value) => _map.containsValue(value); + bool containsKey(key) => _map.containsKey(_wrapKey(key)); + operator [](key) => _map[_wrapKey(key)]; + operator []=(key, value) { _map[_wrapKey(key)] = value; } + putIfAbsent(key, ifAbsent()) => _map.putIfAbsent(_wrapKey(key), ifAbsent); + remove(key) => _map.remove(_wrapKey(key)); + void clear() => _map.clear(); + void forEach(void f(key, value)) => + _map.forEach((k, v) => f(_unwrapKey(k), v)); + Iterable get keys => _map.keys.mappedBy(_unwrapKey); + Iterable get values => _map.values; + int get length => _map.length; + bool get isEmpty => _map.isEmpty; + String toString() => _map.toString(); + + int get hashCode => _hashCode(_map); + + bool operator ==(other) { + if (other is! YamlMap) return false; + return deepEquals(this, other); + } + + /// Wraps an object for use as a key in the map. + _wrapKey(obj) { + if (obj != null && obj is! bool && obj is! List && + (obj is! double || !obj.isNan()) && + (obj is! Map || obj is YamlMap)) { + return obj; + } else if (obj is Map) { + return new YamlMap._wrap(obj); + } + return new _WrappedHashKey(obj); + } + + /// Unwraps an object that was used as a key in the map. + _unwrapKey(obj) => obj is _WrappedHashKey ? obj.value : obj; +} + +/// A class for wrapping normally-unhashable objects that are being used as keys +/// in a YamlMap. +class _WrappedHashKey { + var value; + + _WrappedHashKey(this.value); + + int get hashCode => _hashCode(value); + + String toString() => value.toString(); + + /// This is defined as both values being structurally equal. + bool operator ==(other) { + if (other is! _WrappedHashKey) return false; + return deepEquals(this.value, other.value); + } +} + +/// Returns the hash code for [obj]. This includes null, true, false, maps, and +/// lists. Also handles self-referential structures. +int _hashCode(obj, [List parents]) { + if (parents == null) { + parents = []; + } else if (parents.any((p) => identical(p, obj))) { + return -1; + } + + parents.add(obj); + try { + if (obj == null) return 0; + if (obj == true) return 1; + if (obj == false) return 2; + if (obj is Map) { + return _hashCode(obj.keys, parents) ^ + _hashCode(obj.values, parents); + } + if (obj is Iterable) { + // This is probably a really bad hash function, but presumably we'll get + // this in the standard library before it actually matters. + int hash = 0; + for (var e in obj) { + hash ^= _hashCode(e, parents); + } + return hash; + } + return obj.hashCode; + } finally { + parents.removeLast(); + } +} diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml new file mode 100644 index 000000000..7c944d24a --- /dev/null +++ b/pkgs/yaml/pubspec.yaml @@ -0,0 +1,7 @@ +name: yaml +author: "Dart Team " +homepage: http://www.dartlang.org +description: A parser for YAML. +dependencies: + unittest: + sdk: unittest diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart new file mode 100644 index 000000000..b939b674b --- /dev/null +++ b/pkgs/yaml/test/yaml_test.dart @@ -0,0 +1,1879 @@ +// 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 yaml_test; + +import 'package:unittest/unittest.dart'; +import 'package:yaml/yaml.dart'; +import 'package:yaml/deep_equals.dart'; +// TODO(jmesserly): we should not be reaching outside the YAML package +// The http package has a similar problem. +import '../../../tests/utils/test_utils.dart'; + +/// Constructs a new yaml.YamlMap, optionally from a normal Map. +Map yamlMap([Map from]) => + from == null ? new YamlMap() : new YamlMap.from(from); + +/// Asserts that a string containing a single YAML document produces a given +/// value when loaded. +expectYamlLoads(expected, String source) { + var actual = loadYaml(cleanUpLiteral(source)); + Expect.isTrue(deepEquals(expected, actual), + 'expectYamlLoads(expected: <$expected>, actual: <$actual>)'); +} + +/// Asserts that a string containing a stream of YAML documents produces a given +/// list of values when loaded. +expectYamlStreamLoads(List expected, String source) { + var actual = loadYamlStream(cleanUpLiteral(source)); + Expect.isTrue(deepEquals(expected, actual), + 'expectYamlStreamLoads(expected: <$expected>, actual: <$actual>)'); +} + +main() { + var infinity = double.parse("Infinity"); + var nan = double.parse("NaN"); + + group('YamlMap', () { + group('accepts as a key', () { + _expectKeyWorks(keyFn()) { + var map = yamlMap(); + map[keyFn()] = 5; + expect(map.containsKey(keyFn()), isTrue); + expect(map[keyFn()], 5); + } + + test('null', () => _expectKeyWorks(() => null)); + test('true', () => _expectKeyWorks(() => true)); + test('false', () => _expectKeyWorks(() => false)); + test('a list', () => _expectKeyWorks(() => [1, 2, 3])); + test('a map', () => _expectKeyWorks(() => {'foo': 'bar'})); + test('a YAML map', () => _expectKeyWorks(() => yamlMap({'foo': 'bar'}))); + }); + + test('works as a hash key', () { + var normalMap = new Map(); + normalMap[yamlMap({'foo': 'bar'})] = 'baz'; + expect(normalMap.containsKey(yamlMap({'foo': 'bar'})), isTrue); + expect(normalMap[yamlMap({'foo': 'bar'})], 'baz'); + }); + + test('treats YamlMap keys the same as normal maps', () { + var map = yamlMap(); + map[{'a': 'b'}] = 5; + expect(map[yamlMap({'a': 'b'})], 5); + }); + }); + + group('has a friendly error message for', () { + var tabError = predicate((e) => + e.toString().contains('tab characters are not allowed as indentation')); + + test('using a tab as indentation', () { + expect(() => loadYaml('foo:\n\tbar'), + throwsA(tabError)); + }); + + test('using a tab not as indentation', () { + expect(() => loadYaml(''' + "foo + \tbar" + error'''), + throwsA(isNot(tabError))); + }); + }); + + // The following tests are all taken directly from the YAML spec + // (http://www.yaml.org/spec/1.2/spec.html). Most of them are code examples + // that are directly included in the spec, but additional tests are derived + // from the prose. + + // A few examples from the spec are deliberately excluded, because they test + // features that this implementation doesn't intend to support (character + // encoding detection and user-defined tags). More tests are commented out, + // because they're intended to be supported but not yet implemented. + + // Chapter 2 is just a preview of various Yaml documents. It's probably not + // necessary to test its examples, but it would be nice to test everything in + // the spec. + group('2.1: Collections', () { + test('[Example 2.1]', () { + expectYamlLoads(["Mark McGwire", "Sammy Sosa", "Ken Griffey"], + """ + - Mark McGwire + - Sammy Sosa + - Ken Griffey"""); + }); + + test('[Example 2.2]', () { + expectYamlLoads({"hr": 65, "avg": 0.278, "rbi": 147}, + """ + hr: 65 # Home runs + avg: 0.278 # Batting average + rbi: 147 # Runs Batted In"""); + }); + + test('[Example 2.3]', () { + expectYamlLoads({ + "american": ["Boston Red Sox", "Detroit Tigers", "New York Yankees"], + "national": ["New York Mets", "Chicago Cubs", "Atlanta Braves"], + }, + """ + american: + - Boston Red Sox + - Detroit Tigers + - New York Yankees + national: + - New York Mets + - Chicago Cubs + - Atlanta Braves"""); + }); + + test('[Example 2.4]', () { + expectYamlLoads([ + {"name": "Mark McGwire", "hr": 65, "avg": 0.278}, + {"name": "Sammy Sosa", "hr": 63, "avg": 0.288}, + ], + """ + - + name: Mark McGwire + hr: 65 + avg: 0.278 + - + name: Sammy Sosa + hr: 63 + avg: 0.288"""); + }); + + test('[Example 2.5]', () { + expectYamlLoads([ + ["name", "hr", "avg"], + ["Mark McGwire", 65, 0.278], + ["Sammy Sosa", 63, 0.288] + ], + """ + - [name , hr, avg ] + - [Mark McGwire, 65, 0.278] + - [Sammy Sosa , 63, 0.288]"""); + }); + + test('[Example 2.6]', () { + expectYamlLoads({ + "Mark McGwire": {"hr": 65, "avg": 0.278}, + "Sammy Sosa": {"hr": 63, "avg": 0.288} + }, + """ + Mark McGwire: {hr: 65, avg: 0.278} + Sammy Sosa: { + hr: 63, + avg: 0.288 + }"""); + }); + }); + + group('2.2: Structures', () { + test('[Example 2.7]', () { + expectYamlStreamLoads([ + ["Mark McGwire", "Sammy Sosa", "Ken Griffey"], + ["Chicago Cubs", "St Louis Cardinals"] + ], + """ + # Ranking of 1998 home runs + --- + - Mark McGwire + - Sammy Sosa + - Ken Griffey + + # Team ranking + --- + - Chicago Cubs + - St Louis Cardinals"""); + }); + + test('[Example 2.8]', () { + expectYamlStreamLoads([ + {"time": "20:03:20", "player": "Sammy Sosa", "action": "strike (miss)"}, + {"time": "20:03:47", "player": "Sammy Sosa", "action": "grand slam"}, + ], + """ + --- + time: 20:03:20 + player: Sammy Sosa + action: strike (miss) + ... + --- + time: 20:03:47 + player: Sammy Sosa + action: grand slam + ..."""); + }); + + test('[Example 2.9]', () { + expectYamlLoads({ + "hr": ["Mark McGwire", "Sammy Sosa"], + "rbi": ["Sammy Sosa", "Ken Griffey"] + }, + """ + --- + hr: # 1998 hr ranking + - Mark McGwire + - Sammy Sosa + rbi: + # 1998 rbi ranking + - Sammy Sosa + - Ken Griffey"""); + }); + + // test('[Example 2.10]', () { + // expectYamlLoads({ + // "hr": ["Mark McGwire", "Sammy Sosa"], + // "rbi": ["Sammy Sosa", "Ken Griffey"] + // }, + // """ + // --- + // hr: + // - Mark McGwire + // # Following node labeled SS + // - &SS Sammy Sosa + // rbi: + // - *SS # Subsequent occurrence + // - Ken Griffey"""); + // }); + + test('[Example 2.11]', () { + var doc = yamlMap(); + doc[["Detroit Tigers", "Chicago cubs"]] = ["2001-07-23"]; + doc[["New York Yankees", "Atlanta Braves"]] = + ["2001-07-02", "2001-08-12", "2001-08-14"]; + expectYamlLoads(doc, + """ + ? - Detroit Tigers + - Chicago cubs + : + - 2001-07-23 + + ? [ New York Yankees, + Atlanta Braves ] + : [ 2001-07-02, 2001-08-12, + 2001-08-14 ]"""); + }); + + test('[Example 2.12]', () { + expectYamlLoads([ + {"item": "Super Hoop", "quantity": 1}, + {"item": "Basketball", "quantity": 4}, + {"item": "Big Shoes", "quantity": 1}, + ], + """ + --- + # Products purchased + - item : Super Hoop + quantity: 1 + - item : Basketball + quantity: 4 + - item : Big Shoes + quantity: 1"""); + }); + }); + + group('2.3: Scalars', () { + test('[Example 2.13]', () { + expectYamlLoads( + cleanUpLiteral( + """ + \\//||\\/|| + // || ||__"""), + """ + # ASCII Art + --- | + \\//||\\/|| + // || ||__"""); + }); + + test('[Example 2.14]', () { + expectYamlLoads("Mark McGwire's year was crippled by a knee injury.", + """ + --- > + Mark McGwire's + year was crippled + by a knee injury."""); + }); + + test('[Example 2.15]', () { + expectYamlLoads( + cleanUpLiteral( + """ + Sammy Sosa completed another fine season with great stats. + + 63 Home Runs + 0.288 Batting Average + + What a year!"""), + """ + > + Sammy Sosa completed another + fine season with great stats. + + 63 Home Runs + 0.288 Batting Average + + What a year!"""); + }); + + test('[Example 2.16]', () { + expectYamlLoads({ + "name": "Mark McGwire", + "accomplishment": "Mark set a major league home run record in 1998.\n", + "stats": "65 Home Runs\n0.278 Batting Average" + }, + """ + name: Mark McGwire + accomplishment: > + Mark set a major league + home run record in 1998. + stats: | + 65 Home Runs + 0.278 Batting Average"""); + }); + + test('[Example 2.17]', () { + expectYamlLoads({ + "unicode": "Sosa did fine.\u263A", + "control": "\b1998\t1999\t2000\n", + "hex esc": "\r\n is \r\n", + "single": '"Howdy!" he cried.', + "quoted": " # Not a 'comment'.", + "tie-fighter": "|\\-*-/|" + }, + """ + unicode: "Sosa did fine.\\u263A" + control: "\\b1998\\t1999\\t2000\\n" + hex esc: "\\x0d\\x0a is \\r\\n" + + single: '"Howdy!" he cried.' + quoted: ' # Not a ''comment''.' + tie-fighter: '|\\-*-/|'"""); + }); + + test('[Example 2.18]', () { + expectYamlLoads({ + "plain": "This unquoted scalar spans many lines.", + "quoted": "So does this quoted scalar.\n" + }, + ''' + plain: + This unquoted scalar + spans many lines. + + quoted: "So does this + quoted scalar.\\n"'''); + }); + }); + + group('2.4: Tags', () { + test('[Example 2.19]', () { + expectYamlLoads({ + "canonical": 12345, + "decimal": 12345, + "octal": 12, + "hexadecimal": 12 + }, + """ + canonical: 12345 + decimal: +12345 + octal: 0o14 + hexadecimal: 0xC"""); + }); + + test('[Example 2.20]', () { + expectYamlLoads({ + "canonical": 1230.15, + "exponential": 1230.15, + "fixed": 1230.15, + "negative infinity": -infinity, + "not a number": nan + }, + """ + canonical: 1.23015e+3 + exponential: 12.3015e+02 + fixed: 1230.15 + negative infinity: -.inf + not a number: .NaN"""); + }); + + test('[Example 2.21]', () { + var doc = yamlMap({ + "booleans": [true, false], + "string": "012345" + }); + doc[null] = null; + expectYamlLoads(doc, + """ + null: + booleans: [ true, false ] + string: '012345'"""); + }); + + // Examples 2.22 through 2.26 test custom tag URIs, which this + // implementation currently doesn't plan to support. + }); + + group('2.5 Full Length Example', () { + // Example 2.27 tests custom tag URIs, which this implementation currently + // doesn't plan to support. + + test('[Example 2.28]', () { + expectYamlStreamLoads([ + { + "Time": "2001-11-23 15:01:42 -5", + "User": "ed", + "Warning": "This is an error message for the log file" + }, + { + "Time": "2001-11-23 15:02:31 -5", + "User": "ed", + "Warning": "A slightly different error message." + }, + { + "DateTime": "2001-11-23 15:03:17 -5", + "User": "ed", + "Fatal": 'Unknown variable "bar"', + "Stack": [ + { + "file": "TopClass.py", + "line": 23, + "code": 'x = MoreObject("345\\n")\n' + }, + {"file": "MoreClass.py", "line": 58, "code": "foo = bar"} + ] + } + ], + """ + --- + Time: 2001-11-23 15:01:42 -5 + User: ed + Warning: + This is an error message + for the log file + --- + Time: 2001-11-23 15:02:31 -5 + User: ed + Warning: + A slightly different error + message. + --- + DateTime: 2001-11-23 15:03:17 -5 + User: ed + Fatal: + Unknown variable "bar" + Stack: + - file: TopClass.py + line: 23 + code: | + x = MoreObject("345\\n") + - file: MoreClass.py + line: 58 + code: |- + foo = bar"""); + }); + }); + + // Chapter 3 just talks about the structure of loading and dumping Yaml. + // Chapter 4 explains conventions used in the spec. + + // Chapter 5: Characters + group('5.1: Character Set', () { + expectAllowsCharacter(int charCode) { + var char = new String.fromCharCodes([charCode]); + expectYamlLoads('The character "$char" is allowed', + 'The character "$char" is allowed'); + } + + expectAllowsQuotedCharacter(int charCode) { + var char = new String.fromCharCodes([charCode]); + expectYamlLoads("The character '$char' is allowed", + '"The character \'$char\' is allowed"'); + } + + expectDisallowsCharacter(int charCode) { + var char = new String.fromCharCodes([charCode]); + Expect.throws(() => loadYaml('The character "$char" is disallowed')); + } + + test("doesn't include C0 control characters", () { + expectDisallowsCharacter(0x0); + expectDisallowsCharacter(0x8); + expectDisallowsCharacter(0x1F); + }); + + test("includes TAB", () => expectAllowsCharacter(0x9)); + test("doesn't include DEL", () => expectDisallowsCharacter(0x7F)); + + test("doesn't include C1 control characters", () { + expectDisallowsCharacter(0x80); + expectDisallowsCharacter(0x8A); + expectDisallowsCharacter(0x9F); + }); + + test("includes NEL", () => expectAllowsCharacter(0x85)); + + group("within quoted strings", () { + test("includes DEL", () => expectAllowsQuotedCharacter(0x7F)); + test("includes C1 control characters", () { + expectAllowsQuotedCharacter(0x80); + expectAllowsQuotedCharacter(0x8A); + expectAllowsQuotedCharacter(0x9F); + }); + }); + }); + + // Skipping section 5.2 (Character Encodings), since at the moment the module + // assumes that the client code is providing it with a string of the proper + // encoding. + + group('5.3: Indicator Characters', () { + test('[Example 5.3]', () { + expectYamlLoads({ + 'sequence': ['one', 'two'], + 'mapping': {'sky': 'blue', 'sea': 'green'} + }, + """ + sequence: + - one + - two + mapping: + ? sky + : blue + sea : green"""); + }); + + test('[Example 5.4]', () { + expectYamlLoads({ + 'sequence': ['one', 'two'], + 'mapping': {'sky': 'blue', 'sea': 'green'} + }, + """ + sequence: [ one, two, ] + mapping: { sky: blue, sea: green }"""); + }); + + test('[Example 5.5]', () => expectYamlLoads(null, "# Comment only.")); + + // Skipping 5.6 because it uses an undefined tag. + + test('[Example 5.7]', () { + expectYamlLoads({ + 'literal': "some\ntext\n", + 'folded': "some text\n" + }, + """ + literal: | + some + text + folded: > + some + text + """); + }); + + test('[Example 5.8]', () { + expectYamlLoads({ + 'single': "text", + 'double': "text" + }, + """ + single: 'text' + double: "text" + """); + }); + + // test('[Example 5.9]', () { + // expectYamlLoads("text", + // """ + // %YAML 1.2 + // --- text"""); + // }); + + test('[Example 5.10]', () { + Expect.throws(() => loadYaml("commercial-at: @text")); + Expect.throws(() => loadYaml("commercial-at: `text")); + }); + }); + + group('5.4: Line Break Characters', () { + group('include', () { + test('\\n', () => expectYamlLoads([1, 2], indentLiteral("- 1\n- 2"))); + test('\\r', () => expectYamlLoads([1, 2], "- 1\r- 2")); + }); + + group('do not include', () { + test('form feed', () => Expect.throws(() => loadYaml("- 1\x0C- 2"))); + test('NEL', () => expectYamlLoads(["1\x85- 2"], "- 1\x85- 2")); + test('0x2028', () => expectYamlLoads(["1\u2028- 2"], "- 1\u2028- 2")); + test('0x2029', () => expectYamlLoads(["1\u2029- 2"], "- 1\u2029- 2")); + }); + + group('in a scalar context must be normalized', () { + test("from \\r to \\n", () => + expectYamlLoads(["foo\nbar"], indentLiteral('- |\n foo\r bar'))); + test("from \\r\\n to \\n", () => + expectYamlLoads(["foo\nbar"], indentLiteral('- |\n foo\r\n bar'))); + }); + + test('[Example 5.11]', () { + expectYamlLoads( + cleanUpLiteral(""" + Line break (no glyph) + Line break (glyphed)"""), + """ + | + Line break (no glyph) + Line break (glyphed)"""); + }); + }); + + group('5.5: White Space Characters', () { + test('[Example 5.12]', () { + expectYamlLoads({ + "quoted": "Quoted \t", + "block": 'void main() {\n\tprintf("Hello, world!\\n");\n}\n' + }, + """ + # Tabs and spaces + quoted: "Quoted \t" + block:\t| + void main() { + \tprintf("Hello, world!\\n"); + } + """); + }); + }); + + group('5.7: Escaped Characters', () { + test('[Example 5.13]', () { + expectYamlLoads( + "Fun with \x5C " + "\x22 \x07 \x08 \x1B \x0C " + "\x0A \x0D \x09 \x0B \x00 " + "\x20 \xA0 \x85 \u2028 \u2029 " + "A A A", + ''' + "Fun with \\\\ + \\" \\a \\b \\e \\f \\ + \\n \\r \\t \\v \\0 \\ + \\ \\_ \\N \\L \\P \\ + \\x41 \\u0041 \\U00000041"'''); + }); + + test('[Example 5.14]', () { + Expect.throws(() => loadYaml('Bad escape: "\\c"')); + Expect.throws(() => loadYaml('Bad escape: "\\xq-"')); + }); + }); + + // Chapter 6: Basic Structures + group('6.1: Indentation Spaces', () { + test('may not include TAB characters', () { + Expect.throws(() => loadYaml(cleanUpLiteral( + """ + - + \t- foo + \t- bar"""))); + }); + + test('must be the same for all sibling nodes', () { + Expect.throws(() => loadYaml(cleanUpLiteral( + """ + - + - foo + - bar"""))); + }); + + test('may be different for the children of sibling nodes', () { + expectYamlLoads([["foo"], ["bar"]], + """ + - + - foo + - + - bar"""); + }); + + test('[Example 6.1]', () { + expectYamlLoads({ + "Not indented": { + "By one space": "By four\n spaces\n", + "Flow style": [ + "By two", + "Also by two", + "Still by two" + ] + } + }, + """ + # Leading comment line spaces are + # neither content nor indentation. + + Not indented: + By one space: | + By four + spaces + Flow style: [ # Leading spaces + By two, # in flow style + Also by two, # are neither + \tStill by two # content nor + ] # indentation."""); + }); + + test('[Example 6.2]', () { + expectYamlLoads({'a': ['b', ['c', 'd']]}, + """ + ? a + : -\tb + - -\tc + - d"""); + }); + }); + + group('6.2: Separation Spaces', () { + test('[Example 6.3]', () { + expectYamlLoads([{'foo': 'bar'}, ['baz', 'baz']], + """ + - foo:\t bar + - - baz + -\tbaz"""); + }); + }); + + group('6.3: Line Prefixes', () { + test('[Example 6.4]', () { + expectYamlLoads({ + "plain": "text lines", + "quoted": "text lines", + "block": "text\n \tlines\n" + }, + """ + plain: text + lines + quoted: "text + \tlines" + block: | + text + \tlines + """); + }); + }); + + group('6.4: Empty Lines', () { + test('[Example 6.5]', () { + expectYamlLoads({ + "Folding": "Empty line\nas a line feed", + "Chomping": "Clipped empty lines\n", + }, + """ + Folding: + "Empty line + \t + as a line feed" + Chomping: | + Clipped empty lines + """); + }); + }); + + group('6.5: Line Folding', () { + test('[Example 6.6]', () { + expectYamlLoads("trimmed\n\n\nas space", + """ + >- + trimmed + + + + as + space + """); + }); + + test('[Example 6.7]', () { + expectYamlLoads("foo \n\n\t bar\n\nbaz\n", + """ + > + foo + + \t bar + + baz + """); + }); + + test('[Example 6.8]', () { + expectYamlLoads(" foo\nbar\nbaz ", + ''' + " + foo + + \t bar + + baz + "'''); + }); + }); + + group('6.6: Comments', () { + test('must be separated from other tokens by white space characters', () { + expectYamlLoads("foo#bar", "foo#bar"); + expectYamlLoads("foo:#bar", "foo:#bar"); + expectYamlLoads("-#bar", "-#bar"); + }); + + test('[Example 6.9]', () { + expectYamlLoads({'key': 'value'}, + """ + key: # Comment + value"""); + }); + + group('outside of scalar content', () { + test('may appear on a line of their own', () { + expectYamlLoads([1, 2], + """ + - 1 + # Comment + - 2"""); + }); + + test('are independent of indentation level', () { + expectYamlLoads([[1, 2]], + """ + - + - 1 + # Comment + - 2"""); + }); + + test('include lines containing only white space characters', () { + expectYamlLoads([1, 2], + """ + - 1 + \t + - 2"""); + }); + }); + + group('within scalar content', () { + test('may not appear on a line of their own', () { + expectYamlLoads(["foo\n# not comment\nbar\n"], + """ + - | + foo + # not comment + bar + """); + }); + + test("don't include lines containing only white space characters", () { + expectYamlLoads(["foo\n \t \nbar\n"], + """ + - | + foo + \t + bar + """); + }); + }); + + test('[Example 6.10]', () { + expectYamlLoads(null, + """ + # Comment + + """); + }); + + test('[Example 6.11]', () { + expectYamlLoads({'key': 'value'}, + """ + key: # Comment + # lines + value + """); + }); + + group('ending a block scalar header', () { + test('may not be followed by additional comment lines', () { + expectYamlLoads(["# not comment\nfoo\n"], + """ + - | # comment + # not comment + foo + """); + }); + }); + }); + + group('6.7: Separation Lines', () { + test('may not be used within implicit keys', () { + Expect.throws(() => loadYaml(cleanUpLiteral( + """ + [1, + 2]: 3"""))); + }); + + test('[Example 6.12]', () { + var doc = yamlMap(); + doc[{'first': 'Sammy', 'last': 'Sosa'}] = { + 'hr': 65, + 'avg': 0.278 + }; + expectYamlLoads(doc, + """ + { first: Sammy, last: Sosa }: + # Statistics: + hr: # Home runs + 65 + avg: # Average + 0.278"""); + }); + }); + + group('6.8: Directives', () { + // // TODO(nweiz): assert that this produces a warning + // test('[Example 6.13]', () { + // expectYamlLoads("foo", + // ''' + // %FOO bar baz # Should be ignored + // # with a warning. + // --- "foo"'''); + // }); + + // // TODO(nweiz): assert that this produces a warning + // test('[Example 6.14]', () { + // expectYamlLoads("foo", + // ''' + // %YAML 1.3 # Attempt parsing + // # with a warning + // --- + // "foo"'''); + // }); + + // test('[Example 6.15]', () { + // Expect.throws(() => loadYaml(cleanUpLiteral( + // """ + // %YAML 1.2 + // %YAML 1.1 + // foo"""))); + // }); + + // test('[Example 6.16]', () { + // expectYamlLoads("foo", + // ''' + // %TAG !yaml! tag:yaml.org,2002: + // --- + // !yaml!str "foo"'''); + // }); + + // test('[Example 6.17]', () { + // Expect.throws(() => loadYaml(cleanUpLiteral( + // """ + // %TAG ! !foo + // %TAG ! !foo + // bar"""))); + // }); + + // Examples 6.18 through 6.22 test custom tag URIs, which this + // implementation currently doesn't plan to support. + }); + + group('6.9: Node Properties', () { + // test('may be specified in any order', () { + // expectYamlLoads(["foo", "bar"], + // """ + // - !!str &a1 foo + // - &a2 !!str bar"""); + // }); + + // test('[Example 6.23]', () { + // expectYamlLoads({ + // "foo": "bar", + // "baz": "foo" + // }, + // ''' + // !!str &a1 "foo": + // !!str bar + // &a2 baz : *a1'''); + // }); + + // // Example 6.24 tests custom tag URIs, which this implementation currently + // // doesn't plan to support. + + // test('[Example 6.25]', () { + // Expect.throws(() => loadYaml("- ! foo")); + // Expect.throws(() => loadYaml("- !<\$:?> foo")); + // }); + + // // Examples 6.26 and 6.27 test custom tag URIs, which this implementation + // // currently doesn't plan to support. + + // test('[Example 6.28]', () { + // expectYamlLoads(["12", 12, "12"], + // ''' + // # Assuming conventional resolution: + // - "12" + // - 12 + // - ! 12'''); + // }); + + // test('[Example 6.29]', () { + // expectYamlLoads({ + // "First occurrence": "Value", + // "Second occurrence": "anchor" + // }, + // """ + // First occurrence: &anchor Value + // Second occurrence: *anchor"""); + // }); + }); + + // Chapter 7: Flow Styles + group('7.1: Alias Nodes', () { + // test("must not use an anchor that doesn't previously occur", () { + // Expect.throws(() => loadYaml(cleanUpLiteral( + // """ + // - *anchor + // - &anchor foo""")); + // }); + + // test("don't have to exist for a given anchor node", () { + // expectYamlLoads(["foo"], "- &anchor foo"); + // }); + + // group('must not specify', () { + // test('tag properties', () => Expect.throws(() => loadYaml(cleanUpLiteral( + // """ + // - &anchor foo + // - !str *anchor"""))); + + // test('anchor properties', () => Expect.throws( + // () => loadYaml(cleanUpLiteral( + // """ + // - &anchor foo + // - &anchor2 *anchor"""))); + + // test('content', () => Expect.throws(() => loadYaml(cleanUpLiteral( + // """ + // - &anchor foo + // - *anchor bar"""))); + // }); + + // test('must preserve structural equality', () { + // var doc = loadYaml(cleanUpLiteral( + // """ + // anchor: &anchor [a, b, c] + // alias: *anchor"""); + // var anchorList = doc['anchor']; + // var aliasList = doc['alias']; + // Expect.isTrue(anchorList === aliasList); + // anchorList.add('d'); + // Expect.listEquals(['a', 'b', 'c', 'd'], aliasList); + + // doc = loadYaml(cleanUpLiteral( + // """ + // ? &anchor [a, b, c] + // : ? *anchor + // : bar"""); + // anchorList = doc.keys[0]; + // aliasList = doc[['a', 'b', 'c']].keys[0]; + // Expect.isTrue(anchorList === aliasList); + // anchorList.add('d'); + // Expect.listEquals(['a', 'b', 'c', 'd'], aliasList); + // }); + + // test('[Example 7.1]', () { + // expectYamlLoads({ + // "First occurence": "Foo", + // "Second occurence": "Foo", + // "Override anchor": "Bar", + // "Reuse anchor": "Bar", + // }, + // """ + // First occurrence: &anchor Foo + // Second occurrence: *anchor + // Override anchor: &anchor Bar + // Reuse anchor: *anchor"""); + // }); + }); + + group('7.2: Empty Nodes', () { + // test('[Example 7.2]', () { + // expectYamlLoads({ + // "foo": "", + // "": "bar" + // }, + // """ + // { + // foo : !!str, + // !!str : bar, + // }"""); + // }); + + test('[Example 7.3]', () { + var doc = yamlMap({"foo": null}); + doc[null] = "bar"; + expectYamlLoads(doc, + """ + { + ? foo :, + : bar, + }"""); + }); + }); + + group('7.3: Flow Scalar Styles', () { + test('[Example 7.4]', () { + expectYamlLoads({ + "implicit block key": [{"implicit flow key": "value"}] + }, + ''' + "implicit block key" : [ + "implicit flow key" : value, + ]'''); + }); + + test('[Example 7.5]', () { + expectYamlLoads( + "folded to a space,\nto a line feed, or \t \tnon-content", + ''' + "folded + to a space,\t + + to a line feed, or \t\\ + \\ \tnon-content"'''); + }); + + test('[Example 7.6]', () { + expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", + ''' + " 1st non-empty + + 2nd non-empty + \t3rd non-empty "'''); + }); + + test('[Example 7.7]', () { + expectYamlLoads("here's to \"quotes\"", "'here''s to \"quotes\"'"); + }); + + test('[Example 7.8]', () { + expectYamlLoads({ + "implicit block key": [{"implicit flow key": "value"}] + }, + """ + 'implicit block key' : [ + 'implicit flow key' : value, + ]"""); + }); + + test('[Example 7.9]', () { + expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", + """ + ' 1st non-empty + + 2nd non-empty + \t3rd non-empty '"""); + }); + + test('[Example 7.10]', () { + expectYamlLoads([ + "::vector", ": - ()", "Up, up, and away!", -123, + "http://example.com/foo#bar", + [ + "::vector", ": - ()", "Up, up, and away!", -123, + "http://example.com/foo#bar" + ] + ], + ''' + # Outside flow collection: + - ::vector + - ": - ()" + - Up, up, and away! + - -123 + - http://example.com/foo#bar + # Inside flow collection: + - [ ::vector, + ": - ()", + "Up, up, and away!", + -123, + http://example.com/foo#bar ]'''); + }); + + test('[Example 7.11]', () { + expectYamlLoads({ + "implicit block key": [{"implicit flow key": "value"}] + }, + """ + implicit block key : [ + implicit flow key : value, + ]"""); + }); + + test('[Example 7.12]', () { + expectYamlLoads("1st non-empty\n2nd non-empty 3rd non-empty", + """ + 1st non-empty + + 2nd non-empty + \t3rd non-empty"""); + }); + }); + + group('7.4: Flow Collection Styles', () { + test('[Example 7.13]', () { + expectYamlLoads([ + ['one', 'two'], + ['three', 'four'] + ], + """ + - [ one, two, ] + - [three ,four]"""); + }); + + test('[Example 7.14]', () { + expectYamlLoads([ + "double quoted", "single quoted", "plain text", ["nested"], + {"single": "pair"} + ], + """ + [ + "double + quoted", 'single + quoted', + plain + text, [ nested ], + single: pair, + ]"""); + }); + + test('[Example 7.15]', () { + expectYamlLoads([ + {"one": "two", "three": "four"}, + {"five": "six", "seven": "eight"}, + ], + """ + - { one : two , three: four , } + - {five: six,seven : eight}"""); + }); + + test('[Example 7.16]', () { + var doc = yamlMap({ + "explicit": "entry", + "implicit": "entry" + }); + doc[null] = null; + expectYamlLoads(doc, + """ + { + ? explicit: entry, + implicit: entry, + ? + }"""); + }); + + test('[Example 7.17]', () { + var doc = yamlMap({ + "unquoted": "separate", + "http://foo.com": null, + "omitted value": null + }); + doc[null] = "omitted key"; + expectYamlLoads(doc, + ''' + { + unquoted : "separate", + http://foo.com, + omitted value:, + : omitted key, + }'''); + }); + + test('[Example 7.18]', () { + expectYamlLoads({ + "adjacent": "value", + "readable": "value", + "empty": null + }, + ''' + { + "adjacent":value, + "readable": value, + "empty": + }'''); + }); + + test('[Example 7.19]', () { + expectYamlLoads([{"foo": "bar"}], + """ + [ + foo: bar + ]"""); + }); + + test('[Example 7.20]', () { + expectYamlLoads([{"foo bar": "baz"}], + """ + [ + ? foo + bar : baz + ]"""); + }); + + test('[Example 7.21]', () { + var el1 = yamlMap(); + el1[null] = "empty key entry"; + + var el2 = yamlMap(); + el2[{"JSON": "like"}] = "adjacent"; + + expectYamlLoads([[{"YAML": "separate"}], [el1], [el2]], + """ + - [ YAML : separate ] + - [ : empty key entry ] + - [ {JSON: like}:adjacent ]"""); + }); + + test('[Example 7.22]', () { + Expect.throws(() => loadYaml(cleanUpLiteral( + """ + [ foo + bar: invalid ]"""))); + + // TODO(nweiz): enable this when we throw an error for long keys + // var dotList = []; + // dotList.insertRange(0, 1024, ' '); + // var dots = Strings.join(dotList, ''); + // Expect.throws(() => loadYaml('[ "foo...$dots...bar": invalid ]')); + }); + }); + + group('7.5: Flow Nodes', () { + test('[Example 7.23]', () { + expectYamlLoads([["a", "b"], {"a": "b"}, "a", "b", "c"], + """ + - [ a, b ] + - { a: b } + - "a" + - 'b' + - c"""); + }); + + // test('[Example 7.24]', () { + // expectYamlLoads(["a", "b", "c", "c", ""], + // """ + // - !!str "a" + // - 'b' + // - &anchor "c" + // - *anchor + // - !!str"""); + // }); + }); + + // Chapter 8: Block Styles + group('8.1: Block Scalar Styles', () { + test('[Example 8.1]', () { + expectYamlLoads(["literal\n", " folded\n", "keep\n\n", " strip"], + """ + - | # Empty header + literal + - >1 # Indentation indicator + folded + - |+ # Chomping indicator + keep + + - >1- # Both indicators + strip"""); + }); + + test('[Example 8.2]', () { + // Note: in the spec, the fourth element in this array is listed as + // "\t detected\n", not "\t\ndetected\n". However, I'm reasonably + // confident that "\t\ndetected\n" is correct when parsed according to the + // rest of the spec. + expectYamlLoads([ + "detected\n", + "\n\n# detected\n", + " explicit\n", + "\t\ndetected\n" + ], + """ + - | + detected + - > + + + # detected + - |1 + explicit + - > + \t + detected + """); + }); + + test('[Example 8.3]', () { + Expect.throws(() => loadYaml(cleanUpLiteral( + """ + - | + + text"""))); + + Expect.throws(() => loadYaml(cleanUpLiteral( + """ + - > + text + text"""))); + + Expect.throws(() => loadYaml(cleanUpLiteral( + """ + - |2 + text"""))); + }); + + test('[Example 8.4]', () { + expectYamlLoads({"strip": "text", "clip": "text\n", "keep": "text\n"}, + """ + strip: |- + text + clip: | + text + keep: |+ + text + """); + }); + + test('[Example 8.5]', () { + // This example in the spec only includes a single newline in the "keep" + // value, but as far as I can tell that's not how it's supposed to be + // parsed according to the rest of the spec. + expectYamlLoads({ + "strip": "# text", + "clip": "# text\n", + "keep": "# text\n\n" + }, + """ + # Strip + # Comments: + strip: |- + # text + + # Clip + # comments: + + clip: | + # text + + # Keep + # comments: + + keep: |+ + # text + + # Trail + # comments. + """); + }); + + test('[Example 8.6]', () { + expectYamlLoads({"strip": "", "clip": "", "keep": "\n"}, + """ + strip: >- + + clip: > + + keep: |+ + + """); + }); + + test('[Example 8.7]', () { + expectYamlLoads("literal\n\ttext\n", + """ + | + literal + \ttext + """); + }); + + test('[Example 8.8]', () { + expectYamlLoads("\n\nliteral\n \n\ntext\n", + """ + | + + + literal + + + text + + # Comment"""); + }); + + test('[Example 8.9]', () { + expectYamlLoads("folded text\n", + """ + > + folded + text + """); + }); + + test('[Example 8.10]', () { + expectYamlLoads( + cleanUpLiteral(""" + + folded line + next line + * bullet + + * list + * lines + + last line + """), + """ + > + + folded + line + + next + line + * bullet + + * list + * lines + + last + line + + # Comment"""); + }); + + // Examples 8.11 through 8.13 are duplicates of 8.10. + }); + + group('8.2: Block Collection Styles', () { + test('[Example 8.14]', () { + expectYamlLoads({"block sequence": ["one", {"two": "three"}]}, + """ + block sequence: + - one + - two : three"""); + }); + + test('[Example 8.15]', () { + expectYamlLoads([ + null, "block node\n", ["one", "two"], {"one": "two"} + ], + """ + - # Empty + - | + block node + - - one # Compact + - two # sequence + - one: two # Compact mapping"""); + }); + + test('[Example 8.16]', () { + expectYamlLoads({"block mapping": {"key": "value"}}, + """ + block mapping: + key: value"""); + }); + + test('[Example 8.17]', () { + expectYamlLoads({ + "explicit key": null, + "block key\n": ["one", "two"] + }, + """ + ? explicit key # Empty value + ? | + block key + : - one # Explicit compact + - two # block value"""); + }); + + test('[Example 8.18]', () { + var doc = yamlMap({ + 'plain key': 'in-line value', + "quoted key": ["entry"] + }); + doc[null] = null; + expectYamlLoads(doc, + ''' + plain key: in-line value + : # Both empty + "quoted key": + - entry'''); + }); + + test('[Example 8.19]', () { + var el = yamlMap(); + el[{'earth': 'blue'}] = {'moon': 'white'}; + expectYamlLoads([{'sun': 'yellow'}, el], + """ + - sun: yellow + - ? earth: blue + : moon: white"""); + }); + + // test('[Example 8.20]', () { + // expectYamlLoads(["flow in block", "Block scalar\n", {"foo": "bar"}], + // ''' + // - + // "flow in block" + // - > + // Block scalar + // - !!map # Block collection + // foo : bar'''); + // }); + + // test('[Example 8.21]', () { + // expectYamlLoads({"literal": "value", "folded": "value"}, + // """ + // literal: |2 + // value + // folded: + // !!str + // >1 + // value"""); + // }); + + // test('[Example 8.22]', () { + // expectYamlLoads({ + // "sequence": ["entry", ["nested"]], + // "mapping": {"foo": "bar"} + // }, + // """ + // sequence: !!seq + // - entry + // - !!seq + // - nested + // mapping: !!map + // foo: bar"""); + // }); + }); + + // Chapter 9: YAML Character Stream + group('9.1: Documents', () { + // Example 9.1 tests the use of a BOM, which this implementation currently + // doesn't plan to support. + + // test('[Example 9.2]', () { + // expectYamlLoads("Document", + // """ + // %YAML 1.2 + // --- + // Document + // ... # Suffix"""); + // }); + + test('[Example 9.3]', () { + // The spec example indicates that the comment after "%!PS-Adobe-2.0" + // should be stripped, which would imply that that line is not part of the + // literal defined by the "|". The rest of the spec is ambiguous on this + // point; the allowable indentation for non-indented literal content is + // not clearly explained. However, if both the "|" and the text were + // indented the same amount, the text would be part of the literal, which + // implies that the spec's parse of this document is incorrect. + expectYamlStreamLoads( + ["Bare document", "%!PS-Adobe-2.0 # Not the first line\n"], + """ + Bare + document + ... + # No document + ... + | + %!PS-Adobe-2.0 # Not the first line + """); + }); + + test('[Example 9.4]', () { + expectYamlStreamLoads([{"matches %": 20}, null], + """ + --- + { matches + % : 20 } + ... + --- + # Empty + ..."""); + }); + + // test('[Example 9.5]', () { + // expectYamlStreamLoads(["%!PS-Adobe-2.0\n", null], + // """ + // %YAML 1.2 + // --- | + // %!PS-Adobe-2.0 + // ... + // %YAML1.2 + // --- + // # Empty + // ..."""); + // }); + + // test('[Example 9.6]', () { + // expectYamlStreamLoads(["Document", null, {"matches %": 20}], + // """ + // Document + // --- + // # Empty + // ... + // %YAML 1.2 + // --- + // matches %: 20"""); + // }); + }); + + // Chapter 10: Recommended Schemas + group('10.1: Failsafe Schema', () { + // test('[Example 10.1]', () { + // expectYamlStreamLoads({ + // "Block style": { + // "Clark": "Evans", + // "Ingy": "döt Net", + // "Oren": "Ben-Kiki" + // }, + // "Flow style": { + // "Clark": "Evans", + // "Ingy": "döt Net", + // "Oren": "Ben-Kiki" + // } + // }, + // """ + // Block style: !!map + // Clark : Evans + // Ingy : döt Net + // Oren : Ben-Kiki + + // Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }"""); + // }); + + // test('[Example 10.2]', () { + // expectYamlStreamLoads({ + // "Block style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"], + // "Flow style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"] + // }, + // """ + // Block style: !!seq + // - Clark Evans + // - Ingy döt Net + // - Oren Ben-Kiki + + // Flow style: !!seq [ Clark Evans, Ingy döt Net, Oren Ben-Kiki ]"""); + // }); + + // test('[Example 10.3]', () { + // expectYamlStreamLoads({ + // "Block style": "String: just a theory.", + // "Flow style": "String: just a theory." + // }, + // ''' + // Block style: !!str |- + // String: just a theory. + + // Flow style: !!str "String: just a theory."'''); + // }); + }); + + group('10.2: JSON Schema', () { + // test('[Example 10.4]', () { + // var doc = yamlMap({"key with null value": null}); + // doc[null] = "value for null key"; + // expectYamlStreamLoads(doc, + // """ + // !!null null: value for null key + // key with null value: !!null null"""); + // }); + + // test('[Example 10.5]', () { + // expectYamlStreamLoads({ + // "YAML is a superset of JSON": true, + // "Pluto is a planet": false + // }, + // """ + // YAML is a superset of JSON: !!bool true + // Pluto is a planet: !!bool false"""); + // }); + + // test('[Example 10.6]', () { + // expectYamlStreamLoads({ + // "negative": -12, + // "zero": 0, + // "positive": 34 + // }, + // """ + // negative: !!int -12 + // zero: !!int 0 + // positive: !!int 34"""); + // }); + + // test('[Example 10.7]', () { + // expectYamlStreamLoads({ + // "negative": -1, + // "zero": 0, + // "positive": 23000, + // "infinity": infinity, + // "not a number": nan + // }, + // """ + // negative: !!float -1 + // zero: !!float 0 + // positive: !!float 2.3e4 + // infinity: !!float .inf + // not a number: !!float .nan"""); + // }); + + // test('[Example 10.8]', () { + // expectYamlStreamLoads({ + // "A null": null, + // "Booleans": [true, false], + // "Integers": [0, -0, 3, -19], + // "Floats": [0, 0, 12000, -200000], + // // Despite being invalid in the JSON schema, these values are valid in + // // the core schema which this implementation supports. + // "Invalid": [ true, null, 7, 0x3A, 12.3] + // }, + // """ + // A null: null + // Booleans: [ true, false ] + // Integers: [ 0, -0, 3, -19 ] + // Floats: [ 0., -0.0, 12e03, -2E+05 ] + // Invalid: [ True, Null, 0o7, 0x3A, +12.3 ]"""); + // }); + }); + + group('10.3: Core Schema', () { + test('[Example 10.9]', () { + expectYamlLoads({ + "A null": null, + "Also a null": null, + "Not a null": "", + "Booleans": [true, true, false, false], + "Integers": [0, 7, 0x3A, -19], + "Floats": [0, 0, 0.5, 12000, -200000], + "Also floats": [infinity, -infinity, infinity, nan] + }, + ''' + A null: null + Also a null: # Empty + Not a null: "" + Booleans: [ true, True, false, FALSE ] + Integers: [ 0, 0o7, 0x3A, -19 ] + Floats: [ 0., -0.0, .5, +12e03, -2E+05 ] + Also floats: [ .inf, -.Inf, +.INF, .NAN ]'''); + }); + }); +} From ae52aec41930bfdbf653ad3c507b4c7130608502 Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Thu, 31 Jan 2013 12:37:13 +0000 Subject: [PATCH 002/179] Rename mappedBy to map. Retain a deprecated mappedBy for now. Change return type of mappedBy, skip and take on List to Iterable. BUG= http://dartbug.com/8063 BUG= http://dartbug.com/8064 BUG= http://dartbug.com/6739 BUG= http://dartbug.com/7982 Review URL: https://codereview.chromium.org//12086062 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@17899 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/model.dart | 6 +++--- pkgs/yaml/lib/visitor.dart | 2 +- pkgs/yaml/lib/yaml.dart | 4 ++-- pkgs/yaml/lib/yaml_map.dart | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/yaml/lib/model.dart b/pkgs/yaml/lib/model.dart index 8c111afe3..7a609b9e2 100644 --- a/pkgs/yaml/lib/model.dart +++ b/pkgs/yaml/lib/model.dart @@ -91,7 +91,7 @@ class _SequenceNode extends _Node { } String toString() => - '$tag [${Strings.join(content.mappedBy((e) => '$e'), ', ')}]'; + '$tag [${Strings.join(content.map((e) => '$e'), ', ')}]'; int get hashCode => super.hashCode ^ _hashCode(content); @@ -150,7 +150,7 @@ class _ScalarNode extends _Node { // TODO(nweiz): This could be faster if we used a RegExp to check for // special characters and short-circuited if they didn't exist. - var escapedValue = value.charCodes.mappedBy((c) { + var escapedValue = value.charCodes.map((c) { switch (c) { case _Parser.TAB: return "\\t"; case _Parser.LF: return "\\n"; @@ -223,7 +223,7 @@ class _MappingNode extends _Node { String toString() { var strContent = content.keys - .mappedBy((k) => '${k}: ${content[k]}') + .map((k) => '${k}: ${content[k]}') .join(', '); return '$tag {$strContent}'; } diff --git a/pkgs/yaml/lib/visitor.dart b/pkgs/yaml/lib/visitor.dart index b5c14c949..42dbb2273 100644 --- a/pkgs/yaml/lib/visitor.dart +++ b/pkgs/yaml/lib/visitor.dart @@ -14,7 +14,7 @@ class _Visitor { /// Visits each node in [seq] and returns a list of the results. visitSequence(_SequenceNode seq) - => seq.content.mappedBy((e) => e.visit(this)).toList(); + => seq.content.map((e) => e.visit(this)).toList(); /// Visits each key and value in [map] and returns a map of the results. visitMapping(_MappingNode map) { diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index ef0ac830b..e905e767d 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -60,8 +60,8 @@ loadYaml(String yaml) { /// are YamlMaps. These have a few small behavioral differences from the default /// Map implementation; for details, see the YamlMap class. List loadYamlStream(String yaml) { - return new _Parser(yaml).l_yamlStream().mappedBy((doc) => - new _Constructor(new _Composer(doc).compose()).construct()) + return new _Parser(yaml).l_yamlStream() + .map((doc) => new _Constructor(new _Composer(doc).compose()).construct()) .toList(); } diff --git a/pkgs/yaml/lib/yaml_map.dart b/pkgs/yaml/lib/yaml_map.dart index 65dd11994..cbf18e5d2 100644 --- a/pkgs/yaml/lib/yaml_map.dart +++ b/pkgs/yaml/lib/yaml_map.dart @@ -29,7 +29,7 @@ class YamlMap implements Map { void clear() => _map.clear(); void forEach(void f(key, value)) => _map.forEach((k, v) => f(_unwrapKey(k), v)); - Iterable get keys => _map.keys.mappedBy(_unwrapKey); + Iterable get keys => _map.keys.map(_unwrapKey); Iterable get values => _map.values; int get length => _map.length; bool get isEmpty => _map.isEmpty; From fba7cc2c377809c01f6773242d93b108dca50601 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Thu, 31 Jan 2013 14:02:27 +0000 Subject: [PATCH 003/179] Revert "Rename mappedBy to map." This reverts commit 17899. Review URL: https://codereview.chromium.org//12087103 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@17907 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/model.dart | 6 +++--- pkgs/yaml/lib/visitor.dart | 2 +- pkgs/yaml/lib/yaml.dart | 4 ++-- pkgs/yaml/lib/yaml_map.dart | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/yaml/lib/model.dart b/pkgs/yaml/lib/model.dart index 7a609b9e2..8c111afe3 100644 --- a/pkgs/yaml/lib/model.dart +++ b/pkgs/yaml/lib/model.dart @@ -91,7 +91,7 @@ class _SequenceNode extends _Node { } String toString() => - '$tag [${Strings.join(content.map((e) => '$e'), ', ')}]'; + '$tag [${Strings.join(content.mappedBy((e) => '$e'), ', ')}]'; int get hashCode => super.hashCode ^ _hashCode(content); @@ -150,7 +150,7 @@ class _ScalarNode extends _Node { // TODO(nweiz): This could be faster if we used a RegExp to check for // special characters and short-circuited if they didn't exist. - var escapedValue = value.charCodes.map((c) { + var escapedValue = value.charCodes.mappedBy((c) { switch (c) { case _Parser.TAB: return "\\t"; case _Parser.LF: return "\\n"; @@ -223,7 +223,7 @@ class _MappingNode extends _Node { String toString() { var strContent = content.keys - .map((k) => '${k}: ${content[k]}') + .mappedBy((k) => '${k}: ${content[k]}') .join(', '); return '$tag {$strContent}'; } diff --git a/pkgs/yaml/lib/visitor.dart b/pkgs/yaml/lib/visitor.dart index 42dbb2273..b5c14c949 100644 --- a/pkgs/yaml/lib/visitor.dart +++ b/pkgs/yaml/lib/visitor.dart @@ -14,7 +14,7 @@ class _Visitor { /// Visits each node in [seq] and returns a list of the results. visitSequence(_SequenceNode seq) - => seq.content.map((e) => e.visit(this)).toList(); + => seq.content.mappedBy((e) => e.visit(this)).toList(); /// Visits each key and value in [map] and returns a map of the results. visitMapping(_MappingNode map) { diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index e905e767d..ef0ac830b 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -60,8 +60,8 @@ loadYaml(String yaml) { /// are YamlMaps. These have a few small behavioral differences from the default /// Map implementation; for details, see the YamlMap class. List loadYamlStream(String yaml) { - return new _Parser(yaml).l_yamlStream() - .map((doc) => new _Constructor(new _Composer(doc).compose()).construct()) + return new _Parser(yaml).l_yamlStream().mappedBy((doc) => + new _Constructor(new _Composer(doc).compose()).construct()) .toList(); } diff --git a/pkgs/yaml/lib/yaml_map.dart b/pkgs/yaml/lib/yaml_map.dart index cbf18e5d2..65dd11994 100644 --- a/pkgs/yaml/lib/yaml_map.dart +++ b/pkgs/yaml/lib/yaml_map.dart @@ -29,7 +29,7 @@ class YamlMap implements Map { void clear() => _map.clear(); void forEach(void f(key, value)) => _map.forEach((k, v) => f(_unwrapKey(k), v)); - Iterable get keys => _map.keys.map(_unwrapKey); + Iterable get keys => _map.keys.mappedBy(_unwrapKey); Iterable get values => _map.values; int get length => _map.length; bool get isEmpty => _map.isEmpty; From c1a60bb32c9c3b1174772aefbc465f0da3350cdb Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Thu, 31 Jan 2013 15:12:56 +0000 Subject: [PATCH 004/179] Reapply "Rename mappedBy to map." This reverts commit r17907. TBR. Review URL: https://codereview.chromium.org//12090093 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@17918 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/model.dart | 6 +++--- pkgs/yaml/lib/visitor.dart | 2 +- pkgs/yaml/lib/yaml.dart | 4 ++-- pkgs/yaml/lib/yaml_map.dart | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/yaml/lib/model.dart b/pkgs/yaml/lib/model.dart index 8c111afe3..7a609b9e2 100644 --- a/pkgs/yaml/lib/model.dart +++ b/pkgs/yaml/lib/model.dart @@ -91,7 +91,7 @@ class _SequenceNode extends _Node { } String toString() => - '$tag [${Strings.join(content.mappedBy((e) => '$e'), ', ')}]'; + '$tag [${Strings.join(content.map((e) => '$e'), ', ')}]'; int get hashCode => super.hashCode ^ _hashCode(content); @@ -150,7 +150,7 @@ class _ScalarNode extends _Node { // TODO(nweiz): This could be faster if we used a RegExp to check for // special characters and short-circuited if they didn't exist. - var escapedValue = value.charCodes.mappedBy((c) { + var escapedValue = value.charCodes.map((c) { switch (c) { case _Parser.TAB: return "\\t"; case _Parser.LF: return "\\n"; @@ -223,7 +223,7 @@ class _MappingNode extends _Node { String toString() { var strContent = content.keys - .mappedBy((k) => '${k}: ${content[k]}') + .map((k) => '${k}: ${content[k]}') .join(', '); return '$tag {$strContent}'; } diff --git a/pkgs/yaml/lib/visitor.dart b/pkgs/yaml/lib/visitor.dart index b5c14c949..42dbb2273 100644 --- a/pkgs/yaml/lib/visitor.dart +++ b/pkgs/yaml/lib/visitor.dart @@ -14,7 +14,7 @@ class _Visitor { /// Visits each node in [seq] and returns a list of the results. visitSequence(_SequenceNode seq) - => seq.content.mappedBy((e) => e.visit(this)).toList(); + => seq.content.map((e) => e.visit(this)).toList(); /// Visits each key and value in [map] and returns a map of the results. visitMapping(_MappingNode map) { diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index ef0ac830b..e905e767d 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -60,8 +60,8 @@ loadYaml(String yaml) { /// are YamlMaps. These have a few small behavioral differences from the default /// Map implementation; for details, see the YamlMap class. List loadYamlStream(String yaml) { - return new _Parser(yaml).l_yamlStream().mappedBy((doc) => - new _Constructor(new _Composer(doc).compose()).construct()) + return new _Parser(yaml).l_yamlStream() + .map((doc) => new _Constructor(new _Composer(doc).compose()).construct()) .toList(); } diff --git a/pkgs/yaml/lib/yaml_map.dart b/pkgs/yaml/lib/yaml_map.dart index 65dd11994..cbf18e5d2 100644 --- a/pkgs/yaml/lib/yaml_map.dart +++ b/pkgs/yaml/lib/yaml_map.dart @@ -29,7 +29,7 @@ class YamlMap implements Map { void clear() => _map.clear(); void forEach(void f(key, value)) => _map.forEach((k, v) => f(_unwrapKey(k), v)); - Iterable get keys => _map.keys.mappedBy(_unwrapKey); + Iterable get keys => _map.keys.map(_unwrapKey); Iterable get values => _map.values; int get length => _map.length; bool get isEmpty => _map.isEmpty; From 3735d697b62b24a6968f85df97ef109d389819d8 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Tue, 19 Feb 2013 13:57:03 +0000 Subject: [PATCH 005/179] Remove deprecated Strings class. Review URL: https://codereview.chromium.org//12295014 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@18686 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/model.dart | 7 +++---- pkgs/yaml/test/yaml_test.dart | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pkgs/yaml/lib/model.dart b/pkgs/yaml/lib/model.dart index 7a609b9e2..9f1474e96 100644 --- a/pkgs/yaml/lib/model.dart +++ b/pkgs/yaml/lib/model.dart @@ -90,8 +90,7 @@ class _SequenceNode extends _Node { return true; } - String toString() => - '$tag [${Strings.join(content.map((e) => '$e'), ', ')}]'; + String toString() => '$tag [${content.map((e) => '$e').join(', ')}]'; int get hashCode => super.hashCode ^ _hashCode(content); @@ -179,7 +178,7 @@ class _ScalarNode extends _Node { } } }); - return '"${Strings.join(escapedValue, '')}"'; + return '"${escapedValue.join()}"'; } throw new YamlException("unknown scalar value: $value"); @@ -193,7 +192,7 @@ class _ScalarNode extends _Node { assert(length >= str.length); var prefix = []; prefix.insertRange(0, length - str.length, '0'); - return '${Strings.join(prefix, '')}$str'; + return '${prefix.join()}$str'; } int get hashCode => super.hashCode ^ content.hashCode; diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index b939b674b..901bd3da4 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -1350,7 +1350,7 @@ main() { // TODO(nweiz): enable this when we throw an error for long keys // var dotList = []; // dotList.insertRange(0, 1024, ' '); - // var dots = Strings.join(dotList, ''); + // var dots = dotList.join(); // Expect.throws(() => loadYaml('[ "foo...$dots...bar": invalid ]')); }); }); From 09aaae353d3b79c97f7bd10b5b2278a99054991a Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Mon, 25 Feb 2013 10:48:09 +0000 Subject: [PATCH 006/179] Remove deprecated string features. Make String.codeUnits return a List. Review URL: https://codereview.chromium.org//12282038 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@18960 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/composer.dart | 15 ++++----------- pkgs/yaml/lib/model.dart | 2 +- pkgs/yaml/lib/parser.dart | 8 ++++---- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/pkgs/yaml/lib/composer.dart b/pkgs/yaml/lib/composer.dart index e9c187969..e22159f34 100644 --- a/pkgs/yaml/lib/composer.dart +++ b/pkgs/yaml/lib/composer.dart @@ -120,12 +120,7 @@ class _Composer extends _Visitor { match = new RegExp("^0o([0-7]+)\$").firstMatch(content); if (match != null) { - // TODO(nweiz): clean this up when Dart can parse an octal string - var n = 0; - for (var c in match.group(1).charCodes) { - n *= 8; - n += c - 48; - } + int n = int.parse(match.group(1), radix: 8); return new _ScalarNode(_Tag.yaml("int"), value: n); } @@ -153,15 +148,13 @@ class _Composer extends _Visitor { match = new RegExp("^([+-]?)\.(inf|Inf|INF)\$").firstMatch(content); if (match != null) { - var infinityStr = match.group(1) == "-" ? "-Infinity" : "Infinity"; - return new _ScalarNode(_Tag.yaml("float"), - value: double.parse(infinityStr)); + var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; + return new _ScalarNode(_Tag.yaml("float"), value: value); } match = new RegExp("^\.(nan|NaN|NAN)\$").firstMatch(content); if (match != null) { - return new _ScalarNode(_Tag.yaml("float"), - value: double.parse("NaN")); + return new _ScalarNode(_Tag.yaml("float"), value: double.NAN); } return null; diff --git a/pkgs/yaml/lib/model.dart b/pkgs/yaml/lib/model.dart index 9f1474e96..5c09aa5d9 100644 --- a/pkgs/yaml/lib/model.dart +++ b/pkgs/yaml/lib/model.dart @@ -149,7 +149,7 @@ class _ScalarNode extends _Node { // TODO(nweiz): This could be faster if we used a RegExp to check for // special characters and short-circuited if they didn't exist. - var escapedValue = value.charCodes.map((c) { + var escapedValue = value.codeUnits.map((c) { switch (c) { case _Parser.TAB: return "\\t"; case _Parser.LF: return "\\n"; diff --git a/pkgs/yaml/lib/parser.dart b/pkgs/yaml/lib/parser.dart index f2f255e76..386bb5912 100644 --- a/pkgs/yaml/lib/parser.dart +++ b/pkgs/yaml/lib/parser.dart @@ -172,7 +172,7 @@ class _Parser { /// forward one character. Also updates the current line and column numbers. int next() { if (pos == len) return -1; - var char = s.charCodeAt(pos++); + var char = s.codeUnitAt(pos++); if (isBreak(char)) { line++; column = 0; @@ -193,14 +193,14 @@ class _Parser { return char; } - /// Returns the character at the current position, or the character [i] + /// Returns the code unit at the current position, or the character [i] /// characters after the current position. /// /// Returns -1 if this would return a character after the end or before the /// beginning of the input string. int peek([int i = 0]) { var peekPos = pos + i; - return (peekPos >= len || peekPos < 0) ? -1 : s.charCodeAt(peekPos); + return (peekPos >= len || peekPos < 0) ? -1 : s.codeUnitAt(peekPos); } /// The truthiness operator. Returns `false` if [obj] is `null` or `false`, @@ -304,7 +304,7 @@ class _Parser { /// /// Returns whether or not the string was consumed. bool rawString(String str) => - nAtOnce(str.length, (c, i) => str.charCodeAt(i) == c); + nAtOnce(str.length, (c, i) => str.codeUnitAt(i) == c); /// Consumes and returns a string of characters matching [matcher], or null if /// there are no such characters. From 83a0bf896564c1ba199d225fbac82d4ebba14851 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Fri, 8 Mar 2013 13:07:18 +0000 Subject: [PATCH 007/179] Remove deprecated StringBuffer.add, addAll and addCharCode. Review URL: https://codereview.chromium.org//12473003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@19690 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/parser.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/lib/parser.dart b/pkgs/yaml/lib/parser.dart index 386bb5912..c84f3741d 100644 --- a/pkgs/yaml/lib/parser.dart +++ b/pkgs/yaml/lib/parser.dart @@ -347,13 +347,13 @@ class _Parser { capturingAs = false; if (!truth(res)) return res; - capturedString.add(transformation(s.substring(captureStart, pos))); + capturedString.write(transformation(s.substring(captureStart, pos))); captureStart = pos; return res; } void flushCapture() { - capturedString.add(s.substring(captureStart, pos)); + capturedString.write(s.substring(captureStart, pos)); captureStart = pos; } From e8af83e33d05c52b09ccff7fc39493007479bdd9 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Sat, 9 Mar 2013 02:40:37 +0000 Subject: [PATCH 008/179] Remove Expect from core library. Review URL: https://codereview.chromium.org//12212016 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@19755 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/test/yaml_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 901bd3da4..6013dc945 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -4,6 +4,8 @@ library yaml_test; +// TODO(rnystrom): rewrite tests so that they don't need "Expect". +import "package:expect/expect.dart"; import 'package:unittest/unittest.dart'; import 'package:yaml/yaml.dart'; import 'package:yaml/deep_equals.dart'; From b279b10c96e4d58ca40a6622bc52ed704f151d62 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Sat, 9 Mar 2013 03:19:07 +0000 Subject: [PATCH 009/179] Revert "Remove Expect from core library." This reverts commit 19755. Review URL: https://codereview.chromium.org//12743005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@19756 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/test/yaml_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 6013dc945..901bd3da4 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -4,8 +4,6 @@ library yaml_test; -// TODO(rnystrom): rewrite tests so that they don't need "Expect". -import "package:expect/expect.dart"; import 'package:unittest/unittest.dart'; import 'package:yaml/yaml.dart'; import 'package:yaml/deep_equals.dart'; From 3bff35065ea7907e123036749d1c54c7bbc003af Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Fri, 15 Mar 2013 20:48:26 +0000 Subject: [PATCH 010/179] Fix escaping in YAML RegExp. This was causing it to try to parse "m4" as a number, which fails. Fixes dart-lang/yaml#9128. BUG= Review URL: https://codereview.chromium.org//12876003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@20107 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/composer.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgs/yaml/lib/composer.dart b/pkgs/yaml/lib/composer.dart index e22159f34..90ed3308e 100644 --- a/pkgs/yaml/lib/composer.dart +++ b/pkgs/yaml/lib/composer.dart @@ -98,13 +98,13 @@ class _Composer extends _Visitor { /// Parses a null scalar. _ScalarNode parseNull(String content) { - if (!new RegExp("^(null|Null|NULL|~|)\$").hasMatch(content)) return null; + if (!new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(content)) return null; return new _ScalarNode(_Tag.yaml("null"), value: null); } /// Parses a boolean scalar. _ScalarNode parseBool(String content) { - var match = new RegExp("^(?:(true|True|TRUE)|(false|False|FALSE))\$"). + var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"). firstMatch(content); if (match == null) return null; return new _ScalarNode(_Tag.yaml("bool"), value: match.group(1) != null); @@ -112,19 +112,19 @@ class _Composer extends _Visitor { /// Parses an integer scalar. _ScalarNode parseInt(String content) { - var match = new RegExp("^[-+]?[0-9]+\$").firstMatch(content); + var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(content); if (match != null) { return new _ScalarNode(_Tag.yaml("int"), value: int.parse(match.group(0))); } - match = new RegExp("^0o([0-7]+)\$").firstMatch(content); + match = new RegExp(r"^0o([0-7]+)$").firstMatch(content); if (match != null) { int n = int.parse(match.group(1), radix: 8); return new _ScalarNode(_Tag.yaml("int"), value: n); } - match = new RegExp("^0x[0-9a-fA-F]+\$").firstMatch(content); + match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(content); if (match != null) { return new _ScalarNode(_Tag.yaml("int"), value: int.parse(match.group(0))); @@ -136,7 +136,7 @@ class _Composer extends _Visitor { /// Parses a floating-point scalar. _ScalarNode parseFloat(String content) { var match = new RegExp( - "^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?\$"). + r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"). firstMatch(content); if (match != null) { // YAML allows floats of the form "0.", but Dart does not. Fix up those @@ -146,13 +146,13 @@ class _Composer extends _Visitor { value: double.parse(matchStr)); } - match = new RegExp("^([+-]?)\.(inf|Inf|INF)\$").firstMatch(content); + match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(content); if (match != null) { var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; return new _ScalarNode(_Tag.yaml("float"), value: value); } - match = new RegExp("^\.(nan|NaN|NAN)\$").firstMatch(content); + match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(content); if (match != null) { return new _ScalarNode(_Tag.yaml("float"), value: double.NAN); } From 131da1076db4574a79708dffbb04af83ec13ac08 Mon Sep 17 00:00:00 2001 From: "kevmoo@j832.com" Date: Wed, 20 Mar 2013 19:41:10 +0000 Subject: [PATCH 011/179] Moved pkg pubspecs to use dev_dependencies where appropriate BUG=https://code.google.com/p/dart/issues/detail?id=9309 Review URL: https://codereview.chromium.org//12962003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@20285 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/pubspec.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 7c944d24a..4b17267fc 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -2,6 +2,5 @@ name: yaml author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. -dependencies: - unittest: - sdk: unittest +dev_dependencies: + unittest: any From 3b40e0f17fb36f0c614bb4cfbc9079717600499a Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Fri, 5 Apr 2013 19:43:16 +0000 Subject: [PATCH 012/179] Remove Expect from core library. Committed: https://code.google.com/p/dart/source/detail?r=19755 Reverted: http://code.google.com/p/dart/source/detail?r=19756 Review URL: https://codereview.chromium.org//12212016 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@20996 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/test/yaml_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 901bd3da4..6013dc945 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -4,6 +4,8 @@ library yaml_test; +// TODO(rnystrom): rewrite tests so that they don't need "Expect". +import "package:expect/expect.dart"; import 'package:unittest/unittest.dart'; import 'package:yaml/yaml.dart'; import 'package:yaml/deep_equals.dart'; From 7a891ed7485df8847243141609d1ef997d9f53b8 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Fri, 12 Apr 2013 09:34:52 +0000 Subject: [PATCH 013/179] Remove Collection, Collections and clean up List/Set/Queue implementations of retain/remove. BUG= Review URL: https://codereview.chromium.org//14173003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@21338 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/parser.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/lib/parser.dart b/pkgs/yaml/lib/parser.dart index c84f3741d..9621b135d 100644 --- a/pkgs/yaml/lib/parser.dart +++ b/pkgs/yaml/lib/parser.dart @@ -1119,7 +1119,7 @@ class _Parser { }); // 138 - Collection<_Node> ns_s_flowSeqEntries(int indent, int ctx) { + Iterable<_Node> ns_s_flowSeqEntries(int indent, int ctx) { var first = ns_flowSeqEntry(indent, ctx); if (!truth(first)) return new Queue<_Node>(); zeroOrOne(() => s_separate(indent, ctx)); From b4a4288b0fdda66cfb1920be268a8ccd4c5de6ca Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Mon, 15 Apr 2013 15:20:16 +0000 Subject: [PATCH 014/179] Remove insertRange. Review URL: https://codereview.chromium.org//13956006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@21464 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/model.dart | 3 +-- pkgs/yaml/lib/parser.dart | 4 ++-- pkgs/yaml/test/yaml_test.dart | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/pkgs/yaml/lib/model.dart b/pkgs/yaml/lib/model.dart index 5c09aa5d9..ac237a020 100644 --- a/pkgs/yaml/lib/model.dart +++ b/pkgs/yaml/lib/model.dart @@ -190,8 +190,7 @@ class _ScalarNode extends _Node { /// long. String zeroPad(String str, int length) { assert(length >= str.length); - var prefix = []; - prefix.insertRange(0, length - str.length, '0'); + var prefix = new List.filled(length - str.length, '0'); return '${prefix.join()}$str'; } diff --git a/pkgs/yaml/lib/parser.dart b/pkgs/yaml/lib/parser.dart index 9621b135d..b923fe330 100644 --- a/pkgs/yaml/lib/parser.dart +++ b/pkgs/yaml/lib/parser.dart @@ -1637,7 +1637,7 @@ class _Parser { if (!truth(s_indent(indent))) return null; return c_l_blockSeqEntry(indent); })); - content.insertRange(0, 1, first); + content.insert(0, first); return new _SequenceNode("?", content); }); @@ -1720,7 +1720,7 @@ class _Parser { if (!truth(s_indent(indent))) return null; return ns_l_blockMapEntry(indent); })); - pairs.insertRange(0, 1, first); + pairs.insert(0, first); return map(pairs); }); diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 6013dc945..047c2738b 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -1350,8 +1350,7 @@ main() { bar: invalid ]"""))); // TODO(nweiz): enable this when we throw an error for long keys - // var dotList = []; - // dotList.insertRange(0, 1024, ' '); + // var dotList = new List.filled(1024, ' '); // var dots = dotList.join(); // Expect.throws(() => loadYaml('[ "foo...$dots...bar": invalid ]')); }); From 5ee6549bb74b6d3b91c0643542a785999e1e30ac Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 16 Apr 2013 20:05:22 +0000 Subject: [PATCH 015/179] Restructure the yaml package. Review URL: https://codereview.chromium.org//14103026 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@21571 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/{ => src}/composer.dart | 74 ++--- pkgs/yaml/lib/{ => src}/constructor.dart | 30 +- pkgs/yaml/lib/{ => src}/deep_equals.dart | 0 pkgs/yaml/lib/{ => src}/model.dart | 111 +++---- pkgs/yaml/lib/{ => src}/parser.dart | 360 ++++++++++++----------- pkgs/yaml/lib/src/utils.dart | 39 +++ pkgs/yaml/lib/{ => src}/visitor.dart | 15 +- pkgs/yaml/lib/src/yaml_exception.dart | 15 + pkgs/yaml/lib/{ => src}/yaml_map.dart | 46 +-- pkgs/yaml/lib/yaml.dart | 37 +-- pkgs/yaml/test/yaml_test.dart | 2 +- 11 files changed, 381 insertions(+), 348 deletions(-) rename pkgs/yaml/lib/{ => src}/composer.dart (71%) rename pkgs/yaml/lib/{ => src}/constructor.dart (71%) rename pkgs/yaml/lib/{ => src}/deep_equals.dart (100%) rename pkgs/yaml/lib/{ => src}/model.dart (68%) rename pkgs/yaml/lib/{ => src}/parser.dart (85%) create mode 100644 pkgs/yaml/lib/src/utils.dart rename pkgs/yaml/lib/{ => src}/visitor.dart (74%) create mode 100644 pkgs/yaml/lib/src/yaml_exception.dart rename pkgs/yaml/lib/{ => src}/yaml_map.dart (70%) diff --git a/pkgs/yaml/lib/composer.dart b/pkgs/yaml/lib/src/composer.dart similarity index 71% rename from pkgs/yaml/lib/composer.dart rename to pkgs/yaml/lib/src/composer.dart index 90ed3308e..40b76677e 100644 --- a/pkgs/yaml/lib/composer.dart +++ b/pkgs/yaml/lib/src/composer.dart @@ -2,41 +2,45 @@ // 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. -part of yaml; +library composer; + +import 'model.dart'; +import 'visitor.dart'; +import 'yaml_exception.dart'; /// Takes a parsed YAML document (what the spec calls the "serialization tree") /// and resolves aliases, resolves tags, and parses scalars to produce the /// "representation graph". -class _Composer extends _Visitor { +class Composer extends Visitor { /// The root node of the serialization tree. - _Node root; + final Node _root; /// Map from anchor names to the most recent representation graph node with /// that anchor. - Map anchors; + final _anchors = {}; /// The next id to use for the represenation graph's anchors. The spec doesn't /// use anchors in the representation graph, but we do so that the constructor /// can ensure that the same node in the representation graph produces the /// same native object. - int idCounter; + var _idCounter = 0; - _Composer(this.root) : this.anchors = {}, this.idCounter = 0; + Composer(this._root); /// Runs the Composer to produce a representation graph. - _Node compose() => root.visit(this); + Node compose() => _root.visit(this); /// Returns the anchor to which an alias node refers. - _Node visitAlias(_AliasNode alias) { - if (!anchors.containsKey(alias.anchor)) { + Node visitAlias(AliasNode alias) { + if (!_anchors.containsKey(alias.anchor)) { throw new YamlException("no anchor for alias ${alias.anchor}"); } - return anchors[alias.anchor]; + return _anchors[alias.anchor]; } /// Parses a scalar node according to its tag, or auto-detects the type if no /// tag exists. Currently this only supports the YAML core type schema. - _Node visitScalar(_ScalarNode scalar) { + Node visitScalar(ScalarNode scalar) { if (scalar.tag.name == "!") { return setAnchor(scalar, parseString(scalar.content)); } else if (scalar.tag.name == "?") { @@ -54,7 +58,7 @@ class _Composer extends _Visitor { }; for (var key in tagParsers.keys) { - if (scalar.tag.name != _Tag.yaml(key)) continue; + if (scalar.tag.name != Tag.yaml(key)) continue; var result = tagParsers[key](scalar.content); if (result != null) return setAnchor(scalar, result); throw new YamlException('invalid literal for $key: "${scalar.content}"'); @@ -64,69 +68,69 @@ class _Composer extends _Visitor { } /// Assigns a tag to the sequence and recursively composes its contents. - _Node visitSequence(_SequenceNode seq) { + Node visitSequence(SequenceNode seq) { var tagName = seq.tag.name; - if (tagName != "!" && tagName != "?" && tagName != _Tag.yaml("seq")) { + if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("seq")) { throw new YamlException("invalid tag for sequence: ${tagName}"); } - var result = setAnchor(seq, new _SequenceNode(_Tag.yaml("seq"), null)); + var result = setAnchor(seq, new SequenceNode(Tag.yaml("seq"), null)); result.content = super.visitSequence(seq); return result; } /// Assigns a tag to the mapping and recursively composes its contents. - _Node visitMapping(_MappingNode map) { + Node visitMapping(MappingNode map) { var tagName = map.tag.name; - if (tagName != "!" && tagName != "?" && tagName != _Tag.yaml("map")) { + if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("map")) { throw new YamlException("invalid tag for mapping: ${tagName}"); } - var result = setAnchor(map, new _MappingNode(_Tag.yaml("map"), null)); + var result = setAnchor(map, new MappingNode(Tag.yaml("map"), null)); result.content = super.visitMapping(map); return result; } /// If the serialization tree node [anchored] has an anchor, records that /// that anchor is pointing to the representation graph node [result]. - _Node setAnchor(_Node anchored, _Node result) { + Node setAnchor(Node anchored, Node result) { if (anchored.anchor == null) return result; - result.anchor = '${idCounter++}'; - anchors[anchored.anchor] = result; + result.anchor = '${_idCounter++}'; + _anchors[anchored.anchor] = result; return result; } /// Parses a null scalar. - _ScalarNode parseNull(String content) { + ScalarNode parseNull(String content) { if (!new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(content)) return null; - return new _ScalarNode(_Tag.yaml("null"), value: null); + return new ScalarNode(Tag.yaml("null"), value: null); } /// Parses a boolean scalar. - _ScalarNode parseBool(String content) { + ScalarNode parseBool(String content) { var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"). firstMatch(content); if (match == null) return null; - return new _ScalarNode(_Tag.yaml("bool"), value: match.group(1) != null); + return new ScalarNode(Tag.yaml("bool"), value: match.group(1) != null); } /// Parses an integer scalar. - _ScalarNode parseInt(String content) { + ScalarNode parseInt(String content) { var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(content); if (match != null) { - return new _ScalarNode(_Tag.yaml("int"), + return new ScalarNode(Tag.yaml("int"), value: int.parse(match.group(0))); } match = new RegExp(r"^0o([0-7]+)$").firstMatch(content); if (match != null) { int n = int.parse(match.group(1), radix: 8); - return new _ScalarNode(_Tag.yaml("int"), value: n); + return new ScalarNode(Tag.yaml("int"), value: n); } match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(content); if (match != null) { - return new _ScalarNode(_Tag.yaml("int"), + return new ScalarNode(Tag.yaml("int"), value: int.parse(match.group(0))); } @@ -134,7 +138,7 @@ class _Composer extends _Visitor { } /// Parses a floating-point scalar. - _ScalarNode parseFloat(String content) { + ScalarNode parseFloat(String content) { var match = new RegExp( r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"). firstMatch(content); @@ -142,25 +146,25 @@ class _Composer extends _Visitor { // YAML allows floats of the form "0.", but Dart does not. Fix up those // floats by removing the trailing dot. var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), ""); - return new _ScalarNode(_Tag.yaml("float"), + return new ScalarNode(Tag.yaml("float"), value: double.parse(matchStr)); } match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(content); if (match != null) { var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; - return new _ScalarNode(_Tag.yaml("float"), value: value); + return new ScalarNode(Tag.yaml("float"), value: value); } match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(content); if (match != null) { - return new _ScalarNode(_Tag.yaml("float"), value: double.NAN); + return new ScalarNode(Tag.yaml("float"), value: double.NAN); } return null; } /// Parses a string scalar. - _ScalarNode parseString(String content) => - new _ScalarNode(_Tag.yaml("str"), value: content); + ScalarNode parseString(String content) => + new ScalarNode(Tag.yaml("str"), value: content); } diff --git a/pkgs/yaml/lib/constructor.dart b/pkgs/yaml/lib/src/constructor.dart similarity index 71% rename from pkgs/yaml/lib/constructor.dart rename to pkgs/yaml/lib/src/constructor.dart index 73a62a86f..428c476e5 100644 --- a/pkgs/yaml/lib/constructor.dart +++ b/pkgs/yaml/lib/src/constructor.dart @@ -2,28 +2,32 @@ // 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. -part of yaml; +library constructor; + +import 'model.dart'; +import 'visitor.dart'; +import 'yaml_map.dart'; /// Takes a parsed and composed YAML document (what the spec calls the /// "representation graph") and creates native Dart objects that represent that /// document. -class _Constructor extends _Visitor { +class Constructor extends Visitor { /// The root node of the representation graph. - _Node root; + final Node _root; /// Map from anchor names to the most recent Dart node with that anchor. - Map anchors; + final _anchors = {}; - _Constructor(this.root) : this.anchors = {}; + Constructor(this._root); /// Runs the Constructor to produce a Dart object. - construct() => root.visit(this); + construct() => _root.visit(this); /// Returns the value of a scalar. - visitScalar(_ScalarNode scalar) => scalar.value; + visitScalar(ScalarNode scalar) => scalar.value; /// Converts a sequence into a List of Dart objects. - visitSequence(_SequenceNode seq) { + visitSequence(SequenceNode seq) { var anchor = getAnchor(seq); if (anchor != null) return anchor; var dartSeq = setAnchor(seq, []); @@ -32,7 +36,7 @@ class _Constructor extends _Visitor { } /// Converts a mapping into a Map of Dart objects. - visitMapping(_MappingNode map) { + visitMapping(MappingNode map) { var anchor = getAnchor(map); if (anchor != null) return anchor; var dartMap = setAnchor(map, new YamlMap()); @@ -42,15 +46,15 @@ class _Constructor extends _Visitor { /// Returns the Dart object that already represents [anchored], if such a /// thing exists. - getAnchor(_Node anchored) { + getAnchor(Node anchored) { if (anchored.anchor == null) return null; - if (anchors.containsKey(anchored.anchor)) return anchors[anchored.anchor]; + if (_anchors.containsKey(anchored.anchor)) return _anchors[anchored.anchor]; } /// Records that [value] is the Dart object representing [anchored]. - setAnchor(_Node anchored, value) { + setAnchor(Node anchored, value) { if (anchored.anchor == null) return value; - anchors[anchored.anchor] = value; + _anchors[anchored.anchor] = value; return value; } } diff --git a/pkgs/yaml/lib/deep_equals.dart b/pkgs/yaml/lib/src/deep_equals.dart similarity index 100% rename from pkgs/yaml/lib/deep_equals.dart rename to pkgs/yaml/lib/src/deep_equals.dart diff --git a/pkgs/yaml/lib/model.dart b/pkgs/yaml/lib/src/model.dart similarity index 68% rename from pkgs/yaml/lib/model.dart rename to pkgs/yaml/lib/src/model.dart index ac237a020..d7ee4814d 100644 --- a/pkgs/yaml/lib/model.dart +++ b/pkgs/yaml/lib/src/model.dart @@ -2,14 +2,19 @@ // 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. -part of yaml; +/// This file contains the node classes for the internal representations of YAML +/// documents. These nodes are used for both the serialization tree and the +/// representation graph. +library model; -// This file contains the node classes for the internal representations of YAML -// documents. These nodes are used for both the serialization tree and the -// representation graph. +import 'model.dart'; +import 'parser.dart'; +import 'utils.dart'; +import 'visitor.dart'; +import 'yaml_exception.dart'; /// A tag that indicates the type of a YAML node. -class _Tag { +class Tag { // TODO(nweiz): it would better match the semantics of the spec if there were // a singleton instance of this class for each tag. @@ -25,18 +30,18 @@ class _Tag { /// The kind of the tag: SCALAR_KIND, SEQUENCE_KIND, or MAPPING_KIND. final int kind; - _Tag(this.name, this.kind); + Tag(this.name, this.kind); - _Tag.scalar(String name) : this(name, SCALAR_KIND); - _Tag.sequence(String name) : this(name, SEQUENCE_KIND); - _Tag.mapping(String name) : this(name, MAPPING_KIND); + Tag.scalar(String name) : this(name, SCALAR_KIND); + Tag.sequence(String name) : this(name, SEQUENCE_KIND); + Tag.mapping(String name) : this(name, MAPPING_KIND); /// Returns the standard YAML tag URI for [type]. static String yaml(String type) => "tag:yaml.org,2002:$type"; /// Two tags are equal if their URIs are equal. operator ==(other) { - if (other is! _Tag) return false; + if (other is! Tag) return false; return name == other.name; } @@ -52,37 +57,37 @@ class _Tag { } /// The abstract class for YAML nodes. -abstract class _Node { +abstract class Node { /// Every YAML node has a tag that describes its type. - _Tag tag; + Tag tag; /// Any YAML node can have an anchor associated with it. String anchor; - _Node(this.tag, [this.anchor]); + Node(this.tag, [this.anchor]); bool operator ==(other) { - if (other is! _Node) return false; + if (other is! Node) return false; return tag == other.tag; } - int get hashCode => _hashCode([tag, anchor]); + int get hashCode => hashCodeFor([tag, anchor]); - visit(_Visitor v); + visit(Visitor v); } /// A sequence node represents an ordered list of nodes. -class _SequenceNode extends _Node { +class SequenceNode extends Node { /// The nodes in the sequence. - List<_Node> content; + List content; - _SequenceNode(String tagName, this.content) - : super(new _Tag.sequence(tagName)); + SequenceNode(String tagName, this.content) + : super(new Tag.sequence(tagName)); /// Two sequences are equal if their tags and contents are equal. bool operator ==(other) { // Should be super != other; bug 2554 - if (!(super == other) || other is! _SequenceNode) return false; + if (!(super == other) || other is! SequenceNode) return false; if (content.length != other.content.length) return false; for (var i = 0; i < content.length; i++) { if (content[i] != other.content[i]) return false; @@ -92,20 +97,20 @@ class _SequenceNode extends _Node { String toString() => '$tag [${content.map((e) => '$e').join(', ')}]'; - int get hashCode => super.hashCode ^ _hashCode(content); + int get hashCode => super.hashCode ^ hashCodeFor(content); - visit(_Visitor v) => v.visitSequence(this); + visit(Visitor v) => v.visitSequence(this); } /// An alias node is a reference to an anchor. -class _AliasNode extends _Node { - _AliasNode(String anchor) : super(new _Tag.scalar(_Tag.yaml("str")), anchor); +class AliasNode extends Node { + AliasNode(String anchor) : super(new Tag.scalar(Tag.yaml("str")), anchor); - visit(_Visitor v) => v.visitAlias(this); + visit(Visitor v) => v.visitAlias(this); } /// A scalar node represents all YAML nodes that have a single value. -class _ScalarNode extends _Node { +class ScalarNode extends Node { /// The string value of the scalar node, if it was created by the parser. final String _content; @@ -118,14 +123,14 @@ class _ScalarNode extends _Node { /// be specified for a newly-parsed scalar that hasn't yet been composed. /// Value should be specified for a composed scalar, although `null` is a /// valid value. - _ScalarNode(String tagName, {String content, this.value}) + ScalarNode(String tagName, {String content, this.value}) : _content = content, - super(new _Tag.scalar(tagName)); + super(new Tag.scalar(tagName)); /// Two scalars are equal if their string representations are equal. bool operator ==(other) { // Should be super != other; bug 2554 - if (!(super == other) || other is! _ScalarNode) return false; + if (!(super == other) || other is! ScalarNode) return false; return content == other.content; } @@ -151,21 +156,21 @@ class _ScalarNode extends _Node { var escapedValue = value.codeUnits.map((c) { switch (c) { - case _Parser.TAB: return "\\t"; - case _Parser.LF: return "\\n"; - case _Parser.CR: return "\\r"; - case _Parser.DOUBLE_QUOTE: return '\\"'; - case _Parser.NULL: return "\\0"; - case _Parser.BELL: return "\\a"; - case _Parser.BACKSPACE: return "\\b"; - case _Parser.VERTICAL_TAB: return "\\v"; - case _Parser.FORM_FEED: return "\\f"; - case _Parser.ESCAPE: return "\\e"; - case _Parser.BACKSLASH: return "\\\\"; - case _Parser.NEL: return "\\N"; - case _Parser.NBSP: return "\\_"; - case _Parser.LINE_SEPARATOR: return "\\L"; - case _Parser.PARAGRAPH_SEPARATOR: return "\\P"; + case Parser.TAB: return "\\t"; + case Parser.LF: return "\\n"; + case Parser.CR: return "\\r"; + case Parser.DOUBLE_QUOTE: return '\\"'; + case Parser.NULL: return "\\0"; + case Parser.BELL: return "\\a"; + case Parser.BACKSPACE: return "\\b"; + case Parser.VERTICAL_TAB: return "\\v"; + case Parser.FORM_FEED: return "\\f"; + case Parser.ESCAPE: return "\\e"; + case Parser.BACKSLASH: return "\\\\"; + case Parser.NEL: return "\\N"; + case Parser.NBSP: return "\\_"; + case Parser.LINE_SEPARATOR: return "\\L"; + case Parser.PARAGRAPH_SEPARATOR: return "\\P"; default: if (c < 0x20 || (c >= 0x7f && c < 0x100)) { return "\\x${zeroPad(c.toRadixString(16).toUpperCase(), 2)}"; @@ -196,21 +201,21 @@ class _ScalarNode extends _Node { int get hashCode => super.hashCode ^ content.hashCode; - visit(_Visitor v) => v.visitScalar(this); + visit(Visitor v) => v.visitScalar(this); } /// A mapping node represents an unordered map of nodes to nodes. -class _MappingNode extends _Node { +class MappingNode extends Node { /// The node map. - Map<_Node, _Node> content; + Map content; - _MappingNode(String tagName, this.content) - : super(new _Tag.mapping(tagName)); + MappingNode(String tagName, this.content) + : super(new Tag.mapping(tagName)); /// Two mappings are equal if their tags and contents are equal. bool operator ==(other) { // Should be super != other; bug 2554 - if (!(super == other) || other is! _MappingNode) return false; + if (!(super == other) || other is! MappingNode) return false; if (content.length != other.content.length) return false; for (var key in content.keys) { if (!other.content.containsKey(key)) return false; @@ -226,7 +231,7 @@ class _MappingNode extends _Node { return '$tag {$strContent}'; } - int get hashCode => super.hashCode ^ _hashCode(content); + int get hashCode => super.hashCode ^ hashCodeFor(content); - visit(_Visitor v) => v.visitMapping(this); + visit(Visitor v) => v.visitMapping(this); } diff --git a/pkgs/yaml/lib/parser.dart b/pkgs/yaml/lib/src/parser.dart similarity index 85% rename from pkgs/yaml/lib/parser.dart rename to pkgs/yaml/lib/src/parser.dart index b923fe330..2616038ee 100644 --- a/pkgs/yaml/lib/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -2,7 +2,13 @@ // 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. -part of yaml; +library parser; + +import 'dart:collection'; + +import 'model.dart'; +import 'yaml_exception.dart'; +import 'yaml_map.dart'; /// Translates a string of characters into a YAML serialization tree. /// @@ -17,7 +23,7 @@ part of yaml; /// named `nb-ns-plain-in-line`, and the method implementing it is named /// `nb_ns_plainInLine`. The exception to that rule is methods that just /// recognize character classes; these are named `is*`. -class _Parser { +class Parser { static const TAB = 0x9; static const LF = 0xA; static const CR = 0xD; @@ -111,84 +117,84 @@ class _Parser { static const CHOMPING_CLIP = 2; /// The source string being parsed. - final String s; + final String _s; /// The current position in the source string. - int pos = 0; + int _pos = 0; /// The length of the string being parsed. - final int len; + final int _len; /// The current (0-based) line in the source string. - int line = 0; + int _line = 0; /// The current (0-based) column in the source string. - int column = 0; + int _column = 0; /// Whether we're parsing a bare document (that is, one that doesn't begin /// with `---`). Bare documents don't allow `%` immediately following /// newlines. - bool inBareDocument = false; + bool _inBareDocument = false; /// The line number of the farthest position that has been parsed successfully /// before backtracking. Used for error reporting. - int farthestLine = 0; + int _farthestLine = 0; /// The column number of the farthest position that has been parsed /// successfully before backtracking. Used for error reporting. - int farthestColumn = 0; + int _farthestColumn = 0; /// The farthest position in the source string that has been parsed /// successfully before backtracking. Used for error reporting. - int farthestPos = 0; + int _farthestPos = 0; /// The name of the context of the farthest position that has been parsed /// successfully before backtracking. Used for error reporting. - String farthestContext = "document"; + String _farthestContext = "document"; /// A stack of the names of parse contexts. Used for error reporting. - List contextStack; + List _contextStack; /// Annotations attached to ranges of the source string that add extra /// information to any errors that occur in the annotated range. - _RangeMap errorAnnotations; + _RangeMap _errorAnnotations; /// The buffer containing the string currently being captured. - StringBuffer capturedString; + StringBuffer _capturedString; /// The beginning of the current section of the captured string. - int captureStart; + int _captureStart; /// Whether the current string capture is being overridden. - bool capturingAs = false; + bool _capturingAs = false; - _Parser(String s) - : this.s = s, - len = s.length, - contextStack = ["document"], - errorAnnotations = new _RangeMap(); + Parser(String s) + : this._s = s, + _len = s.length, + _contextStack = ["document"], + _errorAnnotations = new _RangeMap(); /// Return the character at the current position, then move that position /// forward one character. Also updates the current line and column numbers. int next() { - if (pos == len) return -1; - var char = s.codeUnitAt(pos++); + if (_pos == _len) return -1; + var char = _s.codeUnitAt(_pos++); if (isBreak(char)) { - line++; - column = 0; + _line++; + _column = 0; } else { - column++; + _column++; } - if (farthestLine < line) { - farthestLine = line; - farthestColumn = column; - farthestContext = contextStack.last; - } else if (farthestLine == line && farthestColumn < column) { - farthestColumn = column; - farthestContext = contextStack.last; + if (_farthestLine < _line) { + _farthestLine = _line; + _farthestColumn = _column; + _farthestContext = _contextStack.last; + } else if (_farthestLine == _line && _farthestColumn < _column) { + _farthestColumn = _column; + _farthestContext = _contextStack.last; } - farthestPos = pos; + _farthestPos = _pos; return char; } @@ -199,8 +205,8 @@ class _Parser { /// Returns -1 if this would return a character after the end or before the /// beginning of the input string. int peek([int i = 0]) { - var peekPos = pos + i; - return (peekPos >= len || peekPos < 0) ? -1 : s.codeUnitAt(peekPos); + var peekPos = _pos + i; + return (peekPos >= _len || peekPos < 0) ? -1 : _s.codeUnitAt(peekPos); } /// The truthiness operator. Returns `false` if [obj] is `null` or `false`, @@ -243,11 +249,11 @@ class _Parser { /// Conceptually, repeats a production any number of times. List zeroOrMore(consumer()) { var out = []; - var oldPos = pos; + var oldPos = _pos; while (true) { var el = consumer(); - if (!truth(el) || oldPos == pos) return out; - oldPos = pos; + if (!truth(el) || oldPos == _pos) return out; + oldPos = _pos; out.add(el); } return null; // Unreachable. @@ -270,20 +276,20 @@ class _Parser { /// Calls [consumer] and returns its result, but rolls back the parser state /// if [consumer] returns a falsey value. transaction(consumer()) { - var oldPos = pos; - var oldLine = line; - var oldColumn = column; - var oldCaptureStart = captureStart; - String capturedSoFar = capturedString == null ? null : - capturedString.toString(); + var oldPos = _pos; + var oldLine = _line; + var oldColumn = _column; + var oldCaptureStart = _captureStart; + String capturedSoFar = _capturedString == null ? null : + _capturedString.toString(); var res = consumer(); if (truth(res)) return res; - pos = oldPos; - line = oldLine; - column = oldColumn; - captureStart = oldCaptureStart; - capturedString = capturedSoFar == null ? null : + _pos = oldPos; + _line = oldLine; + _column = oldColumn; + _captureStart = oldCaptureStart; + _capturedString = capturedSoFar == null ? null : new StringBuffer(capturedSoFar); return res; } @@ -316,21 +322,21 @@ class _Parser { /// [consumer] in `transaction`. String captureString(consumer()) { // captureString calls may not be nested - assert(capturedString == null); + assert(_capturedString == null); - captureStart = pos; - capturedString = new StringBuffer(); + _captureStart = _pos; + _capturedString = new StringBuffer(); var res = transaction(consumer); if (!truth(res)) { - captureStart = null; - capturedString = null; + _captureStart = null; + _capturedString = null; return null; } flushCapture(); - var result = capturedString.toString(); - captureStart = null; - capturedString = null; + var result = _capturedString.toString(); + _captureStart = null; + _capturedString = null; return result; } @@ -338,27 +344,27 @@ class _Parser { captureAndTransform(consumer, (_) => replacement); captureAndTransform(consumer(), String transformation(String captured)) { - if (capturedString == null) return consumer(); - if (capturingAs) return consumer(); + if (_capturedString == null) return consumer(); + if (_capturingAs) return consumer(); flushCapture(); - capturingAs = true; + _capturingAs = true; var res = consumer(); - capturingAs = false; + _capturingAs = false; if (!truth(res)) return res; - capturedString.write(transformation(s.substring(captureStart, pos))); - captureStart = pos; + _capturedString.write(transformation(_s.substring(_captureStart, _pos))); + _captureStart = _pos; return res; } void flushCapture() { - capturedString.write(s.substring(captureStart, pos)); - captureStart = pos; + _capturedString.write(_s.substring(_captureStart, _pos)); + _captureStart = _pos; } /// Adds a tag and an anchor to [node], if they're defined. - _Node addProps(_Node node, _Pair<_Tag, String> props) { + Node addProps(Node node, _Pair props) { if (props == null || node == null) return node; if (truth(props.first)) node.tag = props.first; if (truth(props.last)) node.anchor = props.last; @@ -366,19 +372,19 @@ class _Parser { } /// Creates a MappingNode from [pairs]. - _MappingNode map(List<_Pair<_Node, _Node>> pairs) { - var content = new Map<_Node, _Node>(); + MappingNode map(List<_Pair> pairs) { + var content = new Map(); pairs.forEach((pair) => content[pair.first] = pair.last); - return new _MappingNode("?", content); + return new MappingNode("?", content); } /// Runs [fn] in a context named [name]. Used for error reporting. context(String name, fn()) { try { - contextStack.add(name); + _contextStack.add(name); return fn(); } finally { - var popped = contextStack.removeLast(); + var popped = _contextStack.removeLast(); assert(popped == name); } } @@ -387,21 +393,21 @@ class _Parser { /// current position and the position of the cursor after running [fn]. The /// cursor is reset after [fn] is run. annotateError(String message, fn()) { - var start = pos; + var start = _pos; var end; transaction(() { fn(); - end = pos; + end = _pos; return false; }); - errorAnnotations[new _Range(start, end)] = message; + _errorAnnotations[new _Range(start, end)] = message; } /// Throws an error with additional context information. error(String message) { // Line and column should be one-based. - throw new SyntaxError(line + 1, column + 1, - "$message (in $farthestContext)"); + throw new SyntaxError(_line + 1, _column + 1, + "$message (in $_farthestContext)"); } /// If [result] is falsey, throws an error saying that [expected] was @@ -411,13 +417,13 @@ class _Parser { error("expected $expected"); } - /// Throws an error saying that the parse failed. Uses [farthestLine], - /// [farthestColumn], and [farthestContext] to provide additional information. + /// Throws an error saying that the parse failed. Uses [_farthestLine], + /// [_farthestColumn], and [_farthestContext] to provide additional information. parseFailed() { - var message = "invalid YAML in $farthestContext"; - var extraError = errorAnnotations[farthestPos]; + var message = "invalid YAML in $_farthestContext"; + var extraError = _errorAnnotations[_farthestPos]; if (extraError != null) message = "$message ($extraError)"; - throw new SyntaxError(farthestLine + 1, farthestColumn + 1, message); + throw new SyntaxError(_farthestLine + 1, _farthestColumn + 1, message); } /// Returns the number of spaces after the current position. @@ -439,7 +445,7 @@ class _Parser { spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length; if (spaces > maxSpaces) { maxSpaces = spaces; - maxSpacesLine = line; + maxSpacesLine = _line; } } while (b_break()); return false; @@ -462,10 +468,10 @@ class _Parser { } /// Returns whether the current position is at the beginning of a line. - bool get atStartOfLine => column == 0; + bool get atStartOfLine => _column == 0; /// Returns whether the current position is at the end of the input. - bool get atEndOfFile => pos == len; + bool get atEndOfFile => _pos == _len; /// Given an indicator character, returns the type of that indicator (or null /// if the indicator isn't found. @@ -796,7 +802,7 @@ class _Parser { bool l_directive() => false; // TODO(nweiz): implement // 96 - _Pair<_Tag, String> c_ns_properties(int indent, int ctx) { + _Pair c_ns_properties(int indent, int ctx) { var tag, anchor; tag = c_ns_tagProperty(); if (truth(tag)) { @@ -804,7 +810,7 @@ class _Parser { if (!truth(s_separate(indent, ctx))) return null; return c_ns_anchorProperty(); }); - return new _Pair<_Tag, String>(tag, anchor); + return new _Pair(tag, anchor); } anchor = c_ns_anchorProperty(); @@ -813,14 +819,14 @@ class _Parser { if (!truth(s_separate(indent, ctx))) return null; return c_ns_tagProperty(); }); - return new _Pair<_Tag, String>(tag, anchor); + return new _Pair(tag, anchor); } return null; } // 97 - _Tag c_ns_tagProperty() => null; // TODO(nweiz): implement + Tag c_ns_tagProperty() => null; // TODO(nweiz): implement // 101 String c_ns_anchorProperty() => null; // TODO(nweiz): implement @@ -833,17 +839,17 @@ class _Parser { captureString(() => oneOrMore(() => consume(isAnchorChar))); // 104 - _Node c_ns_aliasNode() { + Node c_ns_aliasNode() { if (!truth(c_indicator(C_ALIAS))) return null; var name = expect(ns_anchorName(), 'anchor name'); - return new _AliasNode(name); + return new AliasNode(name); } // 105 - _ScalarNode e_scalar() => new _ScalarNode("?", content: ""); + ScalarNode e_scalar() => new ScalarNode("?", content: ""); // 106 - _ScalarNode e_node() => e_scalar(); + ScalarNode e_node() => e_scalar(); // 107 bool nb_doubleChar() => or([ @@ -855,12 +861,12 @@ class _Parser { bool ns_doubleChar() => !isSpace(peek()) && truth(nb_doubleChar()); // 109 - _Node c_doubleQuoted(int indent, int ctx) => context('string', () { + Node c_doubleQuoted(int indent, int ctx) => context('string', () { return transaction(() { if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; var contents = nb_doubleText(indent, ctx); if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; - return new _ScalarNode("!", content: contents); + return new ScalarNode("!", content: contents); }); }); @@ -943,12 +949,12 @@ class _Parser { bool ns_singleChar() => !isSpace(peek()) && truth(nb_singleChar()); // 120 - _Node c_singleQuoted(int indent, int ctx) => context('string', () { + Node c_singleQuoted(int indent, int ctx) => context('string', () { return transaction(() { if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; var contents = nb_singleText(indent, ctx); if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; - return new _ScalarNode("!", content: contents); + return new ScalarNode("!", content: contents); }); }); @@ -1110,18 +1116,18 @@ class _Parser { } // 137 - _SequenceNode c_flowSequence(int indent, int ctx) => transaction(() { + SequenceNode c_flowSequence(int indent, int ctx) => transaction(() { if (!truth(c_indicator(C_SEQUENCE_START))) return null; zeroOrOne(() => s_separate(indent, ctx)); var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx))); if (!truth(c_indicator(C_SEQUENCE_END))) return null; - return new _SequenceNode("?", new List<_Node>.from(content)); + return new SequenceNode("?", new List.from(content)); }); // 138 - Iterable<_Node> ns_s_flowSeqEntries(int indent, int ctx) { + Iterable ns_s_flowSeqEntries(int indent, int ctx) { var first = ns_flowSeqEntry(indent, ctx); - if (!truth(first)) return new Queue<_Node>(); + if (!truth(first)) return new Queue(); zeroOrOne(() => s_separate(indent, ctx)); var rest; @@ -1130,25 +1136,25 @@ class _Parser { rest = zeroOrOne(() => ns_s_flowSeqEntries(indent, ctx)); } - if (rest == null) rest = new Queue<_Node>(); + if (rest == null) rest = new Queue(); rest.addFirst(first); return rest; } // 139 - _Node ns_flowSeqEntry(int indent, int ctx) => or([ + Node ns_flowSeqEntry(int indent, int ctx) => or([ () => ns_flowPair(indent, ctx), () => ns_flowNode(indent, ctx) ]); // 140 - _Node c_flowMapping(int indent, int ctx) { + Node c_flowMapping(int indent, int ctx) { if (!truth(c_indicator(C_MAPPING_START))) return null; zeroOrOne(() => s_separate(indent, ctx)); var content = zeroOrOne(() => ns_s_flowMapEntries(indent, inFlow(ctx))); if (!truth(c_indicator(C_MAPPING_END))) return null; - return new _MappingNode("?", content); + return new MappingNode("?", content); } // 141 @@ -1175,7 +1181,7 @@ class _Parser { } // 142 - _Pair<_Node, _Node> ns_flowMapEntry(int indent, int ctx) => or([ + _Pair ns_flowMapEntry(int indent, int ctx) => or([ () => transaction(() { if (!truth(c_indicator(C_MAPPING_KEY))) return false; if (!truth(s_separate(indent, ctx))) return false; @@ -1185,20 +1191,20 @@ class _Parser { ]); // 143 - _Pair<_Node, _Node> ns_flowMapExplicitEntry(int indent, int ctx) => or([ + _Pair ns_flowMapExplicitEntry(int indent, int ctx) => or([ () => ns_flowMapImplicitEntry(indent, ctx), - () => new _Pair<_Node, _Node>(e_node(), e_node()) + () => new _Pair(e_node(), e_node()) ]); // 144 - _Pair<_Node, _Node> ns_flowMapImplicitEntry(int indent, int ctx) => or([ + _Pair ns_flowMapImplicitEntry(int indent, int ctx) => or([ () => ns_flowMapYamlKeyEntry(indent, ctx), () => c_ns_flowMapEmptyKeyEntry(indent, ctx), () => c_ns_flowMapJsonKeyEntry(indent, ctx) ]); // 145 - _Pair<_Node, _Node> ns_flowMapYamlKeyEntry(int indent, int ctx) { + _Pair ns_flowMapYamlKeyEntry(int indent, int ctx) { var key = ns_flowYamlNode(indent, ctx); if (!truth(key)) return null; var value = or([ @@ -1208,18 +1214,18 @@ class _Parser { }), e_node ]); - return new _Pair<_Node, _Node>(key, value); + return new _Pair(key, value); } // 146 - _Pair<_Node, _Node> c_ns_flowMapEmptyKeyEntry(int indent, int ctx) { + _Pair c_ns_flowMapEmptyKeyEntry(int indent, int ctx) { var value = c_ns_flowMapSeparateValue(indent, ctx); if (!truth(value)) return null; - return new _Pair<_Node, _Node>(e_node(), value); + return new _Pair(e_node(), value); } // 147 - _Node c_ns_flowMapSeparateValue(int indent, int ctx) => transaction(() { + Node c_ns_flowMapSeparateValue(int indent, int ctx) => transaction(() { if (!truth(c_indicator(C_MAPPING_VALUE))) return null; if (isPlainSafe(ctx, peek())) return null; @@ -1233,7 +1239,7 @@ class _Parser { }); // 148 - _Pair<_Node, _Node> c_ns_flowMapJsonKeyEntry(int indent, int ctx) { + _Pair c_ns_flowMapJsonKeyEntry(int indent, int ctx) { var key = c_flowJsonNode(indent, ctx); if (!truth(key)) return null; var value = or([ @@ -1243,11 +1249,11 @@ class _Parser { }), e_node ]); - return new _Pair<_Node, _Node>(key, value); + return new _Pair(key, value); } // 149 - _Node c_ns_flowMapAdjacentValue(int indent, int ctx) { + Node c_ns_flowMapAdjacentValue(int indent, int ctx) { if (!truth(c_indicator(C_MAPPING_VALUE))) return null; return or([ () => transaction(() { @@ -1259,7 +1265,7 @@ class _Parser { } // 150 - _Node ns_flowPair(int indent, int ctx) { + Node ns_flowPair(int indent, int ctx) { var pair = or([ () => transaction(() { if (!truth(c_indicator(C_MAPPING_KEY))) return null; @@ -1274,34 +1280,34 @@ class _Parser { } // 151 - _Pair<_Node, _Node> ns_flowPairEntry(int indent, int ctx) => or([ + _Pair ns_flowPairEntry(int indent, int ctx) => or([ () => ns_flowPairYamlKeyEntry(indent, ctx), () => c_ns_flowMapEmptyKeyEntry(indent, ctx), () => c_ns_flowPairJsonKeyEntry(indent, ctx) ]); // 152 - _Pair<_Node, _Node> ns_flowPairYamlKeyEntry(int indent, int ctx) => + _Pair ns_flowPairYamlKeyEntry(int indent, int ctx) => transaction(() { var key = ns_s_implicitYamlKey(FLOW_KEY); if (!truth(key)) return null; var value = c_ns_flowMapSeparateValue(indent, ctx); if (!truth(value)) return null; - return new _Pair<_Node, _Node>(key, value); + return new _Pair(key, value); }); // 153 - _Pair<_Node, _Node> c_ns_flowPairJsonKeyEntry(int indent, int ctx) => + _Pair c_ns_flowPairJsonKeyEntry(int indent, int ctx) => transaction(() { var key = c_s_implicitJsonKey(FLOW_KEY); if (!truth(key)) return null; var value = c_ns_flowMapAdjacentValue(indent, ctx); if (!truth(value)) return null; - return new _Pair<_Node, _Node>(key, value); + return new _Pair(key, value); }); // 154 - _Node ns_s_implicitYamlKey(int ctx) => transaction(() { + Node ns_s_implicitYamlKey(int ctx) => transaction(() { // TODO(nweiz): this is supposed to be limited to 1024 characters. // The indentation parameter is "null" since it's unused in this path @@ -1312,7 +1318,7 @@ class _Parser { }); // 155 - _Node c_s_implicitJsonKey(int ctx) => transaction(() { + Node c_s_implicitJsonKey(int ctx) => transaction(() { // TODO(nweiz): this is supposed to be limited to 1024 characters. // The indentation parameter is "null" since it's unused in this path @@ -1323,14 +1329,14 @@ class _Parser { }); // 156 - _Node ns_flowYamlContent(int indent, int ctx) { + Node ns_flowYamlContent(int indent, int ctx) { var str = ns_plain(indent, ctx); if (!truth(str)) return null; - return new _ScalarNode("?", content: str); + return new ScalarNode("?", content: str); } // 157 - _Node c_flowJsonContent(int indent, int ctx) => or([ + Node c_flowJsonContent(int indent, int ctx) => or([ () => c_flowSequence(indent, ctx), () => c_flowMapping(indent, ctx), () => c_singleQuoted(indent, ctx), @@ -1338,13 +1344,13 @@ class _Parser { ]); // 158 - _Node ns_flowContent(int indent, int ctx) => or([ + Node ns_flowContent(int indent, int ctx) => or([ () => ns_flowYamlContent(indent, ctx), () => c_flowJsonContent(indent, ctx) ]); // 159 - _Node ns_flowYamlNode(int indent, int ctx) => or([ + Node ns_flowYamlNode(int indent, int ctx) => or([ c_ns_aliasNode, () => ns_flowYamlContent(indent, ctx), () { @@ -1362,7 +1368,7 @@ class _Parser { ]); // 160 - _Node c_flowJsonNode(int indent, int ctx) => transaction(() { + Node c_flowJsonNode(int indent, int ctx) => transaction(() { var props; zeroOrOne(() => transaction(() { props = c_ns_properties(indent, ctx); @@ -1374,7 +1380,7 @@ class _Parser { }); // 161 - _Node ns_flowNode(int indent, int ctx) => or([ + Node ns_flowNode(int indent, int ctx) => or([ c_ns_aliasNode, () => ns_flowContent(indent, ctx), () => transaction(() { @@ -1471,7 +1477,7 @@ class _Parser { }); // 170 - _Node c_l_literal(int indent) => transaction(() { + Node c_l_literal(int indent) => transaction(() { if (!truth(c_indicator(C_LITERAL))) return null; var header = c_b_blockHeader(); if (!truth(header)) return null; @@ -1480,7 +1486,7 @@ class _Parser { var content = l_literalContent(indent + additionalIndent, header.chomping); if (!truth(content)) return null; - return new _ScalarNode("!", content: content); + return new ScalarNode("!", content: content); }); // 171 @@ -1508,7 +1514,7 @@ class _Parser { }); // 174 - _Node c_l_folded(int indent) => transaction(() { + Node c_l_folded(int indent) => transaction(() { if (!truth(c_indicator(C_FOLDED))) return null; var header = c_b_blockHeader(); if (!truth(header)) return null; @@ -1517,7 +1523,7 @@ class _Parser { var content = l_foldedContent(indent + additionalIndent, header.chomping); if (!truth(content)) return null; - return new _ScalarNode("!", content: content); + return new ScalarNode("!", content: content); }); // 175 @@ -1593,7 +1599,7 @@ class _Parser { }); // 183 - _SequenceNode l_blockSequence(int indent) => context('sequence', () { + SequenceNode l_blockSequence(int indent) => context('sequence', () { var additionalIndent = countIndentation() - indent; if (additionalIndent <= 0) return null; @@ -1603,11 +1609,11 @@ class _Parser { })); if (!truth(content)) return null; - return new _SequenceNode("?", content); + return new SequenceNode("?", content); }); // 184 - _Node c_l_blockSeqEntry(int indent) => transaction(() { + Node c_l_blockSeqEntry(int indent) => transaction(() { if (!truth(c_indicator(C_SEQUENCE_ENTRY))) return null; if (isNonSpace(peek())) return null; @@ -1615,7 +1621,7 @@ class _Parser { }); // 185 - _Node s_l_blockIndented(int indent, int ctx) { + Node s_l_blockIndented(int indent, int ctx) { var additionalIndent = countIndentation(); return or([ () => transaction(() { @@ -1629,7 +1635,7 @@ class _Parser { } // 186 - _Node ns_l_compactSequence(int indent) => context('sequence', () { + Node ns_l_compactSequence(int indent) => context('sequence', () { var first = c_l_blockSeqEntry(indent); if (!truth(first)) return null; @@ -1639,11 +1645,11 @@ class _Parser { })); content.insert(0, first); - return new _SequenceNode("?", content); + return new SequenceNode("?", content); }); // 187 - _Node l_blockMapping(int indent) => context('mapping', () { + Node l_blockMapping(int indent) => context('mapping', () { var additionalIndent = countIndentation() - indent; if (additionalIndent <= 0) return null; @@ -1657,13 +1663,13 @@ class _Parser { }); // 188 - _Pair<_Node, _Node> ns_l_blockMapEntry(int indent) => or([ + _Pair ns_l_blockMapEntry(int indent) => or([ () => c_l_blockMapExplicitEntry(indent), () => ns_l_blockMapImplicitEntry(indent) ]); // 189 - _Pair<_Node, _Node> c_l_blockMapExplicitEntry(int indent) { + _Pair c_l_blockMapExplicitEntry(int indent) { var key = c_l_blockMapExplicitKey(indent); if (!truth(key)) return null; @@ -1672,37 +1678,37 @@ class _Parser { e_node ]); - return new _Pair<_Node, _Node>(key, value); + return new _Pair(key, value); } // 190 - _Node c_l_blockMapExplicitKey(int indent) => transaction(() { + Node c_l_blockMapExplicitKey(int indent) => transaction(() { if (!truth(c_indicator(C_MAPPING_KEY))) return null; return s_l_blockIndented(indent, BLOCK_OUT); }); // 191 - _Node l_blockMapExplicitValue(int indent) => transaction(() { + Node l_blockMapExplicitValue(int indent) => transaction(() { if (!truth(s_indent(indent))) return null; if (!truth(c_indicator(C_MAPPING_VALUE))) return null; return s_l_blockIndented(indent, BLOCK_OUT); }); // 192 - _Pair<_Node, _Node> ns_l_blockMapImplicitEntry(int indent) => transaction(() { + _Pair ns_l_blockMapImplicitEntry(int indent) => transaction(() { var key = or([ns_s_blockMapImplicitKey, e_node]); var value = c_l_blockMapImplicitValue(indent); - return truth(value) ? new _Pair<_Node, _Node>(key, value) : null; + return truth(value) ? new _Pair(key, value) : null; }); // 193 - _Node ns_s_blockMapImplicitKey() => context('mapping key', () => or([ + Node ns_s_blockMapImplicitKey() => context('mapping key', () => or([ () => c_s_implicitJsonKey(BLOCK_KEY), () => ns_s_implicitYamlKey(BLOCK_KEY) ])); // 194 - _Node c_l_blockMapImplicitValue(int indent) => context('mapping value', () => + Node c_l_blockMapImplicitValue(int indent) => context('mapping value', () => transaction(() { if (!truth(c_indicator(C_MAPPING_VALUE))) return null; return or([ @@ -1712,7 +1718,7 @@ class _Parser { })); // 195 - _Node ns_l_compactMapping(int indent) => context('mapping', () { + Node ns_l_compactMapping(int indent) => context('mapping', () { var first = ns_l_blockMapEntry(indent); if (!truth(first)) return null; @@ -1726,13 +1732,13 @@ class _Parser { }); // 196 - _Node s_l_blockNode(int indent, int ctx) => or([ + Node s_l_blockNode(int indent, int ctx) => or([ () => s_l_blockInBlock(indent, ctx), () => s_l_flowInBlock(indent) ]); // 197 - _Node s_l_flowInBlock(int indent) => transaction(() { + Node s_l_flowInBlock(int indent) => transaction(() { if (!truth(s_separate(indent + 1, FLOW_OUT))) return null; var node = ns_flowNode(indent + 1, FLOW_OUT); if (!truth(node)) return null; @@ -1741,13 +1747,13 @@ class _Parser { }); // 198 - _Node s_l_blockInBlock(int indent, int ctx) => or([ + Node s_l_blockInBlock(int indent, int ctx) => or([ () => s_l_blockScalar(indent, ctx), () => s_l_blockCollection(indent, ctx) ]); // 199 - _Node s_l_blockScalar(int indent, int ctx) => transaction(() { + Node s_l_blockScalar(int indent, int ctx) => transaction(() { if (!truth(s_separate(indent + 1, ctx))) return null; var props = transaction(() { var innerProps = c_ns_properties(indent + 1, ctx); @@ -1762,7 +1768,7 @@ class _Parser { }); // 200 - _Node s_l_blockCollection(int indent, int ctx) => transaction(() { + Node s_l_blockCollection(int indent, int ctx) => transaction(() { var props = transaction(() { if (!truth(s_separate(indent + 1, ctx))) return null; return c_ns_properties(indent + 1, ctx); @@ -1796,7 +1802,7 @@ class _Parser { // 206 bool c_forbidden() { - if (!inBareDocument || !atStartOfLine) return false; + if (!_inBareDocument || !atStartOfLine) return false; var forbidden = false; transaction(() { if (!truth(or([c_directivesEnd, c_documentEnd]))) return; @@ -1808,17 +1814,17 @@ class _Parser { } // 207 - _Node l_bareDocument() { + Node l_bareDocument() { try { - inBareDocument = true; + _inBareDocument = true; return s_l_blockNode(-1, BLOCK_IN); } finally { - inBareDocument = false; + _inBareDocument = false; } } // 208 - _Node l_explicitDocument() { + Node l_explicitDocument() { if (!truth(c_directivesEnd())) return null; var doc = l_bareDocument(); if (truth(doc)) return doc; @@ -1829,7 +1835,7 @@ class _Parser { } // 209 - _Node l_directiveDocument() { + Node l_directiveDocument() { if (!truth(oneOrMore(l_directive))) return null; var doc = l_explicitDocument(); if (doc != null) return doc; @@ -1838,11 +1844,11 @@ class _Parser { } // 210 - _Node l_anyDocument() => + Node l_anyDocument() => or([l_directiveDocument, l_explicitDocument, l_bareDocument]); // 211 - List<_Node> l_yamlStream() { + List l_yamlStream() { var docs = []; zeroOrMore(l_documentPrefix); var first = zeroOrOne(l_anyDocument); @@ -1868,12 +1874,13 @@ class _Parser { } class SyntaxError extends YamlException { - final int line; - final int column; + final int _line; + final int _column; - SyntaxError(this.line, this.column, String msg) : super(msg); + SyntaxError(this._line, this._column, String msg) : super(msg); - String toString() => "Syntax error on line $line, column $column: $msg"; + String toString() => "Syntax error on line $_line, column $_column: " + "${super.toString()}"; } /// A pair of values. @@ -1916,18 +1923,17 @@ class _Range { /// expensive. class _RangeMap { /// The ranges and their associated elements. - final List<_Pair<_Range, E>> contents; + final List<_Pair<_Range, E>> _contents = <_Pair<_Range, E>>[]; - _RangeMap() : this.contents = <_Pair<_Range, E>>[]; + _RangeMap(); /// Returns the value associated with the range in which [pos] lies, or null /// if there is no such range. If there's more than one such range, the most /// recently set one is used. E operator[](int pos) { // Iterate backwards through contents so the more recent range takes - // precedence. TODO(nweiz): clean this up when issue 2804 is fixed. - for (var i = contents.length - 1; i >= 0; i--) { - var pair = contents[i]; + // precedence. + for (var pair in _contents.reversed) { if (pair.first.contains(pos)) return pair.last; } return null; @@ -1935,5 +1941,5 @@ class _RangeMap { /// Associates [value] with [range]. operator[]=(_Range range, E value) => - contents.add(new _Pair<_Range, E>(range, value)); + _contents.add(new _Pair<_Range, E>(range, value)); } diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart new file mode 100644 index 000000000..a87555d62 --- /dev/null +++ b/pkgs/yaml/lib/src/utils.dart @@ -0,0 +1,39 @@ +// Copyright (c) 2013, 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 utils; + +/// Returns the hash code for [obj]. This includes null, true, false, maps, and +/// lists. Also handles self-referential structures. +int hashCodeFor(obj, [List parents]) { + if (parents == null) { + parents = []; + } else if (parents.any((p) => identical(p, obj))) { + return -1; + } + + parents.add(obj); + try { + if (obj == null) return 0; + if (obj == true) return 1; + if (obj == false) return 2; + if (obj is Map) { + return hashCodeFor(obj.keys, parents) ^ + hashCodeFor(obj.values, parents); + } + if (obj is Iterable) { + // This is probably a really bad hash function, but presumably we'll get + // this in the standard library before it actually matters. + int hash = 0; + for (var e in obj) { + hash ^= hashCodeFor(e, parents); + } + return hash; + } + return obj.hashCode; + } finally { + parents.removeLast(); + } +} + diff --git a/pkgs/yaml/lib/visitor.dart b/pkgs/yaml/lib/src/visitor.dart similarity index 74% rename from pkgs/yaml/lib/visitor.dart rename to pkgs/yaml/lib/src/visitor.dart index 42dbb2273..4a9c54f26 100644 --- a/pkgs/yaml/lib/visitor.dart +++ b/pkgs/yaml/lib/src/visitor.dart @@ -2,22 +2,25 @@ // 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. -part of yaml; +library visitor; + +import 'model.dart'; +import 'yaml_map.dart'; /// The visitor pattern for YAML documents. -class _Visitor { +class Visitor { /// Returns [alias]. - visitAlias(_AliasNode alias) => alias; + visitAlias(AliasNode alias) => alias; /// Returns [scalar]. - visitScalar(_ScalarNode scalar) => scalar; + visitScalar(ScalarNode scalar) => scalar; /// Visits each node in [seq] and returns a list of the results. - visitSequence(_SequenceNode seq) + visitSequence(SequenceNode seq) => seq.content.map((e) => e.visit(this)).toList(); /// Visits each key and value in [map] and returns a map of the results. - visitMapping(_MappingNode map) { + visitMapping(MappingNode map) { var out = new YamlMap(); for (var key in map.content.keys) { out[key.visit(this)] = map.content[key].visit(this); diff --git a/pkgs/yaml/lib/src/yaml_exception.dart b/pkgs/yaml/lib/src/yaml_exception.dart new file mode 100644 index 000000000..66697a18e --- /dev/null +++ b/pkgs/yaml/lib/src/yaml_exception.dart @@ -0,0 +1,15 @@ +// Copyright (c) 2013, 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 yaml_exception; + +/// An error thrown by the YAML processor. +class YamlException implements Exception { + final String _msg; + + YamlException(this._msg); + + String toString() => _msg; +} + diff --git a/pkgs/yaml/lib/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart similarity index 70% rename from pkgs/yaml/lib/yaml_map.dart rename to pkgs/yaml/lib/src/yaml_map.dart index cbf18e5d2..29fec7595 100644 --- a/pkgs/yaml/lib/yaml_map.dart +++ b/pkgs/yaml/lib/src/yaml_map.dart @@ -2,7 +2,10 @@ // 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. -part of yaml; +library yaml_map; + +import 'deep_equals.dart'; +import 'utils.dart'; /// This class wraps behaves almost identically to the normal Dart Map /// implementation, with the following differences: @@ -12,7 +15,7 @@ part of yaml; /// have the same contents. /// * It has a compatible [hashCode] method. class YamlMap implements Map { - Map _map; + final Map _map; YamlMap() : _map = new Map(); @@ -35,7 +38,7 @@ class YamlMap implements Map { bool get isEmpty => _map.isEmpty; String toString() => _map.toString(); - int get hashCode => _hashCode(_map); + int get hashCode => hashCodeFor(_map); bool operator ==(other) { if (other is! YamlMap) return false; @@ -61,11 +64,11 @@ class YamlMap implements Map { /// A class for wrapping normally-unhashable objects that are being used as keys /// in a YamlMap. class _WrappedHashKey { - var value; + final value; _WrappedHashKey(this.value); - int get hashCode => _hashCode(value); + int get hashCode => hashCodeFor(value); String toString() => value.toString(); @@ -75,36 +78,3 @@ class _WrappedHashKey { return deepEquals(this.value, other.value); } } - -/// Returns the hash code for [obj]. This includes null, true, false, maps, and -/// lists. Also handles self-referential structures. -int _hashCode(obj, [List parents]) { - if (parents == null) { - parents = []; - } else if (parents.any((p) => identical(p, obj))) { - return -1; - } - - parents.add(obj); - try { - if (obj == null) return 0; - if (obj == true) return 1; - if (obj == false) return 2; - if (obj is Map) { - return _hashCode(obj.keys, parents) ^ - _hashCode(obj.values, parents); - } - if (obj is Iterable) { - // This is probably a really bad hash function, but presumably we'll get - // this in the standard library before it actually matters. - int hash = 0; - for (var e in obj) { - hash ^= _hashCode(e, parents); - } - return hash; - } - return obj.hashCode; - } finally { - parents.removeLast(); - } -} diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index e905e767d..94e3d4220 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -24,17 +24,13 @@ /// } library yaml; -import 'dart:math' as Math; -import 'dart:collection' show Queue; +import 'src/composer.dart'; +import 'src/constructor.dart'; +import 'src/parser.dart'; +import 'src/yaml_exception.dart'; -import 'deep_equals.dart'; - -part 'yaml_map.dart'; -part 'model.dart'; -part 'parser.dart'; -part 'visitor.dart'; -part 'composer.dart'; -part 'constructor.dart'; +export 'src/yaml_exception.dart'; +export 'src/yaml_map.dart'; /// Loads a single document from a YAML string. If the string contains more than /// one document, this throws an error. @@ -42,8 +38,8 @@ part 'constructor.dart'; /// The return value is mostly normal Dart objects. However, since YAML mappings /// support some key types that the default Dart map implementation doesn't /// (null, NaN, booleans, lists, and maps), all maps in the returned document -/// are YamlMaps. These have a few small behavioral differences from the default -/// Map implementation; for details, see the YamlMap class. +/// are [YamlMap]s. These have a few small behavioral differences from the +/// default Map implementation; for details, see the [YamlMap] class. loadYaml(String yaml) { var stream = loadYamlStream(yaml); if (stream.length != 1) { @@ -57,19 +53,10 @@ loadYaml(String yaml) { /// The return value is mostly normal Dart objects. However, since YAML mappings /// support some key types that the default Dart map implementation doesn't /// (null, NaN, booleans, lists, and maps), all maps in the returned document -/// are YamlMaps. These have a few small behavioral differences from the default -/// Map implementation; for details, see the YamlMap class. +/// are [YamlMap]s. These have a few small behavioral differences from the +/// default Map implementation; for details, see the [YamlMap] class. List loadYamlStream(String yaml) { - return new _Parser(yaml).l_yamlStream() - .map((doc) => new _Constructor(new _Composer(doc).compose()).construct()) + return new Parser(yaml).l_yamlStream() + .map((doc) => new Constructor(new Composer(doc).compose()).construct()) .toList(); } - -/// An error thrown by the YAML processor. -class YamlException implements Exception { - String msg; - - YamlException(this.msg); - - String toString() => msg; -} diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 047c2738b..42cb6137d 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -8,7 +8,7 @@ library yaml_test; import "package:expect/expect.dart"; import 'package:unittest/unittest.dart'; import 'package:yaml/yaml.dart'; -import 'package:yaml/deep_equals.dart'; +import 'package:yaml/src/deep_equals.dart'; // TODO(jmesserly): we should not be reaching outside the YAML package // The http package has a similar problem. import '../../../tests/utils/test_utils.dart'; From aa2c7c1be32b080fcfe8923bc220acf3bc087eae Mon Sep 17 00:00:00 2001 From: "sethladd@google.com" Date: Fri, 19 Apr 2013 20:51:10 +0000 Subject: [PATCH 016/179] add installation instructions to pkg packages BUG= Review URL: https://codereview.chromium.org//14188048 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@21770 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/yaml.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 94e3d4220..85861d564 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -4,6 +4,21 @@ /// A parser for [YAML](http://www.yaml.org/). /// +/// ## Installing ## +/// +/// Use [pub][] to install this package. Add the following to your +/// `pubspec.yaml` file. +/// +/// dependencies: +/// yaml: any +/// +/// Then run `pub install`. +/// +/// For more information, see the +/// [yaml package on pub.dartlang.org][pkg]. +/// +/// ## Using ## +/// /// Use [loadYaml] to load a single document, or [loadYamlStream] to load a /// stream of documents. For example: /// @@ -22,6 +37,9 @@ /// var doc = loadYaml("YAML: YAML Ain't Markup Language"); /// print(json.stringify(doc)); /// } +/// +/// [pub]: http://pub.dartlang.org +/// [pkg]: http://pub.dartlang.org/packages/yaml library yaml; import 'src/composer.dart'; From 98531f0cb4e2359b33f4121e09a76d4057ce4207 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Tue, 28 May 2013 17:30:37 +0000 Subject: [PATCH 017/179] Adding isNotEmpty property to collection and string. BUG= http://dartbug.com/3074 R=floitsch@google.com Review URL: https://codereview.chromium.org//15263004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@23294 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/src/yaml_map.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/yaml/lib/src/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart index 29fec7595..303d8ed77 100644 --- a/pkgs/yaml/lib/src/yaml_map.dart +++ b/pkgs/yaml/lib/src/yaml_map.dart @@ -36,6 +36,7 @@ class YamlMap implements Map { Iterable get values => _map.values; int get length => _map.length; bool get isEmpty => _map.isEmpty; + bool get isNotEmpty => map.isNotEmpty; String toString() => _map.toString(); int get hashCode => hashCodeFor(_map); From 73e48f01855ff77ce476a902e1f422507a37dd50 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 4 Jun 2013 23:34:06 +0000 Subject: [PATCH 018/179] Make my pkg packages warning-clean. R=rnystrom@google.com Review URL: https://codereview.chromium.org//16097013 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@23620 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/src/yaml_map.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/lib/src/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart index 303d8ed77..aa8397cfa 100644 --- a/pkgs/yaml/lib/src/yaml_map.dart +++ b/pkgs/yaml/lib/src/yaml_map.dart @@ -36,7 +36,7 @@ class YamlMap implements Map { Iterable get values => _map.values; int get length => _map.length; bool get isEmpty => _map.isEmpty; - bool get isNotEmpty => map.isNotEmpty; + bool get isNotEmpty => _map.isNotEmpty; String toString() => _map.toString(); int get hashCode => hashCodeFor(_map); From b3c02aa42ee867a1b972394f0c5a0236e9314c9d Mon Sep 17 00:00:00 2001 From: "kevmoo@j832.com" Date: Tue, 6 Aug 2013 20:42:04 +0000 Subject: [PATCH 019/179] pkg: analysis aided cleanup Removed a lot of warnings and hints when opening many pkg projects in the editor R=gram@google.com Review URL: https://codereview.chromium.org//22284003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@25831 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/src/model.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/yaml/lib/src/model.dart b/pkgs/yaml/lib/src/model.dart index d7ee4814d..37247f0dd 100644 --- a/pkgs/yaml/lib/src/model.dart +++ b/pkgs/yaml/lib/src/model.dart @@ -7,7 +7,6 @@ /// representation graph. library model; -import 'model.dart'; import 'parser.dart'; import 'utils.dart'; import 'visitor.dart'; From 096c625f1f49cdd2f4ebe8f654f91e7d2021cbfc Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Wed, 28 Aug 2013 14:05:11 +0000 Subject: [PATCH 020/179] Remove usage of dart:json. R=jmesserly@google.com, lrn@google.com, nweiz@google.com, rnystrom@google.com Review URL: https://codereview.chromium.org//23596007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@26789 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/yaml.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 85861d564..fa5286164 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -29,13 +29,13 @@ /// } /// /// This library currently doesn't support dumping to YAML. You should use -/// `stringify` from `dart:json` instead: +/// `JSON.encode` from `dart:convert` instead: /// -/// import 'dart:json' as json; +/// import 'dart:convert'; /// import 'package:yaml/yaml.dart'; /// main() { /// var doc = loadYaml("YAML: YAML Ain't Markup Language"); -/// print(json.stringify(doc)); +/// print(JSON.encode(doc)); /// } /// /// [pub]: http://pub.dartlang.org From d31d7fc15d1d602b5f7c78d2eb2f16c08b8fdd25 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 20 Sep 2013 21:24:02 +0000 Subject: [PATCH 021/179] Add YamlMap.addAll. BUG=13356 R=jmesserly@google.com Review URL: https://codereview.chromium.org//24175008 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@27725 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/src/yaml_map.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkgs/yaml/lib/src/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart index aa8397cfa..50ae2d95b 100644 --- a/pkgs/yaml/lib/src/yaml_map.dart +++ b/pkgs/yaml/lib/src/yaml_map.dart @@ -23,6 +23,12 @@ class YamlMap implements Map { YamlMap._wrap(this._map); + void addAll(Map other) { + other.forEach((key, value) { + this[key] = value; + }); + } + bool containsValue(value) => _map.containsValue(value); bool containsKey(key) => _map.containsKey(_wrapKey(key)); operator [](key) => _map[_wrapKey(key)]; From 2fcd7cc7fa0beabd9a151a1f259286ff500d31eb Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Fri, 25 Oct 2013 10:30:34 +0000 Subject: [PATCH 022/179] Remove dart:json BUG= http://dartbug.com/12843 R=floitsch@google.com, fschneider@google.com Review URL: https://codereview.chromium.org//40323002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@29240 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index ad7678fc8..47a5419fa 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -10,13 +10,13 @@ stream of documents. For example: } This library currently doesn't support dumping to YAML. You should use -`stringify` from `dart:json` instead: +`JSON.encode` from `dart:convert` instead: - import 'dart:json' as json; + import 'dart:convert'; import 'package:yaml/yaml.dart'; main() { var doc = loadYaml("YAML: YAML Ain't Markup Language"); - print(json.stringify(doc)); + print(JSON.encode(doc)); } The source code for this package is at . From 517b5a8878abf1a94d694d29674889770d993a7b Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" Date: Wed, 6 Nov 2013 03:27:58 +0000 Subject: [PATCH 023/179] add versions and constraints for packages and samples - all packages at 0.9.0, except "analyzer" which had a version already - dependencies at ">=0.9.0 <0.10.0" except analyzer is ">=0.10.0 <0.11.0" - sdk constraint ">=1.0.0 <2.0.0" R=sigmund@google.com Review URL: https://codereview.chromium.org//59763006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@29957 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/pubspec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 4b17267fc..48d498988 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,6 +1,9 @@ name: yaml +version: 0.9.0 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dev_dependencies: - unittest: any + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=1.0.0 <2.0.0" From cf2278422cff6fa9cb9eb345e3cfc701d93d770f Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Wed, 6 Nov 2013 09:09:18 +0000 Subject: [PATCH 024/179] Revert "add versions and constraints for packages and samples" This is currently blocking us from testing samples. BUG= R=kasperl@google.com Review URL: https://codereview.chromium.org//59513007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@29960 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/pubspec.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 48d498988..4b17267fc 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,9 +1,6 @@ name: yaml -version: 0.9.0 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dev_dependencies: - unittest: ">=0.9.0 <0.10.0" -environment: - sdk: ">=1.0.0 <2.0.0" + unittest: any From 63dd51a8bc6546ee3af082c713246614517c448b Mon Sep 17 00:00:00 2001 From: "dgrove@google.com" Date: Wed, 6 Nov 2013 18:28:22 +0000 Subject: [PATCH 025/179] Re-land r29957 (add versions and constraints for packages and samples), with SDK constraints bumped from 1.0.0 to 0.8.10+6 . R=ricow@google.com, sigmund@google.com Review URL: https://codereview.chromium.org//62473002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@29986 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/pubspec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 4b17267fc..1fb4c8d1b 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,6 +1,9 @@ name: yaml +version: 0.9.0 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dev_dependencies: - unittest: any + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=0.8.10+6 <2.0.0" From 9af2a930203b725b651553abdc4f3345ee0a9480 Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Mon, 13 Jan 2014 18:07:45 +0000 Subject: [PATCH 026/179] pkg/unittest: added LICENSE R=rnystrom@google.com Review URL: https://codereview.chromium.org//135343002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@31750 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/LICENSE | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 pkgs/yaml/LICENSE diff --git a/pkgs/yaml/LICENSE b/pkgs/yaml/LICENSE new file mode 100644 index 000000000..5c60afea3 --- /dev/null +++ b/pkgs/yaml/LICENSE @@ -0,0 +1,26 @@ +Copyright 2014, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 175d2704d17bf5e5c809825ba597dbdd82158160 Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Tue, 22 Apr 2014 05:53:33 +0000 Subject: [PATCH 027/179] Remove unmodifiable map wrappers that could instead use UnmodifiableMapView. R=sgjesse@google.com Review URL: https://codereview.chromium.org//214723002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@35244 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/src/yaml_map.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/lib/src/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart index 50ae2d95b..ab07c72b4 100644 --- a/pkgs/yaml/lib/src/yaml_map.dart +++ b/pkgs/yaml/lib/src/yaml_map.dart @@ -55,7 +55,7 @@ class YamlMap implements Map { /// Wraps an object for use as a key in the map. _wrapKey(obj) { if (obj != null && obj is! bool && obj is! List && - (obj is! double || !obj.isNan()) && + (obj is! double || !obj.isNan) && (obj is! Map || obj is YamlMap)) { return obj; } else if (obj is Map) { From efb404319446e3f7214f2a7a4b3bf76630bba942 Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Tue, 22 Apr 2014 06:21:24 +0000 Subject: [PATCH 028/179] Revert "Remove unmodifiable map wrappers that could instead use UnmodifiableMapView." Some tests fail. Review URL: https://codereview.chromium.org//246833003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@35245 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/src/yaml_map.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/lib/src/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart index ab07c72b4..50ae2d95b 100644 --- a/pkgs/yaml/lib/src/yaml_map.dart +++ b/pkgs/yaml/lib/src/yaml_map.dart @@ -55,7 +55,7 @@ class YamlMap implements Map { /// Wraps an object for use as a key in the map. _wrapKey(obj) { if (obj != null && obj is! bool && obj is! List && - (obj is! double || !obj.isNan) && + (obj is! double || !obj.isNan()) && (obj is! Map || obj is YamlMap)) { return obj; } else if (obj is Map) { From f21ae3cdc416a583fcd0762438550c3b9105db56 Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Thu, 24 Apr 2014 08:51:41 +0000 Subject: [PATCH 029/179] Remove unmodifiable map wrappers that could instead use UnmodifiableMapView. R=sgjesse@google.com Committed: https://code.google.com/p/dart/source/detail?r=35244 Review URL: https://codereview.chromium.org//214723002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@35361 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/src/yaml_map.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/lib/src/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart index 50ae2d95b..ab07c72b4 100644 --- a/pkgs/yaml/lib/src/yaml_map.dart +++ b/pkgs/yaml/lib/src/yaml_map.dart @@ -55,7 +55,7 @@ class YamlMap implements Map { /// Wraps an object for use as a key in the map. _wrapKey(obj) { if (obj != null && obj is! bool && obj is! List && - (obj is! double || !obj.isNan()) && + (obj is! double || !obj.isNan) && (obj is! Map || obj is YamlMap)) { return obj; } else if (obj is Map) { From 1cba6f660529b2f805118197dcf3e91cfb8d093d Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 8 May 2014 21:18:14 +0000 Subject: [PATCH 030/179] Fix analyzer warnings in the YAML package. R=rnystrom@google.com Review URL: https://codereview.chromium.org//277593005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@35939 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/lib/src/deep_equals.dart | 22 +++++++++++++--------- pkgs/yaml/lib/src/parser.dart | 14 ++++++++------ pkgs/yaml/lib/src/yaml_map.dart | 2 +- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/pkgs/yaml/lib/src/deep_equals.dart b/pkgs/yaml/lib/src/deep_equals.dart index bce4aadf2..1e1f7ed76 100644 --- a/pkgs/yaml/lib/src/deep_equals.dart +++ b/pkgs/yaml/lib/src/deep_equals.dart @@ -4,8 +4,10 @@ library deep_equals; -/// Returns whether two objects are structurally equivalent. This considers NaN -/// values to be equivalent. It also handles self-referential structures. +/// Returns whether two objects are structurally equivalent. +/// +/// This considers `NaN` values to be equivalent. It also handles +/// self-referential structures. bool deepEquals(obj1, obj2, [List parents1, List parents2]) { if (identical(obj1, obj2)) return true; if (parents1 == null) { @@ -30,8 +32,8 @@ bool deepEquals(obj1, obj2, [List parents1, List parents2]) { return _listEquals(obj1, obj2, parents1, parents2); } else if (obj1 is Map && obj2 is Map) { return _mapEquals(obj1, obj2, parents1, parents2); - } else if (obj1 is double && obj2 is double) { - return _doubleEquals(obj1, obj2); + } else if (obj1 is num && obj2 is num) { + return _numEquals(obj1, obj2); } else { return obj1 == obj2; } @@ -64,9 +66,11 @@ bool _mapEquals(Map map1, Map map2, List parents1, List parents2) { return true; } -/// Returns whether two doubles are equivalent. This differs from `d1 == d2` in -/// that it considers NaN to be equal to itself. -bool _doubleEquals(double d1, double d2) { - if (d1.isNaN && d2.isNaN) return true; - return d1 == d2; +/// Returns whether two numbers are equivalent. +/// +/// This differs from `n1 == n2` in that it considers `NaN` to be equal to +/// itself. +bool _numEquals(num n1, num n2) { + if (n1.isNaN && n2.isNaN) return true; + return n1 == n2; } diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 2616038ee..162fef475 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -1106,13 +1106,14 @@ class Parser { // 136 int inFlow(int ctx) { switch (ctx) { - case FLOW_OUT: - case FLOW_IN: - return FLOW_IN; - case BLOCK_KEY: - case FLOW_KEY: - return FLOW_KEY; + case FLOW_OUT: + case FLOW_IN: + return FLOW_IN; + case BLOCK_KEY: + case FLOW_KEY: + return FLOW_KEY; } + throw "unreachable"; } // 137 @@ -1434,6 +1435,7 @@ class Parser { case CHOMPING_KEEP: return b_asLineFeed(); } + throw "unreachable"; } // 166 diff --git a/pkgs/yaml/lib/src/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart index ab07c72b4..5e3e20a6f 100644 --- a/pkgs/yaml/lib/src/yaml_map.dart +++ b/pkgs/yaml/lib/src/yaml_map.dart @@ -55,7 +55,7 @@ class YamlMap implements Map { /// Wraps an object for use as a key in the map. _wrapKey(obj) { if (obj != null && obj is! bool && obj is! List && - (obj is! double || !obj.isNan) && + (obj is! num || !obj.isNaN) && (obj is! Map || obj is YamlMap)) { return obj; } else if (obj is Map) { From 8c7195ecc7eb1c16e6ed4bbbf33419c9e9e8f8ff Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 20 May 2014 21:40:22 +0000 Subject: [PATCH 031/179] Bring the YAML package's style up to modern standards. R=jmesserly@google.com, rnystrom@google.com Review URL: https://codereview.chromium.org//274953002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@36386 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 5 ++ pkgs/yaml/README.md | 28 ++++--- pkgs/yaml/lib/src/composer.dart | 52 ++++++------ pkgs/yaml/lib/src/constructor.dart | 2 +- pkgs/yaml/lib/src/deep_equals.dart | 113 ++++++++++++++------------ pkgs/yaml/lib/src/model.dart | 59 +++++++++----- pkgs/yaml/lib/src/parser.dart | 21 ++--- pkgs/yaml/lib/src/utils.dart | 53 ++++++------ pkgs/yaml/lib/src/visitor.dart | 2 +- pkgs/yaml/lib/src/yaml_exception.dart | 2 +- pkgs/yaml/lib/src/yaml_map.dart | 85 +++++-------------- pkgs/yaml/lib/yaml.dart | 64 ++++----------- pkgs/yaml/pubspec.yaml | 4 +- pkgs/yaml/test/utils.dart | 83 +++++++++++++++++++ pkgs/yaml/test/yaml_test.dart | 104 +++++++++--------------- 15 files changed, 345 insertions(+), 332 deletions(-) create mode 100644 pkgs/yaml/CHANGELOG.md create mode 100644 pkgs/yaml/test/utils.dart diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md new file mode 100644 index 000000000..695e06971 --- /dev/null +++ b/pkgs/yaml/CHANGELOG.md @@ -0,0 +1,5 @@ +## 0.9.0+1 + +* The `YamlMap` class is deprecated. In a future version, maps returned by + `loadYaml` and `loadYamlStream` will be Dart `HashMap`s with a custom equality + operation. diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index 47a5419fa..531162f41 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -3,21 +3,27 @@ A parser for [YAML](http://www.yaml.org/). Use `loadYaml` to load a single document, or `loadYamlStream` to load a stream of documents. For example: - import 'package:yaml/yaml.dart'; - main() { - var doc = loadYaml("YAML: YAML Ain't Markup Language"); - print(doc['YAML']); - } +```dart +import 'package:yaml/yaml.dart'; + +main() { + var doc = loadYaml("YAML: YAML Ain't Markup Language"); + print(doc['YAML']); +} +``` This library currently doesn't support dumping to YAML. You should use `JSON.encode` from `dart:convert` instead: - import 'dart:convert'; - import 'package:yaml/yaml.dart'; - main() { - var doc = loadYaml("YAML: YAML Ain't Markup Language"); - print(JSON.encode(doc)); - } +```dart +import 'dart:convert'; +import 'package:yaml/yaml.dart'; + +main() { + var doc = loadYaml("YAML: YAML Ain't Markup Language"); + print(JSON.encode(doc)); +} +``` The source code for this package is at . Please file issues at . Other questions or comments can be diff --git a/pkgs/yaml/lib/src/composer.dart b/pkgs/yaml/lib/src/composer.dart index 40b76677e..317809653 100644 --- a/pkgs/yaml/lib/src/composer.dart +++ b/pkgs/yaml/lib/src/composer.dart @@ -2,7 +2,7 @@ // 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 composer; +library yaml.composer; import 'model.dart'; import 'visitor.dart'; @@ -19,10 +19,11 @@ class Composer extends Visitor { /// that anchor. final _anchors = {}; - /// The next id to use for the represenation graph's anchors. The spec doesn't - /// use anchors in the representation graph, but we do so that the constructor - /// can ensure that the same node in the representation graph produces the - /// same native object. + /// The next id to use for the represenation graph's anchors. + /// + /// The spec doesn't use anchors in the representation graph, but we do so + /// that the constructor can ensure that the same node in the representation + /// graph produces the same native object. var _idCounter = 0; Composer(this._root); @@ -33,13 +34,15 @@ class Composer extends Visitor { /// Returns the anchor to which an alias node refers. Node visitAlias(AliasNode alias) { if (!_anchors.containsKey(alias.anchor)) { - throw new YamlException("no anchor for alias ${alias.anchor}"); + throw new YamlException("No anchor for alias ${alias.anchor}."); } return _anchors[alias.anchor]; } /// Parses a scalar node according to its tag, or auto-detects the type if no - /// tag exists. Currently this only supports the YAML core type schema. + /// tag exists. + /// + /// Currently this only supports the YAML core type schema. Node visitScalar(ScalarNode scalar) { if (scalar.tag.name == "!") { return setAnchor(scalar, parseString(scalar.content)); @@ -51,30 +54,31 @@ class Composer extends Visitor { return setAnchor(scalar, parseString(scalar.content)); } - // TODO(nweiz): support the full YAML type repository - var tagParsers = { - 'null': parseNull, 'bool': parseBool, 'int': parseInt, - 'float': parseFloat, 'str': parseString - }; - - for (var key in tagParsers.keys) { - if (scalar.tag.name != Tag.yaml(key)) continue; - var result = tagParsers[key](scalar.content); - if (result != null) return setAnchor(scalar, result); - throw new YamlException('invalid literal for $key: "${scalar.content}"'); - } + var result = _parseByTag(scalar); + if (result != null) return setAnchor(scalar, result); + throw new YamlException('Invalid literal for ${scalar.tag}: ' + '"${scalar.content}".'); + } - throw new YamlException('undefined tag: "${scalar.tag.name}"'); + ScalarNode _parseByTag(ScalarNode scalar) { + switch (scalar.tag.name) { + case "null": return parseNull(scalar.content); + case "bool": return parseBool(scalar.content); + case "int": return parseInt(scalar.content); + case "float": return parseFloat(scalar.content); + case "str": return parseString(scalar.content); + } + throw new YamlException('Undefined tag: ${scalar.tag}.'); } /// Assigns a tag to the sequence and recursively composes its contents. Node visitSequence(SequenceNode seq) { var tagName = seq.tag.name; if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("seq")) { - throw new YamlException("invalid tag for sequence: ${tagName}"); + throw new YamlException("Invalid tag for sequence: ${seq.tag}."); } - var result = setAnchor(seq, new SequenceNode(Tag.yaml("seq"), null)); + var result = setAnchor(seq, new SequenceNode(Tag.yaml('seq'), null)); result.content = super.visitSequence(seq); return result; } @@ -83,10 +87,10 @@ class Composer extends Visitor { Node visitMapping(MappingNode map) { var tagName = map.tag.name; if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("map")) { - throw new YamlException("invalid tag for mapping: ${tagName}"); + throw new YamlException("Invalid tag for mapping: ${map.tag}."); } - var result = setAnchor(map, new MappingNode(Tag.yaml("map"), null)); + var result = setAnchor(map, new MappingNode(Tag.yaml('map'), null)); result.content = super.visitMapping(map); return result; } diff --git a/pkgs/yaml/lib/src/constructor.dart b/pkgs/yaml/lib/src/constructor.dart index 428c476e5..116809dfb 100644 --- a/pkgs/yaml/lib/src/constructor.dart +++ b/pkgs/yaml/lib/src/constructor.dart @@ -2,7 +2,7 @@ // 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 constructor; +library yaml.constructor; import 'model.dart'; import 'visitor.dart'; diff --git a/pkgs/yaml/lib/src/deep_equals.dart b/pkgs/yaml/lib/src/deep_equals.dart index 1e1f7ed76..68fb236a0 100644 --- a/pkgs/yaml/lib/src/deep_equals.dart +++ b/pkgs/yaml/lib/src/deep_equals.dart @@ -2,75 +2,80 @@ // 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 deep_equals; +library yaml.deep_equals; /// Returns whether two objects are structurally equivalent. /// /// This considers `NaN` values to be equivalent. It also handles /// self-referential structures. -bool deepEquals(obj1, obj2, [List parents1, List parents2]) { - if (identical(obj1, obj2)) return true; - if (parents1 == null) { - parents1 = []; - parents2 = []; - } +bool deepEquals(obj1, obj2) => new _DeepEquals().equals(obj1, obj2); - // parents1 and parents2 are guaranteed to be the same size. - for (var i = 0; i < parents1.length; i++) { - var loop1 = identical(obj1, parents1[i]); - var loop2 = identical(obj2, parents2[i]); - // If both structures loop in the same place, they're equal at that point in - // the structure. If one loops and the other doesn't, they're not equal. - if (loop1 && loop2) return true; - if (loop1 || loop2) return false; - } +/// A class that provides access to the list of parent objects used for loop +/// detection. +class _DeepEquals { + final _parents1 = []; + final _parents2 = []; + + /// Returns whether [obj1] and [obj2] are structurally equivalent. + bool equals(obj1, obj2) { + // _parents1 and _parents2 are guaranteed to be the same size. + for (var i = 0; i < _parents1.length; i++) { + var loop1 = identical(obj1, _parents1[i]); + var loop2 = identical(obj2, _parents2[i]); + // If both structures loop in the same place, they're equal at that point + // in the structure. If one loops and the other doesn't, they're not + // equal. + if (loop1 && loop2) return true; + if (loop1 || loop2) return false; + } - parents1.add(obj1); - parents2.add(obj2); - try { - if (obj1 is List && obj2 is List) { - return _listEquals(obj1, obj2, parents1, parents2); - } else if (obj1 is Map && obj2 is Map) { - return _mapEquals(obj1, obj2, parents1, parents2); - } else if (obj1 is num && obj2 is num) { - return _numEquals(obj1, obj2); - } else { - return obj1 == obj2; + _parents1.add(obj1); + _parents2.add(obj2); + try { + if (obj1 is List && obj2 is List) { + return _listEquals(obj1, obj2); + } else if (obj1 is Map && obj2 is Map) { + return _mapEquals(obj1, obj2); + } else if (obj1 is num && obj2 is num) { + return _numEquals(obj1, obj2); + } else { + return obj1 == obj2; + } + } finally { + _parents1.removeLast(); + _parents2.removeLast(); } - } finally { - parents1.removeLast(); - parents2.removeLast(); } -} -/// Returns whether [list1] and [list2] are structurally equal. -bool _listEquals(List list1, List list2, List parents1, List parents2) { - if (list1.length != list2.length) return false; + /// Returns whether [list1] and [list2] are structurally equal. + bool _listEquals(List list1, List list2) { + if (list1.length != list2.length) return false; + + for (var i = 0; i < list1.length; i++) { + if (!equals(list1[i], list2[i])) return false; + } - for (var i = 0; i < list1.length; i++) { - if (!deepEquals(list1[i], list2[i], parents1, parents2)) return false; + return true; } - return true; -} + /// Returns whether [map1] and [map2] are structurally equal. + bool _mapEquals(Map map1, Map map2) { + if (map1.length != map2.length) return false; -/// Returns whether [map1] and [map2] are structurally equal. -bool _mapEquals(Map map1, Map map2, List parents1, List parents2) { - if (map1.length != map2.length) return false; + for (var key in map1.keys) { + if (!map2.containsKey(key)) return false; + if (!equals(map1[key], map2[key])) return false; + } - for (var key in map1.keys) { - if (!map2.containsKey(key)) return false; - if (!deepEquals(map1[key], map2[key], parents1, parents2)) return false; + return true; } - return true; -} - -/// Returns whether two numbers are equivalent. -/// -/// This differs from `n1 == n2` in that it considers `NaN` to be equal to -/// itself. -bool _numEquals(num n1, num n2) { - if (n1.isNaN && n2.isNaN) return true; - return n1 == n2; + /// Returns whether two numbers are equivalent. + /// + /// This differs from `n1 == n2` in that it considers `NaN` to be equal to + /// itself. + bool _numEquals(num n1, num n2) { + if (n1.isNaN && n2.isNaN) return true; + return n1 == n2; + } } diff --git a/pkgs/yaml/lib/src/model.dart b/pkgs/yaml/lib/src/model.dart index 37247f0dd..564cac6b6 100644 --- a/pkgs/yaml/lib/src/model.dart +++ b/pkgs/yaml/lib/src/model.dart @@ -5,39 +5,38 @@ /// This file contains the node classes for the internal representations of YAML /// documents. These nodes are used for both the serialization tree and the /// representation graph. -library model; +library yaml.model; import 'parser.dart'; import 'utils.dart'; import 'visitor.dart'; import 'yaml_exception.dart'; +/// The prefix for tag types defined by the YAML spec. +const _YAML_URI_PREFIX = "tag:yaml.org,2002:"; + /// A tag that indicates the type of a YAML node. class Tag { - // TODO(nweiz): it would better match the semantics of the spec if there were - // a singleton instance of this class for each tag. - - static const SCALAR_KIND = 0; - static const SEQUENCE_KIND = 1; - static const MAPPING_KIND = 2; - - static const String YAML_URI_PREFIX = 'tag:yaml.org,2002:'; - /// The name of the tag, either a URI or a local tag beginning with "!". final String name; - /// The kind of the tag: SCALAR_KIND, SEQUENCE_KIND, or MAPPING_KIND. - final int kind; - - Tag(this.name, this.kind); - - Tag.scalar(String name) : this(name, SCALAR_KIND); - Tag.sequence(String name) : this(name, SEQUENCE_KIND); - Tag.mapping(String name) : this(name, MAPPING_KIND); + /// The kind of the tag. + final TagKind kind; /// Returns the standard YAML tag URI for [type]. static String yaml(String type) => "tag:yaml.org,2002:$type"; + const Tag(this.name, this.kind); + + const Tag.scalar(String name) + : this(name, TagKind.SCALAR); + + const Tag.sequence(String name) + : this(name, TagKind.SEQUENCE); + + const Tag.mapping(String name) + : this(name, TagKind.MAPPING); + /// Two tags are equal if their URIs are equal. operator ==(other) { if (other is! Tag) return false; @@ -45,8 +44,8 @@ class Tag { } String toString() { - if (name.startsWith(YAML_URI_PREFIX)) { - return '!!${name.substring(YAML_URI_PREFIX.length)}'; + if (name.startsWith(_YAML_URI_PREFIX)) { + return '!!${name.substring(_YAML_URI_PREFIX.length)}'; } else { return '!<$name>'; } @@ -55,6 +54,24 @@ class Tag { int get hashCode => name.hashCode; } +/// An enum for kinds of tags. +class TagKind { + /// A tag indicating that the value is a scalar. + static const SCALAR = const TagKind._("scalar"); + + /// A tag indicating that the value is a sequence. + static const SEQUENCE = const TagKind._("sequence"); + + /// A tag indicating that the value is a mapping. + static const MAPPING = const TagKind._("mapping"); + + final String name; + + const TagKind._(this.name); + + String toString() => name; +} + /// The abstract class for YAML nodes. abstract class Node { /// Every YAML node has a tag that describes its type. @@ -185,7 +202,7 @@ class ScalarNode extends Node { return '"${escapedValue.join()}"'; } - throw new YamlException("unknown scalar value: $value"); + throw new YamlException('Unknown scalar value: "$value".'); } String toString() => '$tag "$content"'; diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 162fef475..d1e20ff74 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -2,7 +2,7 @@ // 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 parser; +library yaml.parser; import 'dart:collection'; @@ -407,23 +407,24 @@ class Parser { error(String message) { // Line and column should be one-based. throw new SyntaxError(_line + 1, _column + 1, - "$message (in $_farthestContext)"); + "$message (in $_farthestContext)."); } /// If [result] is falsey, throws an error saying that [expected] was /// expected. expect(result, String expected) { if (truth(result)) return result; - error("expected $expected"); + error("Expected $expected"); } /// Throws an error saying that the parse failed. Uses [_farthestLine], - /// [_farthestColumn], and [_farthestContext] to provide additional information. + /// [_farthestColumn], and [_farthestContext] to provide additional + /// information. parseFailed() { - var message = "invalid YAML in $_farthestContext"; + var message = "Invalid YAML in $_farthestContext"; var extraError = _errorAnnotations[_farthestPos]; if (extraError != null) message = "$message ($extraError)"; - throw new SyntaxError(_farthestLine + 1, _farthestColumn + 1, message); + throw new SyntaxError(_farthestLine + 1, _farthestColumn + 1, "$message."); } /// Returns the number of spaces after the current position. @@ -788,7 +789,7 @@ class Parser { case BLOCK_KEY: case FLOW_KEY: return s_separateInLine(); - default: throw 'invalid context "$ctx"'; + default: throw 'Invalid context "$ctx".'; } } @@ -1014,7 +1015,7 @@ class Parser { var char = peek(); var indicator = indicatorType(char); if (indicator == C_RESERVED) { - error("reserved indicators can't start a plain scalar"); + error("Reserved indicators can't start a plain scalar"); } var match = (isNonSpace(char) && indicator == null) || ((indicator == C_MAPPING_KEY || @@ -1037,7 +1038,7 @@ class Parser { case FLOW_KEY: // 129 return isNonSpace(char) && !isFlowIndicator(char); - default: throw 'invalid context "$ctx"'; + default: throw 'Invalid context "$ctx".'; } } @@ -1066,7 +1067,7 @@ class Parser { case BLOCK_KEY: case FLOW_KEY: return ns_plainOneLine(ctx); - default: throw 'invalid context "$ctx"'; + default: throw 'Invalid context "$ctx".'; } }); }); diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index a87555d62..64cad4727 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -2,38 +2,33 @@ // 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 utils; +library yaml.utils; -/// Returns the hash code for [obj]. This includes null, true, false, maps, and -/// lists. Also handles self-referential structures. -int hashCodeFor(obj, [List parents]) { - if (parents == null) { - parents = []; - } else if (parents.any((p) => identical(p, obj))) { - return -1; - } +import 'package:collection/collection.dart'; - parents.add(obj); - try { - if (obj == null) return 0; - if (obj == true) return 1; - if (obj == false) return 2; - if (obj is Map) { - return hashCodeFor(obj.keys, parents) ^ - hashCodeFor(obj.values, parents); - } - if (obj is Iterable) { - // This is probably a really bad hash function, but presumably we'll get - // this in the standard library before it actually matters. - int hash = 0; - for (var e in obj) { - hash ^= hashCodeFor(e, parents); +/// Returns a hash code for [obj] such that structurally equivalent objects +/// will have the same hash code. +/// +/// This supports deep equality for maps and lists, including those with +/// self-referential structures. +int hashCodeFor(obj) { + var parents = []; + + _hashCodeFor(value) { + if (parents.any((parent) => identical(parent, value))) return -1; + + parents.add(value); + try { + if (value is Map) { + return _hashCodeFor(value.keys) ^ _hashCodeFor(value.values); + } else if (value is Iterable) { + return const IterableEquality().hash(value.map(hashCodeFor)); } - return hash; + return value.hashCode; + } finally { + parents.removeLast(); } - return obj.hashCode; - } finally { - parents.removeLast(); } -} + return _hashCodeFor(obj); +} diff --git a/pkgs/yaml/lib/src/visitor.dart b/pkgs/yaml/lib/src/visitor.dart index 4a9c54f26..7095268d3 100644 --- a/pkgs/yaml/lib/src/visitor.dart +++ b/pkgs/yaml/lib/src/visitor.dart @@ -2,7 +2,7 @@ // 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 visitor; +library yaml.visitor; import 'model.dart'; import 'yaml_map.dart'; diff --git a/pkgs/yaml/lib/src/yaml_exception.dart b/pkgs/yaml/lib/src/yaml_exception.dart index 66697a18e..a86327413 100644 --- a/pkgs/yaml/lib/src/yaml_exception.dart +++ b/pkgs/yaml/lib/src/yaml_exception.dart @@ -2,7 +2,7 @@ // 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 yaml_exception; +library yaml.exception; /// An error thrown by the YAML processor. class YamlException implements Exception { diff --git a/pkgs/yaml/lib/src/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart index 5e3e20a6f..ff3da3654 100644 --- a/pkgs/yaml/lib/src/yaml_map.dart +++ b/pkgs/yaml/lib/src/yaml_map.dart @@ -2,86 +2,39 @@ // 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 yaml_map; +library yaml.map; + +import 'dart:collection'; + +import 'package:collection/collection.dart'; import 'deep_equals.dart'; import 'utils.dart'; -/// This class wraps behaves almost identically to the normal Dart Map +/// This class behaves almost identically to the normal Dart [Map] /// implementation, with the following differences: /// -/// * It allows null, NaN, boolean, list, and map keys. +/// * It allows NaN, list, and map keys. /// * It defines `==` structurally. That is, `yamlMap1 == yamlMap2` if they /// have the same contents. /// * It has a compatible [hashCode] method. -class YamlMap implements Map { - final Map _map; - - YamlMap() : _map = new Map(); - - YamlMap.from(Map map) : _map = new Map.from(map); - - YamlMap._wrap(this._map); - - void addAll(Map other) { - other.forEach((key, value) { - this[key] = value; - }); +/// +/// This class is deprecated. In future releases, this package will use +/// a [HashMap] with a custom equality operation rather than a custom class. +@Deprecated('1.0.0') +class YamlMap extends DelegatingMap { + YamlMap() + : super(new HashMap(equals: deepEquals, hashCode: hashCodeFor)); + + YamlMap.from(Map map) + : super(new HashMap(equals: deepEquals, hashCode: hashCodeFor)) { + addAll(map); } - bool containsValue(value) => _map.containsValue(value); - bool containsKey(key) => _map.containsKey(_wrapKey(key)); - operator [](key) => _map[_wrapKey(key)]; - operator []=(key, value) { _map[_wrapKey(key)] = value; } - putIfAbsent(key, ifAbsent()) => _map.putIfAbsent(_wrapKey(key), ifAbsent); - remove(key) => _map.remove(_wrapKey(key)); - void clear() => _map.clear(); - void forEach(void f(key, value)) => - _map.forEach((k, v) => f(_unwrapKey(k), v)); - Iterable get keys => _map.keys.map(_unwrapKey); - Iterable get values => _map.values; - int get length => _map.length; - bool get isEmpty => _map.isEmpty; - bool get isNotEmpty => _map.isNotEmpty; - String toString() => _map.toString(); - - int get hashCode => hashCodeFor(_map); + int get hashCode => hashCodeFor(this); bool operator ==(other) { if (other is! YamlMap) return false; return deepEquals(this, other); } - - /// Wraps an object for use as a key in the map. - _wrapKey(obj) { - if (obj != null && obj is! bool && obj is! List && - (obj is! num || !obj.isNaN) && - (obj is! Map || obj is YamlMap)) { - return obj; - } else if (obj is Map) { - return new YamlMap._wrap(obj); - } - return new _WrappedHashKey(obj); - } - - /// Unwraps an object that was used as a key in the map. - _unwrapKey(obj) => obj is _WrappedHashKey ? obj.value : obj; -} - -/// A class for wrapping normally-unhashable objects that are being used as keys -/// in a YamlMap. -class _WrappedHashKey { - final value; - - _WrappedHashKey(this.value); - - int get hashCode => hashCodeFor(value); - - String toString() => value.toString(); - - /// This is defined as both values being structurally equal. - bool operator ==(other) { - if (other is! _WrappedHashKey) return false; - return deepEquals(this.value, other.value); - } } diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index fa5286164..dc895e655 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -2,44 +2,6 @@ // 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. -/// A parser for [YAML](http://www.yaml.org/). -/// -/// ## Installing ## -/// -/// Use [pub][] to install this package. Add the following to your -/// `pubspec.yaml` file. -/// -/// dependencies: -/// yaml: any -/// -/// Then run `pub install`. -/// -/// For more information, see the -/// [yaml package on pub.dartlang.org][pkg]. -/// -/// ## Using ## -/// -/// Use [loadYaml] to load a single document, or [loadYamlStream] to load a -/// stream of documents. For example: -/// -/// import 'package:yaml/yaml.dart'; -/// main() { -/// var doc = loadYaml("YAML: YAML Ain't Markup Language"); -/// print(doc['YAML']); -/// } -/// -/// This library currently doesn't support dumping to YAML. You should use -/// `JSON.encode` from `dart:convert` instead: -/// -/// import 'dart:convert'; -/// import 'package:yaml/yaml.dart'; -/// main() { -/// var doc = loadYaml("YAML: YAML Ain't Markup Language"); -/// print(JSON.encode(doc)); -/// } -/// -/// [pub]: http://pub.dartlang.org -/// [pkg]: http://pub.dartlang.org/packages/yaml library yaml; import 'src/composer.dart'; @@ -50,18 +12,23 @@ import 'src/yaml_exception.dart'; export 'src/yaml_exception.dart'; export 'src/yaml_map.dart'; -/// Loads a single document from a YAML string. If the string contains more than -/// one document, this throws an error. +/// Loads a single document from a YAML string. +/// +/// If the string contains more than one document, this throws a +/// [YamlException]. In future releases, this will become an [ArgumentError]. /// /// The return value is mostly normal Dart objects. However, since YAML mappings /// support some key types that the default Dart map implementation doesn't -/// (null, NaN, booleans, lists, and maps), all maps in the returned document -/// are [YamlMap]s. These have a few small behavioral differences from the -/// default Map implementation; for details, see the [YamlMap] class. +/// (NaN, lists, and maps), all maps in the returned document are [YamlMap]s. +/// These have a few small behavioral differences from the default Map +/// implementation; for details, see the [YamlMap] class. +/// +/// In future versions, maps will instead be [HashMap]s with a custom equality +/// operation. loadYaml(String yaml) { var stream = loadYamlStream(yaml); if (stream.length != 1) { - throw new YamlException("Expected 1 document, were ${stream.length}"); + throw new YamlException("Expected 1 document, were ${stream.length}."); } return stream[0]; } @@ -70,9 +37,12 @@ loadYaml(String yaml) { /// /// The return value is mostly normal Dart objects. However, since YAML mappings /// support some key types that the default Dart map implementation doesn't -/// (null, NaN, booleans, lists, and maps), all maps in the returned document -/// are [YamlMap]s. These have a few small behavioral differences from the -/// default Map implementation; for details, see the [YamlMap] class. +/// (NaN, lists, and maps), all maps in the returned document are [YamlMap]s. +/// These have a few small behavioral differences from the default Map +/// implementation; for details, see the [YamlMap] class. +/// +/// In future versions, maps will instead be [HashMap]s with a custom equality +/// operation. List loadYamlStream(String yaml) { return new Parser(yaml).l_yamlStream() .map((doc) => new Constructor(new Composer(doc).compose()).construct()) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 1fb4c8d1b..c3eacd776 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,8 +1,10 @@ name: yaml -version: 0.9.0 +version: 0.9.0+1 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. +dependencies: + collection: ">=0.9.2 <0.10.0" dev_dependencies: unittest: ">=0.9.0 <0.10.0" environment: diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart new file mode 100644 index 000000000..0bac9f939 --- /dev/null +++ b/pkgs/yaml/test/utils.dart @@ -0,0 +1,83 @@ +// Copyright (c) 2014, 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 yaml.test.utils; + +import 'package:unittest/unittest.dart'; +import 'package:yaml/src/deep_equals.dart' as de; +import 'package:yaml/yaml.dart'; + +/// A matcher that validates that a closure or Future throws a [YamlException]. +final Matcher throwsYamlException = throwsA(new isInstanceOf()); + +/// Returns a matcher that asserts that the value equals [expected]. +/// +/// This handles recursive loops and considers `NaN` to equal itself. +Matcher deepEquals(expected) => + predicate((actual) => de.deepEquals(actual, expected), "equals $expected"); + +/// Constructs a new yaml.YamlMap, optionally from a normal Map. +Map yamlMap([Map from]) => + from == null ? new YamlMap() : new YamlMap.from(from); + +/// Asserts that a string containing a single YAML document produces a given +/// value when loaded. +void expectYamlLoads(expected, String source) { + var actual = loadYaml(cleanUpLiteral(source)); + expect(expected, deepEquals(actual)); +} + +/// Asserts that a string containing a stream of YAML documents produces a given +/// list of values when loaded. +void expectYamlStreamLoads(List expected, String source) { + var actual = loadYamlStream(cleanUpLiteral(source)); + expect(expected, deepEquals(actual)); +} + +/// Asserts that a string containing a single YAML document throws a +/// [YamlException]. +void expectYamlFails(String source) { + expect(() => loadYaml(cleanUpLiteral(source)), throwsYamlException); +} + +/// Removes eight spaces of leading indentation from a multiline string. +/// +/// Note that this is very sensitive to how the literals are styled. They should +/// be: +/// ''' +/// Text starts on own line. Lines up with subsequent lines. +/// Lines are indented exactly 8 characters from the left margin. +/// Close is on the same line.''' +/// +/// This does nothing if text is only a single line. +String cleanUpLiteral(String text) { + var lines = text.split('\n'); + if (lines.length <= 1) return text; + + for (var j = 0; j < lines.length; j++) { + if (lines[j].length > 8) { + lines[j] = lines[j].substring(8, lines[j].length); + } else { + lines[j] = ''; + } + } + + return lines.join('\n'); +} + +/// Indents each line of [text] so that, when passed to [cleanUpLiteral], it +/// will produce output identical to [text]. +/// +/// This is useful for literals that need to include newlines but can't be +/// conveniently represented as multi-line strings. +String indentLiteral(String text) { + var lines = text.split('\n'); + if (lines.length <= 1) return text; + + for (var i = 0; i < lines.length; i++) { + lines[i] = " ${lines[i]}"; + } + + return lines.join("\n"); +} diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 42cb6137d..fcfc12ef5 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -2,36 +2,13 @@ // 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 yaml_test; +library yaml.test; // TODO(rnystrom): rewrite tests so that they don't need "Expect". -import "package:expect/expect.dart"; import 'package:unittest/unittest.dart'; import 'package:yaml/yaml.dart'; -import 'package:yaml/src/deep_equals.dart'; -// TODO(jmesserly): we should not be reaching outside the YAML package -// The http package has a similar problem. -import '../../../tests/utils/test_utils.dart'; - -/// Constructs a new yaml.YamlMap, optionally from a normal Map. -Map yamlMap([Map from]) => - from == null ? new YamlMap() : new YamlMap.from(from); - -/// Asserts that a string containing a single YAML document produces a given -/// value when loaded. -expectYamlLoads(expected, String source) { - var actual = loadYaml(cleanUpLiteral(source)); - Expect.isTrue(deepEquals(expected, actual), - 'expectYamlLoads(expected: <$expected>, actual: <$actual>)'); -} -/// Asserts that a string containing a stream of YAML documents produces a given -/// list of values when loaded. -expectYamlStreamLoads(List expected, String source) { - var actual = loadYamlStream(cleanUpLiteral(source)); - Expect.isTrue(deepEquals(expected, actual), - 'expectYamlStreamLoads(expected: <$expected>, actual: <$actual>)'); -} +import 'utils.dart'; main() { var infinity = double.parse("Infinity"); @@ -500,7 +477,7 @@ main() { expectDisallowsCharacter(int charCode) { var char = new String.fromCharCodes([charCode]); - Expect.throws(() => loadYaml('The character "$char" is disallowed')); + expectYamlFails('The character "$char" is disallowed'); } test("doesn't include C0 control characters", () { @@ -598,8 +575,8 @@ main() { // }); test('[Example 5.10]', () { - Expect.throws(() => loadYaml("commercial-at: @text")); - Expect.throws(() => loadYaml("commercial-at: `text")); + expectYamlFails("commercial-at: @text"); + expectYamlFails("commercial-at: `text"); }); }); @@ -610,7 +587,7 @@ main() { }); group('do not include', () { - test('form feed', () => Expect.throws(() => loadYaml("- 1\x0C- 2"))); + test('form feed', () => expectYamlFails("- 1\x0C- 2")); test('NEL', () => expectYamlLoads(["1\x85- 2"], "- 1\x85- 2")); test('0x2028', () => expectYamlLoads(["1\u2028- 2"], "- 1\u2028- 2")); test('0x2029', () => expectYamlLoads(["1\u2029- 2"], "- 1\u2029- 2")); @@ -669,27 +646,27 @@ main() { }); test('[Example 5.14]', () { - Expect.throws(() => loadYaml('Bad escape: "\\c"')); - Expect.throws(() => loadYaml('Bad escape: "\\xq-"')); + expectYamlFails('Bad escape: "\\c"'); + expectYamlFails('Bad escape: "\\xq-"'); }); }); // Chapter 6: Basic Structures group('6.1: Indentation Spaces', () { test('may not include TAB characters', () { - Expect.throws(() => loadYaml(cleanUpLiteral( + expectYamlFails( """ - \t- foo - \t- bar"""))); + \t- bar"""); }); test('must be the same for all sibling nodes', () { - Expect.throws(() => loadYaml(cleanUpLiteral( + expectYamlFails( """ - - foo - - bar"""))); + - bar"""); }); test('may be different for the children of sibling nodes', () { @@ -916,10 +893,10 @@ main() { group('6.7: Separation Lines', () { test('may not be used within implicit keys', () { - Expect.throws(() => loadYaml(cleanUpLiteral( + expectYamlFails( """ [1, - 2]: 3"""))); + 2]: 3"""); }); test('[Example 6.12]', () { @@ -960,11 +937,11 @@ main() { // }); // test('[Example 6.15]', () { - // Expect.throws(() => loadYaml(cleanUpLiteral( + // expectYamlFails( // """ // %YAML 1.2 // %YAML 1.1 - // foo"""))); + // foo"""); // }); // test('[Example 6.16]', () { @@ -976,11 +953,11 @@ main() { // }); // test('[Example 6.17]', () { - // Expect.throws(() => loadYaml(cleanUpLiteral( + // ExpectYamlFails( // """ // %TAG ! !foo // %TAG ! !foo - // bar"""))); + // bar"""); // }); // Examples 6.18 through 6.22 test custom tag URIs, which this @@ -1010,8 +987,8 @@ main() { // // doesn't plan to support. // test('[Example 6.25]', () { - // Expect.throws(() => loadYaml("- ! foo")); - // Expect.throws(() => loadYaml("- !<\$:?> foo")); + // expectYamlFails("- ! foo"); + // expectYamlFails("- !<\$:?> foo"); // }); // // Examples 6.26 and 6.27 test custom tag URIs, which this implementation @@ -1040,10 +1017,10 @@ main() { // Chapter 7: Flow Styles group('7.1: Alias Nodes', () { // test("must not use an anchor that doesn't previously occur", () { - // Expect.throws(() => loadYaml(cleanUpLiteral( + // expectYamlFails( // """ // - *anchor - // - &anchor foo""")); + // - &anchor foo"""); // }); // test("don't have to exist for a given anchor node", () { @@ -1051,18 +1028,17 @@ main() { // }); // group('must not specify', () { - // test('tag properties', () => Expect.throws(() => loadYaml(cleanUpLiteral( + // test('tag properties', () => expectYamlFails( // """ // - &anchor foo - // - !str *anchor"""))); + // - !str *anchor"""); - // test('anchor properties', () => Expect.throws( - // () => loadYaml(cleanUpLiteral( + // test('anchor properties', () => expectYamlFails( // """ // - &anchor foo - // - &anchor2 *anchor"""))); + // - &anchor2 *anchor"""); - // test('content', () => Expect.throws(() => loadYaml(cleanUpLiteral( + // test('content', () => expectYamlFails( // """ // - &anchor foo // - *anchor bar"""))); @@ -1075,9 +1051,7 @@ main() { // alias: *anchor"""); // var anchorList = doc['anchor']; // var aliasList = doc['alias']; - // Expect.isTrue(anchorList === aliasList); - // anchorList.add('d'); - // Expect.listEquals(['a', 'b', 'c', 'd'], aliasList); + // expect(anchorList, same(aliasList)); // doc = loadYaml(cleanUpLiteral( // """ @@ -1086,9 +1060,7 @@ main() { // : bar"""); // anchorList = doc.keys[0]; // aliasList = doc[['a', 'b', 'c']].keys[0]; - // Expect.isTrue(anchorList === aliasList); - // anchorList.add('d'); - // Expect.listEquals(['a', 'b', 'c', 'd'], aliasList); + // expect(anchorList, same(aliasList)); // }); // test('[Example 7.1]', () { @@ -1344,15 +1316,15 @@ main() { }); test('[Example 7.22]', () { - Expect.throws(() => loadYaml(cleanUpLiteral( + expectYamlFails( """ [ foo - bar: invalid ]"""))); + bar: invalid ]"""); // TODO(nweiz): enable this when we throw an error for long keys // var dotList = new List.filled(1024, ' '); // var dots = dotList.join(); - // Expect.throws(() => loadYaml('[ "foo...$dots...bar": invalid ]')); + // expectYamlFails('[ "foo...$dots...bar": invalid ]'); }); }); @@ -1421,22 +1393,22 @@ main() { }); test('[Example 8.3]', () { - Expect.throws(() => loadYaml(cleanUpLiteral( + expectYamlFails( """ - | - text"""))); + text"""); - Expect.throws(() => loadYaml(cleanUpLiteral( + expectYamlFails( """ - > text - text"""))); + text"""); - Expect.throws(() => loadYaml(cleanUpLiteral( + expectYamlFails( """ - |2 - text"""))); + text"""); }); test('[Example 8.4]', () { From c50a54b87a50dc45dbaabe00fb14e9f2d35fd2cb Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 20 May 2014 23:14:05 +0000 Subject: [PATCH 032/179] Ensure that YAML maps' map keys are order-independent. R=jmesserly@google.com BUG= Review URL: https://codereview.chromium.org//297753003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@36399 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/lib/src/utils.dart | 4 +++- pkgs/yaml/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 695e06971..7d1fafd52 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.0+2 + +* Ensure that maps are order-independent when used as map keys. + ## 0.9.0+1 * The `YamlMap` class is deprecated. In a future version, maps returned by diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 64cad4727..463af7013 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -20,7 +20,9 @@ int hashCodeFor(obj) { parents.add(value); try { if (value is Map) { - return _hashCodeFor(value.keys) ^ _hashCodeFor(value.values); + var equality = const UnorderedIterableEquality(); + return equality.hash(value.keys.map(_hashCodeFor)) ^ + equality.hash(value.values.map(_hashCodeFor)); } else if (value is Iterable) { return const IterableEquality().hash(value.map(hashCodeFor)); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index c3eacd776..7186de050 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 0.9.0+1 +version: 0.9.0+2 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. From 1fe46735dd5ecc448fbbb866d65a7ef4edfebc23 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 2 Jun 2014 20:31:34 +0000 Subject: [PATCH 033/179] Use SpanScanner to emit better YAML parse errors. R=efortuna@google.com, jmesserly@google.com, rnystrom@google.com Review URL: https://codereview.chromium.org//308743007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@36897 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 4 + pkgs/yaml/lib/src/parser.dart | 178 ++++++++++++---------------------- pkgs/yaml/lib/yaml.dart | 21 +++- pkgs/yaml/pubspec.yaml | 5 +- 4 files changed, 86 insertions(+), 122 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 7d1fafd52..3520d4cde 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.0 + +* Improve error messages when a file fails to parse. + ## 0.9.0+2 * Ensure that maps are order-independent when used as map keys. diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index d1e20ff74..d203c32e2 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -6,6 +6,8 @@ library yaml.parser; import 'dart:collection'; +import 'package:string_scanner/string_scanner.dart'; + import 'model.dart'; import 'yaml_exception.dart'; import 'yaml_map.dart'; @@ -116,48 +118,28 @@ class Parser { static const CHOMPING_KEEP = 1; static const CHOMPING_CLIP = 2; - /// The source string being parsed. - final String _s; - - /// The current position in the source string. - int _pos = 0; - - /// The length of the string being parsed. - final int _len; - - /// The current (0-based) line in the source string. - int _line = 0; - - /// The current (0-based) column in the source string. - int _column = 0; + /// The scanner that's used to scan through the document. + final SpanScanner _scanner; /// Whether we're parsing a bare document (that is, one that doesn't begin /// with `---`). Bare documents don't allow `%` immediately following /// newlines. bool _inBareDocument = false; - /// The line number of the farthest position that has been parsed successfully - /// before backtracking. Used for error reporting. - int _farthestLine = 0; - - /// The column number of the farthest position that has been parsed - /// successfully before backtracking. Used for error reporting. - int _farthestColumn = 0; - - /// The farthest position in the source string that has been parsed - /// successfully before backtracking. Used for error reporting. - int _farthestPos = 0; + /// The state of the scanner when it was the farthest in the document it's + /// been. + LineScannerState _farthestState; /// The name of the context of the farthest position that has been parsed /// successfully before backtracking. Used for error reporting. String _farthestContext = "document"; /// A stack of the names of parse contexts. Used for error reporting. - List _contextStack; + final _contextStack = ["document"]; /// Annotations attached to ranges of the source string that add extra /// information to any errors that occur in the annotated range. - _RangeMap _errorAnnotations; + final _errorAnnotations = new _RangeMap(); /// The buffer containing the string currently being captured. StringBuffer _capturedString; @@ -168,46 +150,18 @@ class Parser { /// Whether the current string capture is being overridden. bool _capturingAs = false; - Parser(String s) - : this._s = s, - _len = s.length, - _contextStack = ["document"], - _errorAnnotations = new _RangeMap(); - - /// Return the character at the current position, then move that position - /// forward one character. Also updates the current line and column numbers. - int next() { - if (_pos == _len) return -1; - var char = _s.codeUnitAt(_pos++); - if (isBreak(char)) { - _line++; - _column = 0; - } else { - _column++; - } - - if (_farthestLine < _line) { - _farthestLine = _line; - _farthestColumn = _column; - _farthestContext = _contextStack.last; - } else if (_farthestLine == _line && _farthestColumn < _column) { - _farthestColumn = _column; - _farthestContext = _contextStack.last; - } - _farthestPos = _pos; - - return char; + Parser(String yaml, String sourceName) + : _scanner = new SpanScanner(yaml, sourceName) { + _farthestState = _scanner.state; } + /// Returns the character at the current position, then moves that position + /// forward one character. + int next() => _scanner.readChar(); + /// Returns the code unit at the current position, or the character [i] /// characters after the current position. - /// - /// Returns -1 if this would return a character after the end or before the - /// beginning of the input string. - int peek([int i = 0]) { - var peekPos = _pos + i; - return (peekPos >= _len || peekPos < 0) ? -1 : _s.codeUnitAt(peekPos); - } + int peek([int i = 0]) => _scanner.peekChar(i); /// The truthiness operator. Returns `false` if [obj] is `null` or `false`, /// `true` otherwise. @@ -249,11 +203,11 @@ class Parser { /// Conceptually, repeats a production any number of times. List zeroOrMore(consumer()) { var out = []; - var oldPos = _pos; + var oldPos = _scanner.position; while (true) { var el = consumer(); - if (!truth(el) || oldPos == _pos) return out; - oldPos = _pos; + if (!truth(el) || oldPos == _scanner.position) return out; + oldPos = _scanner.position; out.add(el); } return null; // Unreachable. @@ -276,18 +230,15 @@ class Parser { /// Calls [consumer] and returns its result, but rolls back the parser state /// if [consumer] returns a falsey value. transaction(consumer()) { - var oldPos = _pos; - var oldLine = _line; - var oldColumn = _column; + var oldState = _scanner.state; var oldCaptureStart = _captureStart; String capturedSoFar = _capturedString == null ? null : _capturedString.toString(); var res = consumer(); + _refreshFarthestState(); if (truth(res)) return res; - _pos = oldPos; - _line = oldLine; - _column = oldColumn; + _scanner.state = oldState; _captureStart = oldCaptureStart; _capturedString = capturedSoFar == null ? null : new StringBuffer(capturedSoFar); @@ -324,7 +275,7 @@ class Parser { // captureString calls may not be nested assert(_capturedString == null); - _captureStart = _pos; + _captureStart = _scanner.position; _capturedString = new StringBuffer(); var res = transaction(consumer); if (!truth(res)) { @@ -353,14 +304,16 @@ class Parser { _capturingAs = false; if (!truth(res)) return res; - _capturedString.write(transformation(_s.substring(_captureStart, _pos))); - _captureStart = _pos; + _capturedString.write(transformation( + _scanner.string.substring(_captureStart, _scanner.position))); + _captureStart = _scanner.position; return res; } void flushCapture() { - _capturedString.write(_s.substring(_captureStart, _pos)); - _captureStart = _pos; + _capturedString.write(_scanner.string.substring( + _captureStart, _scanner.position)); + _captureStart = _scanner.position; } /// Adds a tag and an anchor to [node], if they're defined. @@ -393,22 +346,19 @@ class Parser { /// current position and the position of the cursor after running [fn]. The /// cursor is reset after [fn] is run. annotateError(String message, fn()) { - var start = _pos; + var start = _scanner.position; var end; transaction(() { fn(); - end = _pos; + end = _scanner.position; return false; }); _errorAnnotations[new _Range(start, end)] = message; } /// Throws an error with additional context information. - error(String message) { - // Line and column should be one-based. - throw new SyntaxError(_line + 1, _column + 1, - "$message (in $_farthestContext)."); - } + void error(String message) => + _scanner.error("$message (in $_farthestContext)."); /// If [result] is falsey, throws an error saying that [expected] was /// expected. @@ -417,14 +367,24 @@ class Parser { error("Expected $expected"); } - /// Throws an error saying that the parse failed. Uses [_farthestLine], - /// [_farthestColumn], and [_farthestContext] to provide additional + /// Throws an error saying that the parse failed. + /// + /// Uses [_farthestState] and [_farthestContext] to provide additional /// information. parseFailed() { var message = "Invalid YAML in $_farthestContext"; - var extraError = _errorAnnotations[_farthestPos]; + _refreshFarthestState(); + _scanner.state = _farthestState; + + var extraError = _errorAnnotations[_scanner.position]; if (extraError != null) message = "$message ($extraError)"; - throw new SyntaxError(_farthestLine + 1, _farthestColumn + 1, "$message."); + _scanner.error("$message."); + } + + /// Update [_farthestState] if the scanner is farther than it's been before. + void _refreshFarthestState() { + if (_scanner.position <= _farthestState.position) return; + _farthestState = _scanner.state; } /// Returns the number of spaces after the current position. @@ -439,15 +399,11 @@ class Parser { if (!header.autoDetectIndent) return header.additionalIndent; var maxSpaces = 0; - var maxSpacesLine = 0; var spaces = 0; transaction(() { do { spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length; - if (spaces > maxSpaces) { - maxSpaces = spaces; - maxSpacesLine = _line; - } + if (spaces > maxSpaces) maxSpaces = spaces; } while (b_break()); return false; }); @@ -460,19 +416,15 @@ class Parser { // It's an error for a leading empty line to be indented more than the first // non-empty line. if (maxSpaces > spaces) { - throw new SyntaxError(maxSpacesLine + 1, maxSpaces, - "Leading empty lines may not be indented more than the first " - "non-empty line."); + _scanner.error("Leading empty lines may not be indented more than the " + "first non-empty line."); } return spaces - indent; } /// Returns whether the current position is at the beginning of a line. - bool get atStartOfLine => _column == 0; - - /// Returns whether the current position is at the end of the input. - bool get atEndOfFile => _pos == _len; + bool get atStartOfLine => _scanner.column == 0; /// Given an indicator character, returns the type of that indicator (or null /// if the indicator isn't found. @@ -504,6 +456,7 @@ class Parser { // 1 bool isPrintable(int char) { + if (char == null) return false; return char == TAB || char == LF || char == CR || @@ -515,7 +468,8 @@ class Parser { } // 2 - bool isJson(int char) => char == TAB || (char >= SP && char <= 0x10FFFF); + bool isJson(int char) => char != null && + (char == TAB || (char >= SP && char <= 0x10FFFF)); // 22 bool c_indicator(int type) => consume((c) => indicatorType(c) == type); @@ -558,10 +512,12 @@ class Parser { bool isNonSpace(int char) => isNonBreak(char) && !isSpace(char); // 35 - bool isDecDigit(int char) => char >= NUMBER_0 && char <= NUMBER_9; + bool isDecDigit(int char) => char != null && char >= NUMBER_0 && + char <= NUMBER_9; // 36 bool isHexDigit(int char) { + if (char == null) return false; return isDecDigit(char) || (char >= LETTER_A && char <= LETTER_F) || (char >= LETTER_CAP_A && char <= LETTER_CAP_F); @@ -754,7 +710,7 @@ class Parser { } // 76 - bool b_comment() => atEndOfFile || b_nonContent(); + bool b_comment() => _scanner.isDone || b_nonContent(); // 77 bool s_b_comment() { @@ -1428,7 +1384,7 @@ class Parser { // 165 bool b_chompedLast(int chomping) { - if (atEndOfFile) return true; + if (_scanner.isDone) return true; switch (chomping) { case CHOMPING_STRIP: return b_nonContent(); @@ -1810,7 +1766,7 @@ class Parser { transaction(() { if (!truth(or([c_directivesEnd, c_documentEnd]))) return; var char = peek(); - forbidden = isBreak(char) || isSpace(char) || atEndOfFile; + forbidden = isBreak(char) || isSpace(char) || _scanner.isDone; return; }); return forbidden; @@ -1871,21 +1827,11 @@ class Parser { return doc; }); - if (!atEndOfFile) parseFailed(); + if (!_scanner.isDone) parseFailed(); return docs; } } -class SyntaxError extends YamlException { - final int _line; - final int _column; - - SyntaxError(this._line, this._column, String msg) : super(msg); - - String toString() => "Syntax error on line $_line, column $_column: " - "${super.toString()}"; -} - /// A pair of values. class _Pair { E first; diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index dc895e655..209db8c3b 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -25,8 +25,11 @@ export 'src/yaml_map.dart'; /// /// In future versions, maps will instead be [HashMap]s with a custom equality /// operation. -loadYaml(String yaml) { - var stream = loadYamlStream(yaml); +/// +/// If [sourceName] is passed, it's used as the name of the file or URL from +/// which the YAML originated for error reporting. +loadYaml(String yaml, {String sourceName}) { + var stream = loadYamlStream(yaml, sourceName: sourceName); if (stream.length != 1) { throw new YamlException("Expected 1 document, were ${stream.length}."); } @@ -43,8 +46,18 @@ loadYaml(String yaml) { /// /// In future versions, maps will instead be [HashMap]s with a custom equality /// operation. -List loadYamlStream(String yaml) { - return new Parser(yaml).l_yamlStream() +/// +/// If [sourceName] is passed, it's used as the name of the file or URL from +/// which the YAML originated for error reporting. +List loadYamlStream(String yaml, {String sourceName}) { + var stream; + try { + stream = new Parser(yaml, sourceName).l_yamlStream(); + } on FormatException catch (error) { + throw new YamlException(error.toString()); + } + + return stream .map((doc) => new Constructor(new Composer(doc).compose()).construct()) .toList(); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 7186de050..5e1ed24ef 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,11 +1,12 @@ name: yaml -version: 0.9.0+2 +version: 0.10.0-dev author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dependencies: collection: ">=0.9.2 <0.10.0" + string_scanner: ">=0.0.2 <0.1.0" dev_dependencies: - unittest: ">=0.9.0 <0.10.0" + unittest: ">=0.9.0 <0.12.0" environment: sdk: ">=0.8.10+6 <2.0.0" From be352d6f37f46fe168752cc5de94f1fa8b0359dd Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 2 Jun 2014 23:14:13 +0000 Subject: [PATCH 034/179] Release yaml 0.10.0. R=rnystrom@google.com Review URL: https://codereview.chromium.org//310703002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@36905 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 5e1ed24ef..b57224c87 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 0.10.0-dev +version: 0.10.0 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. From 3e258175dd595bc06b6f6d9a9f77cb99f74235b1 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 3 Jun 2014 20:33:29 +0000 Subject: [PATCH 035/179] Attach source range information to parsed YAML nodes. Also release yaml 1.0.0. R=efortuna@google.com, rnystrom@google.com, sigmund@google.com Review URL: https://codereview.chromium.org//302313007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@36937 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 15 +++ pkgs/yaml/lib/src/composer.dart | 74 ++++++----- pkgs/yaml/lib/src/constructor.dart | 44 ++++--- .../src/{deep_equals.dart => equality.dart} | 53 +++++++- pkgs/yaml/lib/src/model.dart | 30 +++-- pkgs/yaml/lib/src/parser.dart | 123 +++++++++--------- pkgs/yaml/lib/src/utils.dart | 33 +---- pkgs/yaml/lib/src/visitor.dart | 4 +- pkgs/yaml/lib/src/yaml_map.dart | 40 ------ pkgs/yaml/lib/src/yaml_node.dart | 92 +++++++++++++ pkgs/yaml/lib/yaml.dart | 24 +++- pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/utils.dart | 17 ++- pkgs/yaml/test/yaml_test.dart | 53 ++------ 14 files changed, 355 insertions(+), 249 deletions(-) rename pkgs/yaml/lib/src/{deep_equals.dart => equality.dart} (59%) delete mode 100644 pkgs/yaml/lib/src/yaml_map.dart create mode 100644 pkgs/yaml/lib/src/yaml_node.dart diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 3520d4cde..4b243d813 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,18 @@ +## 1.0.0 + +* **Backwards incompatibility**: The data structures returned by `loadYaml` and + `loadYamlStream` are now immutable. + +* **Backwards incompatibility**: The interface of the `YamlMap` class has + changed substantially in numerous ways. External users may no longer construct + their own instances. + +* Maps and lists returned by `loadYaml` and `loadYamlStream` now contain + information about their source locations. + +* A new `loadYamlNode` function returns the source location of top-level scalars + as well. + ## 0.10.0 * Improve error messages when a file fails to parse. diff --git a/pkgs/yaml/lib/src/composer.dart b/pkgs/yaml/lib/src/composer.dart index 317809653..4c19da14a 100644 --- a/pkgs/yaml/lib/src/composer.dart +++ b/pkgs/yaml/lib/src/composer.dart @@ -4,6 +4,8 @@ library yaml.composer; +import 'package:source_maps/source_maps.dart'; + import 'model.dart'; import 'visitor.dart'; import 'yaml_exception.dart'; @@ -45,13 +47,13 @@ class Composer extends Visitor { /// Currently this only supports the YAML core type schema. Node visitScalar(ScalarNode scalar) { if (scalar.tag.name == "!") { - return setAnchor(scalar, parseString(scalar.content)); + return setAnchor(scalar, parseString(scalar)); } else if (scalar.tag.name == "?") { for (var fn in [parseNull, parseBool, parseInt, parseFloat]) { - var result = fn(scalar.content); + var result = fn(scalar); if (result != null) return result; } - return setAnchor(scalar, parseString(scalar.content)); + return setAnchor(scalar, parseString(scalar)); } var result = _parseByTag(scalar); @@ -62,11 +64,11 @@ class Composer extends Visitor { ScalarNode _parseByTag(ScalarNode scalar) { switch (scalar.tag.name) { - case "null": return parseNull(scalar.content); - case "bool": return parseBool(scalar.content); - case "int": return parseInt(scalar.content); - case "float": return parseFloat(scalar.content); - case "str": return parseString(scalar.content); + case "null": return parseNull(scalar); + case "bool": return parseBool(scalar); + case "int": return parseInt(scalar); + case "float": return parseFloat(scalar); + case "str": return parseString(scalar); } throw new YamlException('Undefined tag: ${scalar.tag}.'); } @@ -78,7 +80,8 @@ class Composer extends Visitor { throw new YamlException("Invalid tag for sequence: ${seq.tag}."); } - var result = setAnchor(seq, new SequenceNode(Tag.yaml('seq'), null)); + var result = setAnchor(seq, + new SequenceNode(Tag.yaml('seq'), null, seq.span)); result.content = super.visitSequence(seq); return result; } @@ -90,7 +93,8 @@ class Composer extends Visitor { throw new YamlException("Invalid tag for mapping: ${map.tag}."); } - var result = setAnchor(map, new MappingNode(Tag.yaml('map'), null)); + var result = setAnchor(map, + new MappingNode(Tag.yaml('map'), null, map.span)); result.content = super.visitMapping(map); return result; } @@ -105,36 +109,40 @@ class Composer extends Visitor { } /// Parses a null scalar. - ScalarNode parseNull(String content) { - if (!new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(content)) return null; - return new ScalarNode(Tag.yaml("null"), value: null); + ScalarNode parseNull(ScalarNode scalar) { + if (new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(scalar.content)) { + return new ScalarNode(Tag.yaml("null"), scalar.span, value: null); + } else { + return null; + } } /// Parses a boolean scalar. - ScalarNode parseBool(String content) { + ScalarNode parseBool(ScalarNode scalar) { var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"). - firstMatch(content); + firstMatch(scalar.content); if (match == null) return null; - return new ScalarNode(Tag.yaml("bool"), value: match.group(1) != null); + return new ScalarNode(Tag.yaml("bool"), scalar.span, + value: match.group(1) != null); } /// Parses an integer scalar. - ScalarNode parseInt(String content) { - var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(content); + ScalarNode parseInt(ScalarNode scalar) { + var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(scalar.content); if (match != null) { - return new ScalarNode(Tag.yaml("int"), + return new ScalarNode(Tag.yaml("int"), scalar.span, value: int.parse(match.group(0))); } - match = new RegExp(r"^0o([0-7]+)$").firstMatch(content); + match = new RegExp(r"^0o([0-7]+)$").firstMatch(scalar.content); if (match != null) { int n = int.parse(match.group(1), radix: 8); - return new ScalarNode(Tag.yaml("int"), value: n); + return new ScalarNode(Tag.yaml("int"), scalar.span, value: n); } - match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(content); + match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(scalar.content); if (match != null) { - return new ScalarNode(Tag.yaml("int"), + return new ScalarNode(Tag.yaml("int"), scalar.span, value: int.parse(match.group(0))); } @@ -142,33 +150,33 @@ class Composer extends Visitor { } /// Parses a floating-point scalar. - ScalarNode parseFloat(String content) { + ScalarNode parseFloat(ScalarNode scalar) { var match = new RegExp( - r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"). - firstMatch(content); + r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"). + firstMatch(scalar.content); if (match != null) { // YAML allows floats of the form "0.", but Dart does not. Fix up those // floats by removing the trailing dot. var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), ""); - return new ScalarNode(Tag.yaml("float"), + return new ScalarNode(Tag.yaml("float"), scalar.span, value: double.parse(matchStr)); } - match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(content); + match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(scalar.content); if (match != null) { var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; - return new ScalarNode(Tag.yaml("float"), value: value); + return new ScalarNode(Tag.yaml("float"), scalar.span, value: value); } - match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(content); + match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(scalar.content); if (match != null) { - return new ScalarNode(Tag.yaml("float"), value: double.NAN); + return new ScalarNode(Tag.yaml("float"), scalar.span, value: double.NAN); } return null; } /// Parses a string scalar. - ScalarNode parseString(String content) => - new ScalarNode(Tag.yaml("str"), value: content); + ScalarNode parseString(ScalarNode scalar) => + new ScalarNode(Tag.yaml("str"), scalar.span, value: scalar.content); } diff --git a/pkgs/yaml/lib/src/constructor.dart b/pkgs/yaml/lib/src/constructor.dart index 116809dfb..a8224a493 100644 --- a/pkgs/yaml/lib/src/constructor.dart +++ b/pkgs/yaml/lib/src/constructor.dart @@ -4,9 +4,10 @@ library yaml.constructor; +import 'equality.dart'; import 'model.dart'; import 'visitor.dart'; -import 'yaml_map.dart'; +import 'yaml_node.dart'; /// Takes a parsed and composed YAML document (what the spec calls the /// "representation graph") and creates native Dart objects that represent that @@ -16,43 +17,54 @@ class Constructor extends Visitor { final Node _root; /// Map from anchor names to the most recent Dart node with that anchor. - final _anchors = {}; + final _anchors = {}; Constructor(this._root); /// Runs the Constructor to produce a Dart object. - construct() => _root.visit(this); + YamlNode construct() => _root.visit(this); /// Returns the value of a scalar. - visitScalar(ScalarNode scalar) => scalar.value; + YamlScalar visitScalar(ScalarNode scalar) => + new YamlScalar(scalar.value, scalar.span); /// Converts a sequence into a List of Dart objects. - visitSequence(SequenceNode seq) { + YamlList visitSequence(SequenceNode seq) { var anchor = getAnchor(seq); if (anchor != null) return anchor; - var dartSeq = setAnchor(seq, []); - dartSeq.addAll(super.visitSequence(seq)); + var nodes = []; + var dartSeq = setAnchor(seq, new YamlList(nodes, seq.span)); + nodes.addAll(super.visitSequence(seq)); return dartSeq; } - /// Converts a mapping into a Map of Dart objects. - visitMapping(MappingNode map) { + /// Converts a mapping into a [Map] of Dart objects. + YamlMap visitMapping(MappingNode map) { var anchor = getAnchor(map); if (anchor != null) return anchor; - var dartMap = setAnchor(map, new YamlMap()); - super.visitMapping(map).forEach((k, v) { dartMap[k] = v; }); + var nodes = deepEqualsMap(); + var dartMap = setAnchor(map, new YamlMap(nodes, map.span)); + super.visitMapping(map).forEach((k, v) => nodes[k] = v); return dartMap; } - /// Returns the Dart object that already represents [anchored], if such a - /// thing exists. - getAnchor(Node anchored) { + /// Returns a new Dart object wrapping the object that already represents + /// [anchored], if such a thing exists. + YamlNode getAnchor(Node anchored) { if (anchored.anchor == null) return null; - if (_anchors.containsKey(anchored.anchor)) return _anchors[anchored.anchor]; + var value = _anchors[anchored.anchor]; + if (vaule == null) return null; + + // Re-wrap [value]'s contents so that it's associated with the span of the + // anchor rather than its original definition. + if (value is YamlMap) return new YamlMap(value.nodes, anchored.span); + if (value is YamlList) return new YamlList(value.nodes, anchored.span); + assert(value is YamlScalar); + return new YamlScalar(value.value, anchored.span); } /// Records that [value] is the Dart object representing [anchored]. - setAnchor(Node anchored, value) { + YamlNode setAnchor(Node anchored, YamlNode value) { if (anchored.anchor == null) return value; _anchors[anchored.anchor] = value; return value; diff --git a/pkgs/yaml/lib/src/deep_equals.dart b/pkgs/yaml/lib/src/equality.dart similarity index 59% rename from pkgs/yaml/lib/src/deep_equals.dart rename to pkgs/yaml/lib/src/equality.dart index 68fb236a0..540813599 100644 --- a/pkgs/yaml/lib/src/deep_equals.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -1,13 +1,22 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, 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 yaml.deep_equals; +library yaml.equality; + +import 'dart:collection'; + +import 'package:collection/collection.dart'; + +import 'yaml_node.dart'; + +/// Returns a [Map] that compares its keys based on [deepEquals]. +Map deepEqualsMap() => new HashMap(equals: deepEquals, hashCode: deepHashCode); /// Returns whether two objects are structurally equivalent. /// -/// This considers `NaN` values to be equivalent. It also handles -/// self-referential structures. +/// This considers `NaN` values to be equivalent, handles self-referential +/// structures, and considers [YamlScalar]s to be equal to their values. bool deepEquals(obj1, obj2) => new _DeepEquals().equals(obj1, obj2); /// A class that provides access to the list of parent objects used for loop @@ -18,6 +27,9 @@ class _DeepEquals { /// Returns whether [obj1] and [obj2] are structurally equivalent. bool equals(obj1, obj2) { + if (obj1 is YamlScalar) obj1 = obj1.value; + if (obj2 is YamlScalar) obj2 = obj2.value; + // _parents1 and _parents2 are guaranteed to be the same size. for (var i = 0; i < _parents1.length; i++) { var loop1 = identical(obj1, _parents1[i]); @@ -79,3 +91,36 @@ class _DeepEquals { return n1 == n2; } } + +/// Returns a hash code for [obj] such that structurally equivalent objects +/// will have the same hash code. +/// +/// This supports deep equality for maps and lists, including those with +/// self-referential structures, and returns the same hash code for +/// [YamlScalar]s and their values. +int deepHashCode(obj) { + var parents = []; + + _deepHashCode(value) { + if (parents.any((parent) => identical(parent, value))) return -1; + + parents.add(value); + try { + if (value is Map) { + var equality = const UnorderedIterableEquality(); + return equality.hash(value.keys.map(_deepHashCode)) ^ + equality.hash(value.values.map(_deepHashCode)); + } else if (value is Iterable) { + return const IterableEquality().hash(value.map(deepHashCode)); + } else if (value is YamlScalar) { + return value.value.hashCode; + } else { + return value.hashCode; + } + } finally { + parents.removeLast(); + } + } + + return _deepHashCode(obj); +} diff --git a/pkgs/yaml/lib/src/model.dart b/pkgs/yaml/lib/src/model.dart index 564cac6b6..f0e839c06 100644 --- a/pkgs/yaml/lib/src/model.dart +++ b/pkgs/yaml/lib/src/model.dart @@ -7,8 +7,10 @@ /// representation graph. library yaml.model; +import 'package:source_maps/source_maps.dart'; + +import 'equality.dart'; import 'parser.dart'; -import 'utils.dart'; import 'visitor.dart'; import 'yaml_exception.dart'; @@ -80,14 +82,17 @@ abstract class Node { /// Any YAML node can have an anchor associated with it. String anchor; - Node(this.tag, [this.anchor]); + /// The source span for this node. + Span span; + + Node(this.tag, this.span, [this.anchor]); bool operator ==(other) { if (other is! Node) return false; return tag == other.tag; } - int get hashCode => hashCodeFor([tag, anchor]); + int get hashCode => tag.hashCode ^ anchor.hashCode; visit(Visitor v); } @@ -97,8 +102,8 @@ class SequenceNode extends Node { /// The nodes in the sequence. List content; - SequenceNode(String tagName, this.content) - : super(new Tag.sequence(tagName)); + SequenceNode(String tagName, this.content, Span span) + : super(new Tag.sequence(tagName), span); /// Two sequences are equal if their tags and contents are equal. bool operator ==(other) { @@ -113,14 +118,15 @@ class SequenceNode extends Node { String toString() => '$tag [${content.map((e) => '$e').join(', ')}]'; - int get hashCode => super.hashCode ^ hashCodeFor(content); + int get hashCode => super.hashCode ^ deepHashCode(content); visit(Visitor v) => v.visitSequence(this); } /// An alias node is a reference to an anchor. class AliasNode extends Node { - AliasNode(String anchor) : super(new Tag.scalar(Tag.yaml("str")), anchor); + AliasNode(String anchor, Span span) + : super(new Tag.scalar(Tag.yaml("str")), span, anchor); visit(Visitor v) => v.visitAlias(this); } @@ -139,9 +145,9 @@ class ScalarNode extends Node { /// be specified for a newly-parsed scalar that hasn't yet been composed. /// Value should be specified for a composed scalar, although `null` is a /// valid value. - ScalarNode(String tagName, {String content, this.value}) + ScalarNode(String tagName, Span span, {String content, this.value}) : _content = content, - super(new Tag.scalar(tagName)); + super(new Tag.scalar(tagName), span); /// Two scalars are equal if their string representations are equal. bool operator ==(other) { @@ -225,8 +231,8 @@ class MappingNode extends Node { /// The node map. Map content; - MappingNode(String tagName, this.content) - : super(new Tag.mapping(tagName)); + MappingNode(String tagName, this.content, Span span) + : super(new Tag.mapping(tagName), span); /// Two mappings are equal if their tags and contents are equal. bool operator ==(other) { @@ -247,7 +253,7 @@ class MappingNode extends Node { return '$tag {$strContent}'; } - int get hashCode => super.hashCode ^ hashCodeFor(content); + int get hashCode => super.hashCode ^ deepHashCode(content); visit(Visitor v) => v.visitMapping(this); } diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index d203c32e2..98658e6a3 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -6,11 +6,13 @@ library yaml.parser; import 'dart:collection'; +import 'package:source_maps/source_maps.dart'; import 'package:string_scanner/string_scanner.dart'; +import 'equality.dart'; import 'model.dart'; +import 'utils.dart'; import 'yaml_exception.dart'; -import 'yaml_map.dart'; /// Translates a string of characters into a YAML serialization tree. /// @@ -317,7 +319,7 @@ class Parser { } /// Adds a tag and an anchor to [node], if they're defined. - Node addProps(Node node, _Pair props) { + Node addProps(Node node, Pair props) { if (props == null || node == null) return node; if (truth(props.first)) node.tag = props.first; if (truth(props.last)) node.anchor = props.last; @@ -325,10 +327,10 @@ class Parser { } /// Creates a MappingNode from [pairs]. - MappingNode map(List<_Pair> pairs) { + MappingNode map(List> pairs, Span span) { var content = new Map(); pairs.forEach((pair) => content[pair.first] = pair.last); - return new MappingNode("?", content); + return new MappingNode("?", content, span); } /// Runs [fn] in a context named [name]. Used for error reporting. @@ -759,7 +761,7 @@ class Parser { bool l_directive() => false; // TODO(nweiz): implement // 96 - _Pair c_ns_properties(int indent, int ctx) { + Pair c_ns_properties(int indent, int ctx) { var tag, anchor; tag = c_ns_tagProperty(); if (truth(tag)) { @@ -767,7 +769,7 @@ class Parser { if (!truth(s_separate(indent, ctx))) return null; return c_ns_anchorProperty(); }); - return new _Pair(tag, anchor); + return new Pair(tag, anchor); } anchor = c_ns_anchorProperty(); @@ -776,7 +778,7 @@ class Parser { if (!truth(s_separate(indent, ctx))) return null; return c_ns_tagProperty(); }); - return new _Pair(tag, anchor); + return new Pair(tag, anchor); } return null; @@ -797,13 +799,14 @@ class Parser { // 104 Node c_ns_aliasNode() { + var start = _scanner.state; if (!truth(c_indicator(C_ALIAS))) return null; var name = expect(ns_anchorName(), 'anchor name'); - return new AliasNode(name); + return new AliasNode(name, _scanner.spanFrom(start)); } // 105 - ScalarNode e_scalar() => new ScalarNode("?", content: ""); + ScalarNode e_scalar() => new ScalarNode("?", _scanner.emptySpan, content: ""); // 106 ScalarNode e_node() => e_scalar(); @@ -820,10 +823,11 @@ class Parser { // 109 Node c_doubleQuoted(int indent, int ctx) => context('string', () { return transaction(() { + var start = _scanner.state; if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; var contents = nb_doubleText(indent, ctx); if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; - return new ScalarNode("!", content: contents); + return new ScalarNode("!", _scanner.spanFrom(start), content: contents); }); }); @@ -908,10 +912,11 @@ class Parser { // 120 Node c_singleQuoted(int indent, int ctx) => context('string', () { return transaction(() { + var start = _scanner.state; if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; var contents = nb_singleText(indent, ctx); if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; - return new ScalarNode("!", content: contents); + return new ScalarNode("!", _scanner.spanFrom(start), content: contents); }); }); @@ -1075,11 +1080,13 @@ class Parser { // 137 SequenceNode c_flowSequence(int indent, int ctx) => transaction(() { + var start = _scanner.state; if (!truth(c_indicator(C_SEQUENCE_START))) return null; zeroOrOne(() => s_separate(indent, ctx)); var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx))); if (!truth(c_indicator(C_SEQUENCE_END))) return null; - return new SequenceNode("?", new List.from(content)); + return new SequenceNode("?", new List.from(content), + _scanner.spanFrom(start)); }); // 138 @@ -1108,17 +1115,18 @@ class Parser { // 140 Node c_flowMapping(int indent, int ctx) { + var start = _scanner.state; if (!truth(c_indicator(C_MAPPING_START))) return null; zeroOrOne(() => s_separate(indent, ctx)); var content = zeroOrOne(() => ns_s_flowMapEntries(indent, inFlow(ctx))); if (!truth(c_indicator(C_MAPPING_END))) return null; - return new MappingNode("?", content); + return new MappingNode("?", content, _scanner.spanFrom(start)); } // 141 - YamlMap ns_s_flowMapEntries(int indent, int ctx) { + Map ns_s_flowMapEntries(int indent, int ctx) { var first = ns_flowMapEntry(indent, ctx); - if (!truth(first)) return new YamlMap(); + if (!truth(first)) return deepEqualsMap(); zeroOrOne(() => s_separate(indent, ctx)); var rest; @@ -1127,7 +1135,7 @@ class Parser { rest = ns_s_flowMapEntries(indent, ctx); } - if (rest == null) rest = new YamlMap(); + if (rest == null) rest = deepEqualsMap(); // TODO(nweiz): Duplicate keys should be an error. This includes keys with // different representations but the same value (e.g. 10 vs 0xa). To make @@ -1139,7 +1147,7 @@ class Parser { } // 142 - _Pair ns_flowMapEntry(int indent, int ctx) => or([ + Pair ns_flowMapEntry(int indent, int ctx) => or([ () => transaction(() { if (!truth(c_indicator(C_MAPPING_KEY))) return false; if (!truth(s_separate(indent, ctx))) return false; @@ -1149,20 +1157,20 @@ class Parser { ]); // 143 - _Pair ns_flowMapExplicitEntry(int indent, int ctx) => or([ + Pair ns_flowMapExplicitEntry(int indent, int ctx) => or([ () => ns_flowMapImplicitEntry(indent, ctx), - () => new _Pair(e_node(), e_node()) + () => new Pair(e_node(), e_node()) ]); // 144 - _Pair ns_flowMapImplicitEntry(int indent, int ctx) => or([ + Pair ns_flowMapImplicitEntry(int indent, int ctx) => or([ () => ns_flowMapYamlKeyEntry(indent, ctx), () => c_ns_flowMapEmptyKeyEntry(indent, ctx), () => c_ns_flowMapJsonKeyEntry(indent, ctx) ]); // 145 - _Pair ns_flowMapYamlKeyEntry(int indent, int ctx) { + Pair ns_flowMapYamlKeyEntry(int indent, int ctx) { var key = ns_flowYamlNode(indent, ctx); if (!truth(key)) return null; var value = or([ @@ -1172,14 +1180,14 @@ class Parser { }), e_node ]); - return new _Pair(key, value); + return new Pair(key, value); } // 146 - _Pair c_ns_flowMapEmptyKeyEntry(int indent, int ctx) { + Pair c_ns_flowMapEmptyKeyEntry(int indent, int ctx) { var value = c_ns_flowMapSeparateValue(indent, ctx); if (!truth(value)) return null; - return new _Pair(e_node(), value); + return new Pair(e_node(), value); } // 147 @@ -1197,7 +1205,7 @@ class Parser { }); // 148 - _Pair c_ns_flowMapJsonKeyEntry(int indent, int ctx) { + Pair c_ns_flowMapJsonKeyEntry(int indent, int ctx) { var key = c_flowJsonNode(indent, ctx); if (!truth(key)) return null; var value = or([ @@ -1207,7 +1215,7 @@ class Parser { }), e_node ]); - return new _Pair(key, value); + return new Pair(key, value); } // 149 @@ -1224,6 +1232,7 @@ class Parser { // 150 Node ns_flowPair(int indent, int ctx) { + var start = _scanner.state; var pair = or([ () => transaction(() { if (!truth(c_indicator(C_MAPPING_KEY))) return null; @@ -1234,34 +1243,34 @@ class Parser { ]); if (!truth(pair)) return null; - return map([pair]); + return map([pair], _scanner.spanFrom(start)); } // 151 - _Pair ns_flowPairEntry(int indent, int ctx) => or([ + Pair ns_flowPairEntry(int indent, int ctx) => or([ () => ns_flowPairYamlKeyEntry(indent, ctx), () => c_ns_flowMapEmptyKeyEntry(indent, ctx), () => c_ns_flowPairJsonKeyEntry(indent, ctx) ]); // 152 - _Pair ns_flowPairYamlKeyEntry(int indent, int ctx) => + Pair ns_flowPairYamlKeyEntry(int indent, int ctx) => transaction(() { var key = ns_s_implicitYamlKey(FLOW_KEY); if (!truth(key)) return null; var value = c_ns_flowMapSeparateValue(indent, ctx); if (!truth(value)) return null; - return new _Pair(key, value); + return new Pair(key, value); }); // 153 - _Pair c_ns_flowPairJsonKeyEntry(int indent, int ctx) => + Pair c_ns_flowPairJsonKeyEntry(int indent, int ctx) => transaction(() { var key = c_s_implicitJsonKey(FLOW_KEY); if (!truth(key)) return null; var value = c_ns_flowMapAdjacentValue(indent, ctx); if (!truth(value)) return null; - return new _Pair(key, value); + return new Pair(key, value); }); // 154 @@ -1288,9 +1297,10 @@ class Parser { // 156 Node ns_flowYamlContent(int indent, int ctx) { + var start = _scanner.state; var str = ns_plain(indent, ctx); if (!truth(str)) return null; - return new ScalarNode("?", content: str); + return new ScalarNode("?", _scanner.spanFrom(start), content: str); } // 157 @@ -1437,6 +1447,7 @@ class Parser { // 170 Node c_l_literal(int indent) => transaction(() { + var start = _scanner.state; if (!truth(c_indicator(C_LITERAL))) return null; var header = c_b_blockHeader(); if (!truth(header)) return null; @@ -1445,7 +1456,7 @@ class Parser { var content = l_literalContent(indent + additionalIndent, header.chomping); if (!truth(content)) return null; - return new ScalarNode("!", content: content); + return new ScalarNode("!", _scanner.spanFrom(start), content: content); }); // 171 @@ -1474,6 +1485,7 @@ class Parser { // 174 Node c_l_folded(int indent) => transaction(() { + var start = _scanner.state; if (!truth(c_indicator(C_FOLDED))) return null; var header = c_b_blockHeader(); if (!truth(header)) return null; @@ -1482,7 +1494,7 @@ class Parser { var content = l_foldedContent(indent + additionalIndent, header.chomping); if (!truth(content)) return null; - return new ScalarNode("!", content: content); + return new ScalarNode("!", _scanner.spanFrom(start), content: content); }); // 175 @@ -1562,13 +1574,14 @@ class Parser { var additionalIndent = countIndentation() - indent; if (additionalIndent <= 0) return null; + var start = _scanner.state; var content = oneOrMore(() => transaction(() { if (!truth(s_indent(indent + additionalIndent))) return null; return c_l_blockSeqEntry(indent + additionalIndent); })); if (!truth(content)) return null; - return new SequenceNode("?", content); + return new SequenceNode("?", content, _scanner.spanFrom(start)); }); // 184 @@ -1595,6 +1608,7 @@ class Parser { // 186 Node ns_l_compactSequence(int indent) => context('sequence', () { + var start = _scanner.state; var first = c_l_blockSeqEntry(indent); if (!truth(first)) return null; @@ -1604,7 +1618,7 @@ class Parser { })); content.insert(0, first); - return new SequenceNode("?", content); + return new SequenceNode("?", content, _scanner.spanFrom(start)); }); // 187 @@ -1612,23 +1626,24 @@ class Parser { var additionalIndent = countIndentation() - indent; if (additionalIndent <= 0) return null; + var start = _scanner.state; var pairs = oneOrMore(() => transaction(() { if (!truth(s_indent(indent + additionalIndent))) return null; return ns_l_blockMapEntry(indent + additionalIndent); })); if (!truth(pairs)) return null; - return map(pairs); + return map(pairs, _scanner.spanFrom(start)); }); // 188 - _Pair ns_l_blockMapEntry(int indent) => or([ + Pair ns_l_blockMapEntry(int indent) => or([ () => c_l_blockMapExplicitEntry(indent), () => ns_l_blockMapImplicitEntry(indent) ]); // 189 - _Pair c_l_blockMapExplicitEntry(int indent) { + Pair c_l_blockMapExplicitEntry(int indent) { var key = c_l_blockMapExplicitKey(indent); if (!truth(key)) return null; @@ -1637,7 +1652,7 @@ class Parser { e_node ]); - return new _Pair(key, value); + return new Pair(key, value); } // 190 @@ -1654,10 +1669,10 @@ class Parser { }); // 192 - _Pair ns_l_blockMapImplicitEntry(int indent) => transaction(() { + Pair ns_l_blockMapImplicitEntry(int indent) => transaction(() { var key = or([ns_s_blockMapImplicitKey, e_node]); var value = c_l_blockMapImplicitValue(indent); - return truth(value) ? new _Pair(key, value) : null; + return truth(value) ? new Pair(key, value) : null; }); // 193 @@ -1678,6 +1693,7 @@ class Parser { // 195 Node ns_l_compactMapping(int indent) => context('mapping', () { + var start = _scanner.state; var first = ns_l_blockMapEntry(indent); if (!truth(first)) return null; @@ -1687,7 +1703,7 @@ class Parser { })); pairs.insert(0, first); - return map(pairs); + return map(pairs, _scanner.spanFrom(start)); }); // 196 @@ -1807,7 +1823,8 @@ class Parser { or([l_directiveDocument, l_explicitDocument, l_bareDocument]); // 211 - List l_yamlStream() { + Pair, Span> l_yamlStream() { + var start = _scanner.state; var docs = []; zeroOrMore(l_documentPrefix); var first = zeroOrOne(l_anyDocument); @@ -1828,20 +1845,10 @@ class Parser { }); if (!_scanner.isDone) parseFailed(); - return docs; + return new Pair(docs, _scanner.spanFrom(start)); } } -/// A pair of values. -class _Pair { - E first; - F last; - - _Pair(this.first, this.last); - - String toString() => '($first, $last)'; -} - /// The information in the header for a block scalar. class _BlockHeader { final int additionalIndent; @@ -1872,7 +1879,7 @@ class _Range { /// expensive. class _RangeMap { /// The ranges and their associated elements. - final List<_Pair<_Range, E>> _contents = <_Pair<_Range, E>>[]; + final List> _contents = >[]; _RangeMap(); @@ -1890,5 +1897,5 @@ class _RangeMap { /// Associates [value] with [range]. operator[]=(_Range range, E value) => - _contents.add(new _Pair<_Range, E>(range, value)); + _contents.add(new Pair<_Range, E>(range, value)); } diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 463af7013..84c1113a0 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -4,33 +4,12 @@ library yaml.utils; -import 'package:collection/collection.dart'; +/// A pair of values. +class Pair { + final E first; + final F last; -/// Returns a hash code for [obj] such that structurally equivalent objects -/// will have the same hash code. -/// -/// This supports deep equality for maps and lists, including those with -/// self-referential structures. -int hashCodeFor(obj) { - var parents = []; + Pair(this.first, this.last); - _hashCodeFor(value) { - if (parents.any((parent) => identical(parent, value))) return -1; - - parents.add(value); - try { - if (value is Map) { - var equality = const UnorderedIterableEquality(); - return equality.hash(value.keys.map(_hashCodeFor)) ^ - equality.hash(value.values.map(_hashCodeFor)); - } else if (value is Iterable) { - return const IterableEquality().hash(value.map(hashCodeFor)); - } - return value.hashCode; - } finally { - parents.removeLast(); - } - } - - return _hashCodeFor(obj); + String toString() => '($first, $last)'; } diff --git a/pkgs/yaml/lib/src/visitor.dart b/pkgs/yaml/lib/src/visitor.dart index 7095268d3..3f4c45538 100644 --- a/pkgs/yaml/lib/src/visitor.dart +++ b/pkgs/yaml/lib/src/visitor.dart @@ -4,8 +4,8 @@ library yaml.visitor; +import 'equality.dart'; import 'model.dart'; -import 'yaml_map.dart'; /// The visitor pattern for YAML documents. class Visitor { @@ -21,7 +21,7 @@ class Visitor { /// Visits each key and value in [map] and returns a map of the results. visitMapping(MappingNode map) { - var out = new YamlMap(); + var out = deepEqualsMap(); for (var key in map.content.keys) { out[key.visit(this)] = map.content[key].visit(this); } diff --git a/pkgs/yaml/lib/src/yaml_map.dart b/pkgs/yaml/lib/src/yaml_map.dart deleted file mode 100644 index ff3da3654..000000000 --- a/pkgs/yaml/lib/src/yaml_map.dart +++ /dev/null @@ -1,40 +0,0 @@ -// 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 yaml.map; - -import 'dart:collection'; - -import 'package:collection/collection.dart'; - -import 'deep_equals.dart'; -import 'utils.dart'; - -/// This class behaves almost identically to the normal Dart [Map] -/// implementation, with the following differences: -/// -/// * It allows NaN, list, and map keys. -/// * It defines `==` structurally. That is, `yamlMap1 == yamlMap2` if they -/// have the same contents. -/// * It has a compatible [hashCode] method. -/// -/// This class is deprecated. In future releases, this package will use -/// a [HashMap] with a custom equality operation rather than a custom class. -@Deprecated('1.0.0') -class YamlMap extends DelegatingMap { - YamlMap() - : super(new HashMap(equals: deepEquals, hashCode: hashCodeFor)); - - YamlMap.from(Map map) - : super(new HashMap(equals: deepEquals, hashCode: hashCodeFor)) { - addAll(map); - } - - int get hashCode => hashCodeFor(this); - - bool operator ==(other) { - if (other is! YamlMap) return false; - return deepEquals(this, other); - } -} diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart new file mode 100644 index 000000000..d0e057899 --- /dev/null +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -0,0 +1,92 @@ +// 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 yaml.map; + +import 'dart:collection' as collection; + +import 'package:collection/collection.dart'; +import 'package:source_maps/source_maps.dart'; + +/// An interface for parsed nodes from a YAML source tree. +/// +/// [YamlMap]s and [YamlList]s implement this interface in addition to the +/// normal [Map] and [List] interfaces, so any maps and lists will be +/// [YamlNode]s regardless of how they're accessed. +/// +/// Scalars values like strings and numbers, on the other hand, don't have this +/// interface by default. Instead, they can be accessed as [YamlScalar]s via +/// [YamlMap.nodes] or [YamlList.nodes]. +abstract class YamlNode { + /// The source span for this node. + /// + /// [Span.getLocationMessage] can be used to produce a human-friendly message + /// about this node. + Span get span; + + /// The inner value of this node. + /// + /// For [YamlScalar]s, this will return the wrapped value. For [YamlMap] and + /// [YamlList], it will return [this], since they already implement [Map] and + /// [List], respectively. + get value; +} + +/// A read-only [Map] parsed from YAML. +class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { + final Span span; + + final Map nodes; + + Map get value => this; + + Iterable get keys => nodes.keys.map((node) => node.value); + + /// Users of the library should not construct [YamlMap]s manually. + YamlMap(Map nodes, this.span) + : nodes = new UnmodifiableMapView(nodes); + + operator [](key) { + var node = nodes[key]; + return node == null ? null : node.value; + } +} + +// TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed. +/// A read-only [List] parsed from YAML. +class YamlList extends YamlNode with collection.ListMixin { + final Span span; + + final List nodes; + + List get value => this; + + int get length => nodes.length; + + set length(int index) { + throw new UnsupportedError("Cannot modify an unmodifiable List"); + } + + /// Users of the library should not construct [YamlList]s manually. + YamlList(List nodes, this.span) + : nodes = new UnmodifiableListView(nodes); + + operator [](int index) => nodes[index].value; + + operator []=(int index, value) { + throw new UnsupportedError("Cannot modify an unmodifiable List"); + } +} + +/// A wrapped scalar value parsed from YAML. +class YamlScalar extends YamlNode { + final Span span; + + final value; + + /// Users of the library should not construct [YamlScalar]s manually. + YamlScalar(this.value, this.span); + + String toString() => value.toString(); +} diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 209db8c3b..f59719d63 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -8,9 +8,10 @@ import 'src/composer.dart'; import 'src/constructor.dart'; import 'src/parser.dart'; import 'src/yaml_exception.dart'; +import 'src/yaml_node.dart'; export 'src/yaml_exception.dart'; -export 'src/yaml_map.dart'; +export 'src/yaml_node.dart'; /// Loads a single document from a YAML string. /// @@ -28,12 +29,20 @@ export 'src/yaml_map.dart'; /// /// If [sourceName] is passed, it's used as the name of the file or URL from /// which the YAML originated for error reporting. -loadYaml(String yaml, {String sourceName}) { +loadYaml(String yaml, {String sourceName}) => + loadYamlNode(yaml, sourceName: sourceName).value; + +/// Loads a single document from a YAML string as a [YamlNode]. +/// +/// This is just like [loadYaml], except that where [loadYaml] would return a +/// normal Dart value this returns a [YamlNode] instead. This allows the caller +/// to be confident that the return value will always be a [YamlNode]. +YamlNode loadYamlNode(String yaml, {String sourceName}) { var stream = loadYamlStream(yaml, sourceName: sourceName); if (stream.length != 1) { throw new YamlException("Expected 1 document, were ${stream.length}."); } - return stream[0]; + return stream.nodes[0]; } /// Loads a stream of documents from a YAML string. @@ -49,15 +58,16 @@ loadYaml(String yaml, {String sourceName}) { /// /// If [sourceName] is passed, it's used as the name of the file or URL from /// which the YAML originated for error reporting. -List loadYamlStream(String yaml, {String sourceName}) { - var stream; +YamlList loadYamlStream(String yaml, {String sourceName}) { + var pair; try { - stream = new Parser(yaml, sourceName).l_yamlStream(); + pair = new Parser(yaml, sourceName).l_yamlStream(); } on FormatException catch (error) { throw new YamlException(error.toString()); } - return stream + var nodes = pair.first .map((doc) => new Constructor(new Composer(doc).compose()).construct()) .toList(); + return new YamlList(nodes, pair.last); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index b57224c87..267216150 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 0.10.0 +version: 1.0.0 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index 0bac9f939..9c96ec103 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -5,7 +5,7 @@ library yaml.test.utils; import 'package:unittest/unittest.dart'; -import 'package:yaml/src/deep_equals.dart' as de; +import 'package:yaml/src/equality.dart' as equality; import 'package:yaml/yaml.dart'; /// A matcher that validates that a closure or Future throws a [YamlException]. @@ -14,25 +14,28 @@ final Matcher throwsYamlException = throwsA(new isInstanceOf()); /// Returns a matcher that asserts that the value equals [expected]. /// /// This handles recursive loops and considers `NaN` to equal itself. -Matcher deepEquals(expected) => - predicate((actual) => de.deepEquals(actual, expected), "equals $expected"); +Matcher deepEquals(expected) => predicate((actual) => + equality.deepEquals(actual, expected), "equals $expected"); /// Constructs a new yaml.YamlMap, optionally from a normal Map. -Map yamlMap([Map from]) => - from == null ? new YamlMap() : new YamlMap.from(from); +Map deepEqualsMap([Map from]) { + var map = equality.deepEqualsMap(); + if (from != null) map.addAll(from); + return map; +} /// Asserts that a string containing a single YAML document produces a given /// value when loaded. void expectYamlLoads(expected, String source) { var actual = loadYaml(cleanUpLiteral(source)); - expect(expected, deepEquals(actual)); + expect(actual, deepEquals(expected)); } /// Asserts that a string containing a stream of YAML documents produces a given /// list of values when loaded. void expectYamlStreamLoads(List expected, String source) { var actual = loadYamlStream(cleanUpLiteral(source)); - expect(expected, deepEquals(actual)); + expect(actual, deepEquals(expected)); } /// Asserts that a string containing a single YAML document throws a diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index fcfc12ef5..4fbb10878 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -14,37 +14,6 @@ main() { var infinity = double.parse("Infinity"); var nan = double.parse("NaN"); - group('YamlMap', () { - group('accepts as a key', () { - _expectKeyWorks(keyFn()) { - var map = yamlMap(); - map[keyFn()] = 5; - expect(map.containsKey(keyFn()), isTrue); - expect(map[keyFn()], 5); - } - - test('null', () => _expectKeyWorks(() => null)); - test('true', () => _expectKeyWorks(() => true)); - test('false', () => _expectKeyWorks(() => false)); - test('a list', () => _expectKeyWorks(() => [1, 2, 3])); - test('a map', () => _expectKeyWorks(() => {'foo': 'bar'})); - test('a YAML map', () => _expectKeyWorks(() => yamlMap({'foo': 'bar'}))); - }); - - test('works as a hash key', () { - var normalMap = new Map(); - normalMap[yamlMap({'foo': 'bar'})] = 'baz'; - expect(normalMap.containsKey(yamlMap({'foo': 'bar'})), isTrue); - expect(normalMap[yamlMap({'foo': 'bar'})], 'baz'); - }); - - test('treats YamlMap keys the same as normal maps', () { - var map = yamlMap(); - map[{'a': 'b'}] = 5; - expect(map[yamlMap({'a': 'b'})], 5); - }); - }); - group('has a friendly error message for', () { var tabError = predicate((e) => e.toString().contains('tab characters are not allowed as indentation')); @@ -221,7 +190,7 @@ main() { // }); test('[Example 2.11]', () { - var doc = yamlMap(); + var doc = deepEqualsMap(); doc[["Detroit Tigers", "Chicago cubs"]] = ["2001-07-23"]; doc[["New York Yankees", "Atlanta Braves"]] = ["2001-07-02", "2001-08-12", "2001-08-14"]; @@ -382,7 +351,7 @@ main() { }); test('[Example 2.21]', () { - var doc = yamlMap({ + var doc = deepEqualsMap({ "booleans": [true, false], "string": "012345" }); @@ -900,7 +869,7 @@ main() { }); test('[Example 6.12]', () { - var doc = yamlMap(); + var doc = deepEqualsMap(); doc[{'first': 'Sammy', 'last': 'Sosa'}] = { 'hr': 65, 'avg': 0.278 @@ -1092,7 +1061,7 @@ main() { // }); test('[Example 7.3]', () { - var doc = yamlMap({"foo": null}); + var doc = deepEqualsMap({"foo": null}); doc[null] = "bar"; expectYamlLoads(doc, """ @@ -1239,7 +1208,7 @@ main() { }); test('[Example 7.16]', () { - var doc = yamlMap({ + var doc = deepEqualsMap({ "explicit": "entry", "implicit": "entry" }); @@ -1254,7 +1223,7 @@ main() { }); test('[Example 7.17]', () { - var doc = yamlMap({ + var doc = deepEqualsMap({ "unquoted": "separate", "http://foo.com": null, "omitted value": null @@ -1302,10 +1271,10 @@ main() { }); test('[Example 7.21]', () { - var el1 = yamlMap(); + var el1 = deepEqualsMap(); el1[null] = "empty key entry"; - var el2 = yamlMap(); + var el2 = deepEqualsMap(); el2[{"JSON": "like"}] = "adjacent"; expectYamlLoads([[{"YAML": "separate"}], [el1], [el2]], @@ -1577,7 +1546,7 @@ main() { }); test('[Example 8.18]', () { - var doc = yamlMap({ + var doc = deepEqualsMap({ 'plain key': 'in-line value', "quoted key": ["entry"] }); @@ -1591,7 +1560,7 @@ main() { }); test('[Example 8.19]', () { - var el = yamlMap(); + var el = deepEqualsMap(); el[{'earth': 'blue'}] = {'moon': 'white'}; expectYamlLoads([{'sun': 'yellow'}, el], """ @@ -1763,7 +1732,7 @@ main() { group('10.2: JSON Schema', () { // test('[Example 10.4]', () { - // var doc = yamlMap({"key with null value": null}); + // var doc = deepEqualsMap({"key with null value": null}); // doc[null] = "value for null key"; // expectYamlStreamLoads(doc, // """ From 46688d09edc25ddb39916f8867677e4337ae48a7 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 3 Jun 2014 21:10:52 +0000 Subject: [PATCH 036/179] Fix a variable name typo in yaml. R=rnystrom@google.com Review URL: https://codereview.chromium.org//318513002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@36945 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/lib/src/composer.dart | 2 -- pkgs/yaml/lib/src/constructor.dart | 2 +- pkgs/yaml/lib/src/parser.dart | 1 - pkgs/yaml/pubspec.yaml | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 4b243d813..261a66682 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0+1 + +* Fix a variable name typo. + ## 1.0.0 * **Backwards incompatibility**: The data structures returned by `loadYaml` and diff --git a/pkgs/yaml/lib/src/composer.dart b/pkgs/yaml/lib/src/composer.dart index 4c19da14a..1a23bc6fc 100644 --- a/pkgs/yaml/lib/src/composer.dart +++ b/pkgs/yaml/lib/src/composer.dart @@ -4,8 +4,6 @@ library yaml.composer; -import 'package:source_maps/source_maps.dart'; - import 'model.dart'; import 'visitor.dart'; import 'yaml_exception.dart'; diff --git a/pkgs/yaml/lib/src/constructor.dart b/pkgs/yaml/lib/src/constructor.dart index a8224a493..5cf23c7c5 100644 --- a/pkgs/yaml/lib/src/constructor.dart +++ b/pkgs/yaml/lib/src/constructor.dart @@ -53,7 +53,7 @@ class Constructor extends Visitor { YamlNode getAnchor(Node anchored) { if (anchored.anchor == null) return null; var value = _anchors[anchored.anchor]; - if (vaule == null) return null; + if (value == null) return null; // Re-wrap [value]'s contents so that it's associated with the span of the // anchor rather than its original definition. diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 98658e6a3..b42638f52 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -12,7 +12,6 @@ import 'package:string_scanner/string_scanner.dart'; import 'equality.dart'; import 'model.dart'; import 'utils.dart'; -import 'yaml_exception.dart'; /// Translates a string of characters into a YAML serialization tree. /// diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 267216150..50fc3db4b 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 1.0.0 +version: 1.0.0+1 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. From 8ff802915c86ba7bce22e920ed0998e774f1a00b Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 5 Jun 2014 00:47:28 +0000 Subject: [PATCH 037/179] Fix yaml's SDK constraint to contain only SDKs with MapMixin. R=rnystrom@google.com BUG=19200 Review URL: https://codereview.chromium.org//312163003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@37024 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 50fc3db4b..b783228b0 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 1.0.0+1 +version: 1.0.0+2 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. @@ -9,4 +9,4 @@ dependencies: dev_dependencies: unittest: ">=0.9.0 <0.12.0" environment: - sdk: ">=0.8.10+6 <2.0.0" + sdk: ">=1.5.0-dev.0.0 <2.0.0" From c1351874a01318509c83bec7cb9fc5fb313fec9a Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 23 Jun 2014 21:07:00 +0000 Subject: [PATCH 038/179] Make YamlException inherit from SpanFormatException. R=rnystrom@google.com Review URL: https://codereview.chromium.org//342943006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@37618 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 8 ++++++++ pkgs/yaml/lib/src/composer.dart | 15 +++++++++------ pkgs/yaml/lib/src/model.dart | 2 +- pkgs/yaml/lib/src/yaml_exception.dart | 11 +++++------ pkgs/yaml/lib/yaml.dart | 9 ++++++--- pkgs/yaml/pubspec.yaml | 3 ++- 6 files changed, 31 insertions(+), 17 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 261a66682..fdd924001 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.1.0 + +* Make `YamlException` inherit from source_map's [`SpanFormatException`][]. This + improves the error formatting and allows callers access to source range + information. + +[SpanFormatException]: (http://www.dartdocs.org/documentation/source_maps/0.9.2/index.html#source_maps/source_maps.SpanFormatException) + ## 1.0.0+1 * Fix a variable name typo. diff --git a/pkgs/yaml/lib/src/composer.dart b/pkgs/yaml/lib/src/composer.dart index 1a23bc6fc..8612067e7 100644 --- a/pkgs/yaml/lib/src/composer.dart +++ b/pkgs/yaml/lib/src/composer.dart @@ -34,7 +34,8 @@ class Composer extends Visitor { /// Returns the anchor to which an alias node refers. Node visitAlias(AliasNode alias) { if (!_anchors.containsKey(alias.anchor)) { - throw new YamlException("No anchor for alias ${alias.anchor}."); + throw new YamlException("No anchor for alias ${alias.anchor}.", + alias.span); } return _anchors[alias.anchor]; } @@ -56,8 +57,8 @@ class Composer extends Visitor { var result = _parseByTag(scalar); if (result != null) return setAnchor(scalar, result); - throw new YamlException('Invalid literal for ${scalar.tag}: ' - '"${scalar.content}".'); + throw new YamlException('Invalid literal for ${scalar.tag}.', + scalar.span); } ScalarNode _parseByTag(ScalarNode scalar) { @@ -68,14 +69,15 @@ class Composer extends Visitor { case "float": return parseFloat(scalar); case "str": return parseString(scalar); } - throw new YamlException('Undefined tag: ${scalar.tag}.'); + throw new YamlException('Undefined tag: ${scalar.tag}.', scalar.span); } /// Assigns a tag to the sequence and recursively composes its contents. Node visitSequence(SequenceNode seq) { var tagName = seq.tag.name; if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("seq")) { - throw new YamlException("Invalid tag for sequence: ${seq.tag}."); + throw new YamlException("Invalid tag for sequence: ${seq.tag}.", + seq.span); } var result = setAnchor(seq, @@ -88,7 +90,8 @@ class Composer extends Visitor { Node visitMapping(MappingNode map) { var tagName = map.tag.name; if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("map")) { - throw new YamlException("Invalid tag for mapping: ${map.tag}."); + throw new YamlException("Invalid tag for mapping: ${map.tag}.", + map.span); } var result = setAnchor(map, diff --git a/pkgs/yaml/lib/src/model.dart b/pkgs/yaml/lib/src/model.dart index f0e839c06..097376957 100644 --- a/pkgs/yaml/lib/src/model.dart +++ b/pkgs/yaml/lib/src/model.dart @@ -208,7 +208,7 @@ class ScalarNode extends Node { return '"${escapedValue.join()}"'; } - throw new YamlException('Unknown scalar value: "$value".'); + throw new YamlException('Unknown scalar value.', span); } String toString() => '$tag "$content"'; diff --git a/pkgs/yaml/lib/src/yaml_exception.dart b/pkgs/yaml/lib/src/yaml_exception.dart index a86327413..9d4371768 100644 --- a/pkgs/yaml/lib/src/yaml_exception.dart +++ b/pkgs/yaml/lib/src/yaml_exception.dart @@ -4,12 +4,11 @@ library yaml.exception; -/// An error thrown by the YAML processor. -class YamlException implements Exception { - final String _msg; - - YamlException(this._msg); +import 'package:source_maps/source_maps.dart'; - String toString() => _msg; +/// An error thrown by the YAML processor. +class YamlException extends SpanFormatException { + YamlException(String message, Span span) + : super(message, span); } diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index f59719d63..80a63190c 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -4,6 +4,8 @@ library yaml; +import 'package:string_scanner/string_scanner.dart'; + import 'src/composer.dart'; import 'src/constructor.dart'; import 'src/parser.dart'; @@ -40,7 +42,8 @@ loadYaml(String yaml, {String sourceName}) => YamlNode loadYamlNode(String yaml, {String sourceName}) { var stream = loadYamlStream(yaml, sourceName: sourceName); if (stream.length != 1) { - throw new YamlException("Expected 1 document, were ${stream.length}."); + throw new YamlException("Expected 1 document, were ${stream.length}.", + stream.span); } return stream.nodes[0]; } @@ -62,8 +65,8 @@ YamlList loadYamlStream(String yaml, {String sourceName}) { var pair; try { pair = new Parser(yaml, sourceName).l_yamlStream(); - } on FormatException catch (error) { - throw new YamlException(error.toString()); + } on StringScannerException catch (error) { + throw new YamlException(error.message, error.span); } var nodes = pair.first diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index b783228b0..d8eefd4a7 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,11 +1,12 @@ name: yaml -version: 1.0.0+2 +version: 1.1.0-dev author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dependencies: collection: ">=0.9.2 <0.10.0" string_scanner: ">=0.0.2 <0.1.0" + source_maps: ">=0.9.2 <0.10.0" dev_dependencies: unittest: ">=0.9.0 <0.12.0" environment: From 8f3e034f866c4335e1fa253ffdd7f14c7caf7dc0 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 24 Jun 2014 18:38:29 +0000 Subject: [PATCH 039/179] Add new constructors to YamlNode subclasses. These constructors make it easy to use the same code for extracting data from both YAML and non-YAML objects. R=rnystrom@google.com Review URL: https://codereview.chromium.org//343063002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@37665 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 4 + pkgs/yaml/lib/src/constructor.dart | 18 ++- pkgs/yaml/lib/src/null_span.dart | 47 ++++++ pkgs/yaml/lib/src/yaml_node.dart | 69 ++++++++- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 149 +++++++++++++++++++ pkgs/yaml/lib/yaml.dart | 2 +- pkgs/yaml/pubspec.yaml | 3 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 163 +++++++++++++++++++++ 8 files changed, 439 insertions(+), 16 deletions(-) create mode 100644 pkgs/yaml/lib/src/null_span.dart create mode 100644 pkgs/yaml/lib/src/yaml_node_wrapper.dart create mode 100644 pkgs/yaml/test/yaml_node_wrapper_test.dart diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index fdd924001..186cfabdc 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,5 +1,9 @@ ## 1.1.0 +* Add new publicly-accessible constructors for `YamlNode` subclasses. These + constructors make it possible to use the same API to access non-YAML data as + YAML data. + * Make `YamlException` inherit from source_map's [`SpanFormatException`][]. This improves the error formatting and allows callers access to source range information. diff --git a/pkgs/yaml/lib/src/constructor.dart b/pkgs/yaml/lib/src/constructor.dart index 5cf23c7c5..5931dae01 100644 --- a/pkgs/yaml/lib/src/constructor.dart +++ b/pkgs/yaml/lib/src/constructor.dart @@ -26,14 +26,14 @@ class Constructor extends Visitor { /// Returns the value of a scalar. YamlScalar visitScalar(ScalarNode scalar) => - new YamlScalar(scalar.value, scalar.span); + new YamlScalar.internal(scalar.value, scalar.span); /// Converts a sequence into a List of Dart objects. YamlList visitSequence(SequenceNode seq) { var anchor = getAnchor(seq); if (anchor != null) return anchor; var nodes = []; - var dartSeq = setAnchor(seq, new YamlList(nodes, seq.span)); + var dartSeq = setAnchor(seq, new YamlList.internal(nodes, seq.span)); nodes.addAll(super.visitSequence(seq)); return dartSeq; } @@ -43,7 +43,7 @@ class Constructor extends Visitor { var anchor = getAnchor(map); if (anchor != null) return anchor; var nodes = deepEqualsMap(); - var dartMap = setAnchor(map, new YamlMap(nodes, map.span)); + var dartMap = setAnchor(map, new YamlMap.internal(nodes, map.span)); super.visitMapping(map).forEach((k, v) => nodes[k] = v); return dartMap; } @@ -57,10 +57,14 @@ class Constructor extends Visitor { // Re-wrap [value]'s contents so that it's associated with the span of the // anchor rather than its original definition. - if (value is YamlMap) return new YamlMap(value.nodes, anchored.span); - if (value is YamlList) return new YamlList(value.nodes, anchored.span); - assert(value is YamlScalar); - return new YamlScalar(value.value, anchored.span); + if (value is YamlMap) { + return new YamlMap.internal(value.nodes, anchored.span); + } else if (value is YamlList) { + return new YamlList.internal(value.nodes, anchored.span); + } else { + assert(value is YamlScalar); + return new YamlScalar.internal(value.value, anchored.span); + } } /// Records that [value] is the Dart object representing [anchored]. diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart new file mode 100644 index 000000000..b3e325499 --- /dev/null +++ b/pkgs/yaml/lib/src/null_span.dart @@ -0,0 +1,47 @@ +// Copyright (c) 2014, 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 yaml.null_span; + +import 'package:path/path.dart' as p; +import 'package:source_maps/source_maps.dart'; + +/// A [Span] with no location information. +/// +/// This is used with [YamlMap.wrap] and [YamlList.wrap] to provide means of +/// accessing a non-YAML map that behaves transparently like a map parsed from +/// YAML. +class NullSpan extends Span { + Location get end => start; + final text = ""; + + NullSpan(String sourceUrl) + : this._(new NullLocation(sourceUrl)); + + NullSpan._(Location location) + : super(location, location, false); + + String formatLocationMessage(String message, {bool useColors: false, + String color}) { + var locationMessage = sourceUrl == null ? "in an unknown location" : + "in ${p.prettyUri(sourceUrl)}"; + return "$locationMessage: $message"; + } +} + +/// A [Location] with no location information. +/// +/// This is used with [YamlMap.wrap] and [YamlList.wrap] to provide means of +/// accessing a non-YAML map that behaves transparently like a map parsed from +/// YAML. +class NullLocation extends Location { + final String sourceUrl; + final line = 0; + final column = 0; + + String get formatString => sourceUrl == null ? "unknown location" : sourceUrl; + + NullLocation(this.sourceUrl) + : super(0); +} diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index d0e057899..1aded2be7 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -2,13 +2,16 @@ // 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 yaml.map; +library yaml.yaml_node; import 'dart:collection' as collection; import 'package:collection/collection.dart'; import 'package:source_maps/source_maps.dart'; +import 'null_span.dart'; +import 'yaml_node_wrapper.dart'; + /// An interface for parsed nodes from a YAML source tree. /// /// [YamlMap]s and [YamlList]s implement this interface in addition to the @@ -37,14 +40,40 @@ abstract class YamlNode { class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { final Span span; + /// A view of [this] where the keys and values are guaranteed to be + /// [YamlNode]s. + /// + /// The key type is `dynamic` to allow values to be accessed using + /// non-[YamlNode] keys, but [Map.keys] and [Map.forEach] will always expose + /// them as [YamlNode]s. For example, for `{"foo": [1, 2, 3]}` [nodes] will be + /// a map from a [YamlScalar] to a [YamlList], but since the key type is + /// `dynamic` `map.nodes["foo"]` will still work. final Map nodes; Map get value => this; Iterable get keys => nodes.keys.map((node) => node.value); - /// Users of the library should not construct [YamlMap]s manually. - YamlMap(Map nodes, this.span) + /// Creates an empty YamlMap. + /// + /// This map's [span] won't have useful location information. However, it will + /// have a reasonable implementation of [Span.getLocationMessage]. If + /// [sourceName] is passed, it's used as the [Span.sourceUrl]. + factory YamlMap({String sourceName}) => + new YamlMapWrapper(const {}, sourceName); + + /// Wraps a Dart map so that it can be accessed (recursively) like a + /// [YamlMap]. + /// + /// Any [Span]s returned by this map or its children will be dummies without + /// useful location information. However, they will have a reasonable + /// implementation of [Span.getLocationMessage]. If [sourceName] is passed, + /// it's used as the [Span.sourceUrl]. + factory YamlMap.wrap(Map dartMap, {String sourceName}) => + new YamlMapWrapper(dartMap, sourceName); + + /// Users of the library should not use this constructor. + YamlMap.internal(Map nodes, this.span) : nodes = new UnmodifiableMapView(nodes); operator [](key) { @@ -68,8 +97,26 @@ class YamlList extends YamlNode with collection.ListMixin { throw new UnsupportedError("Cannot modify an unmodifiable List"); } - /// Users of the library should not construct [YamlList]s manually. - YamlList(List nodes, this.span) + /// Creates an empty YamlList. + /// + /// This list's [span] won't have useful location information. However, it + /// will have a reasonable implementation of [Span.getLocationMessage]. If + /// [sourceName] is passed, it's used as the [Span.sourceUrl]. + factory YamlList({String sourceName}) => + new YamlListWrapper(const [], sourceName); + + /// Wraps a Dart list so that it can be accessed (recursively) like a + /// [YamlList]. + /// + /// Any [Span]s returned by this list or its children will be dummies without + /// useful location information. However, they will have a reasonable + /// implementation of [Span.getLocationMessage]. If [sourceName] is passed, + /// it's used as the [Span.sourceUrl]. + factory YamlList.wrap(List dartList, {String sourceName}) => + new YamlListWrapper(dartList, sourceName); + + /// Users of the library should not use this constructor. + YamlList.internal(List nodes, this.span) : nodes = new UnmodifiableListView(nodes); operator [](int index) => nodes[index].value; @@ -85,8 +132,16 @@ class YamlScalar extends YamlNode { final value; - /// Users of the library should not construct [YamlScalar]s manually. - YamlScalar(this.value, this.span); + /// Wraps a Dart value in a [YamlScalar]. + /// + /// This scalar's [span] won't have useful location information. However, it + /// will have a reasonable implementation of [Span.getLocationMessage]. If + /// [sourceName] is passed, it's used as the [Span.sourceUrl]. + YamlScalar.wrap(this.value, {String sourceName}) + : span = new NullSpan(sourceName); + + /// Users of the library should not use this constructor. + YamlScalar.internal(this.value, this.span); String toString() => value.toString(); } diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart new file mode 100644 index 000000000..8ea084e33 --- /dev/null +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -0,0 +1,149 @@ +// Copyright (c) 2014, 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 yaml.yaml_node_wrapper; + +import 'dart:collection'; + +import 'package:collection/collection.dart' as pkg_collection; +import 'package:source_maps/source_maps.dart'; + +import 'null_span.dart'; +import 'yaml_node.dart'; + +/// A wrapper that makes a normal Dart map behave like a [YamlMap]. +class YamlMapWrapper extends MapBase + with pkg_collection.UnmodifiableMapMixin + implements YamlMap { + final Map _dartMap; + + final Span span; + + final Map nodes; + + Map get value => this; + + Iterable get keys => _dartMap.keys; + + YamlMapWrapper(Map dartMap, String sourceName) + : this._(dartMap, new NullSpan(sourceName)); + + YamlMapWrapper._(Map dartMap, Span span) + : _dartMap = dartMap, + span = span, + nodes = new _YamlMapNodes(dartMap, span); + + operator [](Object key) { + var value = _dartMap[key]; + if (value is Map) return new YamlMapWrapper._(value, span); + if (value is List) return new YamlListWrapper._(value, span); + return value; + } + + int get hashCode => _dartMap.hashCode; + + operator ==(Object other) => + other is YamlMapWrapper && other._dartMap == _dartMap; +} + +/// The implementation of [YamlMapWrapper.nodes] as a wrapper around the Dart +/// map. +class _YamlMapNodes extends MapBase + with pkg_collection.UnmodifiableMapMixin { + final Map _dartMap; + + final Span _span; + + Iterable get keys => + _dartMap.keys.map((key) => new YamlScalar.internal(key, _span)); + + _YamlMapNodes(this._dartMap, this._span); + + YamlNode operator [](Object key) { + if (key is YamlScalar) key = key.value; + if (!_dartMap.containsKey(key)) return null; + return _nodeForValue(_dartMap[key], _span); + } + + int get hashCode => _dartMap.hashCode; + + operator ==(Object other) => + other is _YamlMapNodes && other._dartMap == _dartMap; +} + +// TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed. +/// A wrapper that makes a normal Dart list behave like a [YamlList]. +class YamlListWrapper extends ListBase implements YamlList { + final List _dartList; + + final Span span; + + final List nodes; + + List get value => this; + + int get length => _dartList.length; + + set length(int index) { + throw new UnsupportedError("Cannot modify an unmodifiable List."); + } + + YamlListWrapper(List dartList, String sourceName) + : this._(dartList, new NullSpan(sourceName)); + + YamlListWrapper._(List dartList, Span span) + : _dartList = dartList, + span = span, + nodes = new _YamlListNodes(dartList, span); + + operator [](int index) { + var value = _dartList[index]; + if (value is Map) return new YamlMapWrapper._(value, span); + if (value is List) return new YamlListWrapper._(value, span); + return value; + } + + operator []=(int index, value) { + throw new UnsupportedError("Cannot modify an unmodifiable List."); + } + + int get hashCode => _dartList.hashCode; + + operator ==(Object other) => + other is YamlListWrapper && other._dartList == _dartList; +} + +// TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed. +/// The implementation of [YamlListWrapper.nodes] as a wrapper around the Dart +/// list. +class _YamlListNodes extends ListBase { + final List _dartList; + + final Span _span; + + int get length => _dartList.length; + + set length(int index) { + throw new UnsupportedError("Cannot modify an unmodifiable List."); + } + + _YamlListNodes(this._dartList, this._span); + + YamlNode operator [](int index) => _nodeForValue(_dartList[index], _span); + + operator []=(int index, value) { + throw new UnsupportedError("Cannot modify an unmodifiable List."); + } + + int get hashCode => _dartList.hashCode; + + operator ==(Object other) => + other is _YamlListNodes && other._dartList == _dartList; +} + +YamlNode _nodeForValue(value, Span span) { + if (value is Map) return new YamlMapWrapper._(value, span); + if (value is List) return new YamlListWrapper._(value, span); + return new YamlScalar.internal(value, span); +} diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 80a63190c..0afc2cc8e 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -72,5 +72,5 @@ YamlList loadYamlStream(String yaml, {String sourceName}) { var nodes = pair.first .map((doc) => new Constructor(new Composer(doc).compose()).construct()) .toList(); - return new YamlList(nodes, pair.last); + return new YamlList.internal(nodes, pair.last); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index d8eefd4a7..558969579 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,10 +1,11 @@ name: yaml -version: 1.1.0-dev +version: 1.1.0 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dependencies: collection: ">=0.9.2 <0.10.0" + path: ">=1.2.0 <2.0.0" string_scanner: ">=0.0.2 <0.1.0" source_maps: ">=0.9.2 <0.10.0" dev_dependencies: diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart new file mode 100644 index 000000000..8bf4761ba --- /dev/null +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -0,0 +1,163 @@ +// 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 yaml.node_wrapper_test; + +import 'package:source_maps/source_maps.dart'; +import 'package:unittest/unittest.dart'; +import 'package:yaml/yaml.dart'; + +main() { + test("YamlMap() with no sourceName", () { + var map = new YamlMap(); + expect(map, isEmpty); + expect(map.nodes, isEmpty); + expect(map.span, isNullSpan(isNull)); + }); + + test("YamlMap() with a sourceName", () { + var map = new YamlMap(sourceName: "source"); + expect(map.span, isNullSpan("source")); + }); + + test("YamlList() with no sourceName", () { + var list = new YamlList(); + expect(list, isEmpty); + expect(list.nodes, isEmpty); + expect(list.span, isNullSpan(isNull)); + }); + + test("YamlList() with a sourceName", () { + var list = new YamlList(sourceName: "source"); + expect(list.span, isNullSpan("source")); + }); + + test("YamlMap.wrap() with no sourceName", () { + var map = new YamlMap.wrap({ + "list": [1, 2, 3], + "map": { + "foo": "bar", + "nested": [4, 5, 6] + }, + "scalar": "value" + }); + + expect(map, equals({ + "list": [1, 2, 3], + "map": { + "foo": "bar", + "nested": [4, 5, 6] + }, + "scalar": "value" + })); + + expect(map.span, isNullSpan(isNull)); + expect(map["list"], new isInstanceOf()); + expect(map["list"].nodes[0], new isInstanceOf()); + expect(map["list"].span, isNullSpan(isNull)); + expect(map["map"], new isInstanceOf()); + expect(map["map"].nodes["foo"], new isInstanceOf()); + expect(map["map"]["nested"], new isInstanceOf()); + expect(map["map"].span, isNullSpan(isNull)); + expect(map.nodes["scalar"], new isInstanceOf()); + expect(map.nodes["scalar"].value, "value"); + expect(map.nodes["scalar"].span, isNullSpan(isNull)); + expect(map["scalar"], "value"); + expect(map.keys, unorderedEquals(["list", "map", "scalar"])); + expect(map.nodes.keys, everyElement(new isInstanceOf())); + expect(map.nodes[new YamlScalar.wrap("list")], equals([1, 2, 3])); + }); + + test("YamlMap.wrap() with a sourceName", () { + var map = new YamlMap.wrap({ + "list": [1, 2, 3], + "map": { + "foo": "bar", + "nested": [4, 5, 6] + }, + "scalar": "value" + }, sourceName: "source"); + + expect(map.span, isNullSpan("source")); + expect(map["list"].span, isNullSpan("source")); + expect(map["map"].span, isNullSpan("source")); + expect(map.nodes["scalar"].span, isNullSpan("source")); + }); + + test("YamlList.wrap() with no sourceName", () { + var list = new YamlList.wrap([ + [1, 2, 3], + { + "foo": "bar", + "nested": [4, 5, 6] + }, + "value" + ]); + + expect(list, equals([ + [1, 2, 3], + { + "foo": "bar", + "nested": [4, 5, 6] + }, + "value" + ])); + + expect(list.span, isNullSpan(isNull)); + expect(list[0], new isInstanceOf()); + expect(list[0].nodes[0], new isInstanceOf()); + expect(list[0].span, isNullSpan(isNull)); + expect(list[1], new isInstanceOf()); + expect(list[1].nodes["foo"], new isInstanceOf()); + expect(list[1]["nested"], new isInstanceOf()); + expect(list[1].span, isNullSpan(isNull)); + expect(list.nodes[2], new isInstanceOf()); + expect(list.nodes[2].value, "value"); + expect(list.nodes[2].span, isNullSpan(isNull)); + expect(list[2], "value"); + }); + + test("YamlList.wrap() with a sourceName", () { + var list = new YamlList.wrap([ + [1, 2, 3], + { + "foo": "bar", + "nested": [4, 5, 6] + }, + "value" + ]); + + expect(list.span, isNullSpan(isNull)); + expect(list[0].span, isNullSpan(isNull)); + expect(list[1].span, isNullSpan(isNull)); + expect(list.nodes[2].span, isNullSpan(isNull)); + }); + + solo_test("re-wrapped objects equal one another", () { + var list = new YamlList.wrap([ + [1, 2, 3], + {"foo": "bar"} + ]); + + expect(list[0] == list[0], isTrue); + expect(list[0].nodes == list[0].nodes, isTrue); + expect(list[0] == new YamlList.wrap([1, 2, 3]), isFalse); + expect(list[1] == list[1], isTrue); + expect(list[1].nodes == list[1].nodes, isTrue); + expect(list[1] == new YamlMap.wrap({"foo": "bar"}), isFalse); + }); +} + +Matcher isNullSpan(sourceUrl) => predicate((span) { + expect(span, new isInstanceOf()); + expect(span.length, equals(0)); + expect(span.text, isEmpty); + expect(span.isIdentifier, isFalse); + expect(span.start, equals(span.end)); + expect(span.start.offset, equals(0)); + expect(span.start.line, equals(0)); + expect(span.start.column, equals(0)); + expect(span.sourceUrl, sourceUrl); + return true; +}); From 8b38f4be7340718a126e10d5424691a0ddfb1484 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 24 Jun 2014 20:07:33 +0000 Subject: [PATCH 040/179] Fix busted type parameters in yaml. R=rnystrom@google.com Review URL: https://codereview.chromium.org//354653003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@37668 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 6 ++++++ pkgs/yaml/lib/src/yaml_node_wrapper.dart | 5 +++-- pkgs/yaml/pubspec.yaml | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 186cfabdc..e4f532c4e 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.1.1 + +* Fix broken type arguments that caused breakage on dart2js. + +* Fix an analyzer warning in `yaml_node_wrapper.dart`. + ## 1.1.0 * Add new publicly-accessible constructors for `YamlNode` subclasses. These diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index 8ea084e33..2dcaa2385 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -14,7 +14,7 @@ import 'yaml_node.dart'; /// A wrapper that makes a normal Dart map behave like a [YamlMap]. class YamlMapWrapper extends MapBase - with pkg_collection.UnmodifiableMapMixin + with pkg_collection.UnmodifiableMapMixin implements YamlMap { final Map _dartMap; @@ -61,7 +61,8 @@ class _YamlMapNodes extends MapBase _YamlMapNodes(this._dartMap, this._span); YamlNode operator [](Object key) { - if (key is YamlScalar) key = key.value; + // Use "as" here because key being assigned to invalidates type propagation. + if (key is YamlScalar) key = (key as YamlScalar).value; if (!_dartMap.containsKey(key)) return null; return _nodeForValue(_dartMap[key], _span); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 558969579..c160482fc 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 1.1.0 +version: 1.1.1 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. From 92c54cccf59c8e03b2c6cd333d1b00c415bfdb0f Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 23 Jul 2014 23:44:09 +0000 Subject: [PATCH 041/179] Move a number of packages and some of pub over to using source_span. R=efortuna@google.com, rnystrom@google.com, sigmund@google.com BUG=19930 Review URL: https://codereview.chromium.org//401753002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@38526 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 8 +++ pkgs/yaml/lib/src/model.dart | 12 ++-- pkgs/yaml/lib/src/null_span.dart | 38 ++---------- pkgs/yaml/lib/src/parser.dart | 10 +-- pkgs/yaml/lib/src/yaml_exception.dart | 6 +- pkgs/yaml/lib/src/yaml_node.dart | 72 ++++++++++++---------- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 24 ++++---- pkgs/yaml/lib/yaml.dart | 20 +++--- pkgs/yaml/pubspec.yaml | 6 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 22 +++---- 10 files changed, 105 insertions(+), 113 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index e4f532c4e..94c880731 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,11 @@ +## 2.0.0 + +* Switch from `source_maps`' `Span` class to `source_span`'s `SourceSpan` class. + +* For consistency with `source_span` and `string_scanner`, all `sourceName` + parameters have been renamed to `sourceUrl`. They now accept Urls as well as + Strings. + ## 1.1.1 * Fix broken type arguments that caused breakage on dart2js. diff --git a/pkgs/yaml/lib/src/model.dart b/pkgs/yaml/lib/src/model.dart index 097376957..93cb49c7a 100644 --- a/pkgs/yaml/lib/src/model.dart +++ b/pkgs/yaml/lib/src/model.dart @@ -7,7 +7,7 @@ /// representation graph. library yaml.model; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'equality.dart'; import 'parser.dart'; @@ -83,7 +83,7 @@ abstract class Node { String anchor; /// The source span for this node. - Span span; + SourceSpan span; Node(this.tag, this.span, [this.anchor]); @@ -102,7 +102,7 @@ class SequenceNode extends Node { /// The nodes in the sequence. List content; - SequenceNode(String tagName, this.content, Span span) + SequenceNode(String tagName, this.content, SourceSpan span) : super(new Tag.sequence(tagName), span); /// Two sequences are equal if their tags and contents are equal. @@ -125,7 +125,7 @@ class SequenceNode extends Node { /// An alias node is a reference to an anchor. class AliasNode extends Node { - AliasNode(String anchor, Span span) + AliasNode(String anchor, SourceSpan span) : super(new Tag.scalar(Tag.yaml("str")), span, anchor); visit(Visitor v) => v.visitAlias(this); @@ -145,7 +145,7 @@ class ScalarNode extends Node { /// be specified for a newly-parsed scalar that hasn't yet been composed. /// Value should be specified for a composed scalar, although `null` is a /// valid value. - ScalarNode(String tagName, Span span, {String content, this.value}) + ScalarNode(String tagName, SourceSpan span, {String content, this.value}) : _content = content, super(new Tag.scalar(tagName), span); @@ -231,7 +231,7 @@ class MappingNode extends Node { /// The node map. Map content; - MappingNode(String tagName, this.content, Span span) + MappingNode(String tagName, this.content, SourceSpan span) : super(new Tag.mapping(tagName), span); /// Two mappings are equal if their tags and contents are equal. diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index b3e325499..1054df168 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -4,44 +4,18 @@ library yaml.null_span; -import 'package:path/path.dart' as p; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; /// A [Span] with no location information. /// /// This is used with [YamlMap.wrap] and [YamlList.wrap] to provide means of /// accessing a non-YAML map that behaves transparently like a map parsed from /// YAML. -class NullSpan extends Span { - Location get end => start; +class NullSpan extends SourceSpanMixin { + final SourceLocation start; + SourceLocation get end => start; final text = ""; - NullSpan(String sourceUrl) - : this._(new NullLocation(sourceUrl)); - - NullSpan._(Location location) - : super(location, location, false); - - String formatLocationMessage(String message, {bool useColors: false, - String color}) { - var locationMessage = sourceUrl == null ? "in an unknown location" : - "in ${p.prettyUri(sourceUrl)}"; - return "$locationMessage: $message"; - } -} - -/// A [Location] with no location information. -/// -/// This is used with [YamlMap.wrap] and [YamlList.wrap] to provide means of -/// accessing a non-YAML map that behaves transparently like a map parsed from -/// YAML. -class NullLocation extends Location { - final String sourceUrl; - final line = 0; - final column = 0; - - String get formatString => sourceUrl == null ? "unknown location" : sourceUrl; - - NullLocation(this.sourceUrl) - : super(0); + NullSpan(sourceUrl) + : start = new SourceLocation(0, sourceUrl: sourceUrl); } diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index b42638f52..94f551f21 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -6,7 +6,7 @@ library yaml.parser; import 'dart:collection'; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'package:string_scanner/string_scanner.dart'; import 'equality.dart'; @@ -151,8 +151,8 @@ class Parser { /// Whether the current string capture is being overridden. bool _capturingAs = false; - Parser(String yaml, String sourceName) - : _scanner = new SpanScanner(yaml, sourceName) { + Parser(String yaml, sourceUrl) + : _scanner = new SpanScanner(yaml, sourceUrl: sourceUrl) { _farthestState = _scanner.state; } @@ -326,7 +326,7 @@ class Parser { } /// Creates a MappingNode from [pairs]. - MappingNode map(List> pairs, Span span) { + MappingNode map(List> pairs, SourceSpan span) { var content = new Map(); pairs.forEach((pair) => content[pair.first] = pair.last); return new MappingNode("?", content, span); @@ -1822,7 +1822,7 @@ class Parser { or([l_directiveDocument, l_explicitDocument, l_bareDocument]); // 211 - Pair, Span> l_yamlStream() { + Pair, SourceSpan> l_yamlStream() { var start = _scanner.state; var docs = []; zeroOrMore(l_documentPrefix); diff --git a/pkgs/yaml/lib/src/yaml_exception.dart b/pkgs/yaml/lib/src/yaml_exception.dart index 9d4371768..86899531e 100644 --- a/pkgs/yaml/lib/src/yaml_exception.dart +++ b/pkgs/yaml/lib/src/yaml_exception.dart @@ -4,11 +4,11 @@ library yaml.exception; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; /// An error thrown by the YAML processor. -class YamlException extends SpanFormatException { - YamlException(String message, Span span) +class YamlException extends SourceSpanFormatException { + YamlException(String message, SourceSpan span) : super(message, span); } diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 1aded2be7..4f770609b 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -7,7 +7,7 @@ library yaml.yaml_node; import 'dart:collection' as collection; import 'package:collection/collection.dart'; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'null_span.dart'; import 'yaml_node_wrapper.dart'; @@ -24,9 +24,9 @@ import 'yaml_node_wrapper.dart'; abstract class YamlNode { /// The source span for this node. /// - /// [Span.getLocationMessage] can be used to produce a human-friendly message - /// about this node. - Span get span; + /// [SourceSpan.message] can be used to produce a human-friendly message about + /// this node. + SourceSpan get span; /// The inner value of this node. /// @@ -38,7 +38,7 @@ abstract class YamlNode { /// A read-only [Map] parsed from YAML. class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { - final Span span; + final SourceSpan span; /// A view of [this] where the keys and values are guaranteed to be /// [YamlNode]s. @@ -57,20 +57,24 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// Creates an empty YamlMap. /// /// This map's [span] won't have useful location information. However, it will - /// have a reasonable implementation of [Span.getLocationMessage]. If - /// [sourceName] is passed, it's used as the [Span.sourceUrl]. - factory YamlMap({String sourceName}) => - new YamlMapWrapper(const {}, sourceName); + /// have a reasonable implementation of [SourceSpan.message]. If [sourceUrl] + /// is passed, it's used as the [SourceSpan.sourceUrl]. + /// + /// [sourceUrl] may be either a [String], a [Uri], or `null`. + factory YamlMap({sourceUrl}) => + new YamlMapWrapper(const {}, sourceUrl); /// Wraps a Dart map so that it can be accessed (recursively) like a /// [YamlMap]. /// - /// Any [Span]s returned by this map or its children will be dummies without - /// useful location information. However, they will have a reasonable - /// implementation of [Span.getLocationMessage]. If [sourceName] is passed, - /// it's used as the [Span.sourceUrl]. - factory YamlMap.wrap(Map dartMap, {String sourceName}) => - new YamlMapWrapper(dartMap, sourceName); + /// Any [SourceSpan]s returned by this map or its children will be dummies + /// without useful location information. However, they will have a reasonable + /// implementation of [SourceSpan.getLocationMessage]. If [sourceUrl] is + /// passed, it's used as the [SourceSpan.sourceUrl]. + /// + /// [sourceUrl] may be either a [String], a [Uri], or `null`. + factory YamlMap.wrap(Map dartMap, {sourceUrl}) => + new YamlMapWrapper(dartMap, sourceUrl); /// Users of the library should not use this constructor. YamlMap.internal(Map nodes, this.span) @@ -85,7 +89,7 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { // TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed. /// A read-only [List] parsed from YAML. class YamlList extends YamlNode with collection.ListMixin { - final Span span; + final SourceSpan span; final List nodes; @@ -100,20 +104,24 @@ class YamlList extends YamlNode with collection.ListMixin { /// Creates an empty YamlList. /// /// This list's [span] won't have useful location information. However, it - /// will have a reasonable implementation of [Span.getLocationMessage]. If - /// [sourceName] is passed, it's used as the [Span.sourceUrl]. - factory YamlList({String sourceName}) => - new YamlListWrapper(const [], sourceName); + /// will have a reasonable implementation of [SourceSpan.message]. If + /// [sourceUrl] is passed, it's used as the [SourceSpan.sourceUrl]. + /// + /// [sourceUrl] may be either a [String], a [Uri], or `null`. + factory YamlList({sourceUrl}) => + new YamlListWrapper(const [], sourceUrl); /// Wraps a Dart list so that it can be accessed (recursively) like a /// [YamlList]. /// - /// Any [Span]s returned by this list or its children will be dummies without - /// useful location information. However, they will have a reasonable - /// implementation of [Span.getLocationMessage]. If [sourceName] is passed, - /// it's used as the [Span.sourceUrl]. - factory YamlList.wrap(List dartList, {String sourceName}) => - new YamlListWrapper(dartList, sourceName); + /// Any [SourceSpan]s returned by this list or its children will be dummies + /// without useful location information. However, they will have a reasonable + /// implementation of [SourceSpan.getLocationMessage]. If [sourceUrl] is + /// passed, it's used as the [Span.sourceUrl]. + /// + /// [sourceUrl] may be either a [String], a [Uri], or `null`. + factory YamlList.wrap(List dartList, {sourceUrl}) => + new YamlListWrapper(dartList, sourceUrl); /// Users of the library should not use this constructor. YamlList.internal(List nodes, this.span) @@ -128,17 +136,19 @@ class YamlList extends YamlNode with collection.ListMixin { /// A wrapped scalar value parsed from YAML. class YamlScalar extends YamlNode { - final Span span; + final SourceSpan span; final value; /// Wraps a Dart value in a [YamlScalar]. /// /// This scalar's [span] won't have useful location information. However, it - /// will have a reasonable implementation of [Span.getLocationMessage]. If - /// [sourceName] is passed, it's used as the [Span.sourceUrl]. - YamlScalar.wrap(this.value, {String sourceName}) - : span = new NullSpan(sourceName); + /// will have a reasonable implementation of [SourceSpan.message]. If + /// [sourceUrl] is passed, it's used as the [Span.sourceUrl]. + /// + /// [sourceUrl] may be either a [String], a [Uri], or `null`. + YamlScalar.wrap(this.value, {sourceUrl}) + : span = new NullSpan(sourceUrl); /// Users of the library should not use this constructor. YamlScalar.internal(this.value, this.span); diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index 2dcaa2385..d000dcb8e 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -7,7 +7,7 @@ library yaml.yaml_node_wrapper; import 'dart:collection'; import 'package:collection/collection.dart' as pkg_collection; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'null_span.dart'; import 'yaml_node.dart'; @@ -18,7 +18,7 @@ class YamlMapWrapper extends MapBase implements YamlMap { final Map _dartMap; - final Span span; + final SourceSpan span; final Map nodes; @@ -26,10 +26,10 @@ class YamlMapWrapper extends MapBase Iterable get keys => _dartMap.keys; - YamlMapWrapper(Map dartMap, String sourceName) - : this._(dartMap, new NullSpan(sourceName)); + YamlMapWrapper(Map dartMap, sourceUrl) + : this._(dartMap, new NullSpan(sourceUrl)); - YamlMapWrapper._(Map dartMap, Span span) + YamlMapWrapper._(Map dartMap, SourceSpan span) : _dartMap = dartMap, span = span, nodes = new _YamlMapNodes(dartMap, span); @@ -53,7 +53,7 @@ class _YamlMapNodes extends MapBase with pkg_collection.UnmodifiableMapMixin { final Map _dartMap; - final Span _span; + final SourceSpan _span; Iterable get keys => _dartMap.keys.map((key) => new YamlScalar.internal(key, _span)); @@ -78,7 +78,7 @@ class _YamlMapNodes extends MapBase class YamlListWrapper extends ListBase implements YamlList { final List _dartList; - final Span span; + final SourceSpan span; final List nodes; @@ -90,10 +90,10 @@ class YamlListWrapper extends ListBase implements YamlList { throw new UnsupportedError("Cannot modify an unmodifiable List."); } - YamlListWrapper(List dartList, String sourceName) - : this._(dartList, new NullSpan(sourceName)); + YamlListWrapper(List dartList, sourceUrl) + : this._(dartList, new NullSpan(sourceUrl)); - YamlListWrapper._(List dartList, Span span) + YamlListWrapper._(List dartList, SourceSpan span) : _dartList = dartList, span = span, nodes = new _YamlListNodes(dartList, span); @@ -121,7 +121,7 @@ class YamlListWrapper extends ListBase implements YamlList { class _YamlListNodes extends ListBase { final List _dartList; - final Span _span; + final SourceSpan _span; int get length => _dartList.length; @@ -143,7 +143,7 @@ class _YamlListNodes extends ListBase { other is _YamlListNodes && other._dartList == _dartList; } -YamlNode _nodeForValue(value, Span span) { +YamlNode _nodeForValue(value, SourceSpan span) { if (value is Map) return new YamlMapWrapper._(value, span); if (value is List) return new YamlListWrapper._(value, span); return new YamlScalar.internal(value, span); diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 0afc2cc8e..e45dd6ebe 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -29,18 +29,18 @@ export 'src/yaml_node.dart'; /// In future versions, maps will instead be [HashMap]s with a custom equality /// operation. /// -/// If [sourceName] is passed, it's used as the name of the file or URL from -/// which the YAML originated for error reporting. -loadYaml(String yaml, {String sourceName}) => - loadYamlNode(yaml, sourceName: sourceName).value; +/// If [sourceUrl] is passed, it's used as the URL from which the YAML +/// originated for error reporting. It can be a [String], a [Uri], or `null`. +loadYaml(String yaml, {sourceUrl}) => + loadYamlNode(yaml, sourceUrl: sourceUrl).value; /// Loads a single document from a YAML string as a [YamlNode]. /// /// This is just like [loadYaml], except that where [loadYaml] would return a /// normal Dart value this returns a [YamlNode] instead. This allows the caller /// to be confident that the return value will always be a [YamlNode]. -YamlNode loadYamlNode(String yaml, {String sourceName}) { - var stream = loadYamlStream(yaml, sourceName: sourceName); +YamlNode loadYamlNode(String yaml, {sourceUrl}) { + var stream = loadYamlStream(yaml, sourceUrl: sourceUrl); if (stream.length != 1) { throw new YamlException("Expected 1 document, were ${stream.length}.", stream.span); @@ -59,12 +59,12 @@ YamlNode loadYamlNode(String yaml, {String sourceName}) { /// In future versions, maps will instead be [HashMap]s with a custom equality /// operation. /// -/// If [sourceName] is passed, it's used as the name of the file or URL from -/// which the YAML originated for error reporting. -YamlList loadYamlStream(String yaml, {String sourceName}) { +/// If [sourceUrl] is passed, it's used as the URL from which the YAML +/// originated for error reporting. It can be a [String], a [Uri], or `null`. +YamlList loadYamlStream(String yaml, {sourceUrl}) { var pair; try { - pair = new Parser(yaml, sourceName).l_yamlStream(); + pair = new Parser(yaml, sourceUrl).l_yamlStream(); } on StringScannerException catch (error) { throw new YamlException(error.message, error.span); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index c160482fc..470bc2fcf 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,13 +1,13 @@ name: yaml -version: 1.1.1 +version: 2.0.0 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dependencies: collection: ">=0.9.2 <0.10.0" path: ">=1.2.0 <2.0.0" - string_scanner: ">=0.0.2 <0.1.0" - source_maps: ">=0.9.2 <0.10.0" + string_scanner: ">=0.1.0 <0.2.0" + source_span: ">=1.0.0 <2.0.0" dev_dependencies: unittest: ">=0.9.0 <0.12.0" environment: diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index 8bf4761ba..7d4faa6dd 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -9,31 +9,31 @@ import 'package:unittest/unittest.dart'; import 'package:yaml/yaml.dart'; main() { - test("YamlMap() with no sourceName", () { + test("YamlMap() with no sourceUrl", () { var map = new YamlMap(); expect(map, isEmpty); expect(map.nodes, isEmpty); expect(map.span, isNullSpan(isNull)); }); - test("YamlMap() with a sourceName", () { - var map = new YamlMap(sourceName: "source"); + test("YamlMap() with a sourceUrl", () { + var map = new YamlMap(sourceUrl: "source"); expect(map.span, isNullSpan("source")); }); - test("YamlList() with no sourceName", () { + test("YamlList() with no sourceUrl", () { var list = new YamlList(); expect(list, isEmpty); expect(list.nodes, isEmpty); expect(list.span, isNullSpan(isNull)); }); - test("YamlList() with a sourceName", () { - var list = new YamlList(sourceName: "source"); + test("YamlList() with a sourceUrl", () { + var list = new YamlList(sourceUrl: "source"); expect(list.span, isNullSpan("source")); }); - test("YamlMap.wrap() with no sourceName", () { + test("YamlMap.wrap() with no sourceUrl", () { var map = new YamlMap.wrap({ "list": [1, 2, 3], "map": { @@ -69,7 +69,7 @@ main() { expect(map.nodes[new YamlScalar.wrap("list")], equals([1, 2, 3])); }); - test("YamlMap.wrap() with a sourceName", () { + test("YamlMap.wrap() with a sourceUrl", () { var map = new YamlMap.wrap({ "list": [1, 2, 3], "map": { @@ -77,7 +77,7 @@ main() { "nested": [4, 5, 6] }, "scalar": "value" - }, sourceName: "source"); + }, sourceUrl: "source"); expect(map.span, isNullSpan("source")); expect(map["list"].span, isNullSpan("source")); @@ -85,7 +85,7 @@ main() { expect(map.nodes["scalar"].span, isNullSpan("source")); }); - test("YamlList.wrap() with no sourceName", () { + test("YamlList.wrap() with no sourceUrl", () { var list = new YamlList.wrap([ [1, 2, 3], { @@ -118,7 +118,7 @@ main() { expect(list[2], "value"); }); - test("YamlList.wrap() with a sourceName", () { + test("YamlList.wrap() with a sourceUrl", () { var list = new YamlList.wrap([ [1, 2, 3], { From 8d5d55d25443d27cf9c09db645e7f6f753a727d1 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 29 Jul 2014 01:37:14 +0000 Subject: [PATCH 042/179] Fix lingering references to the old Span in yaml. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//413403002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@38656 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 5 +++++ pkgs/yaml/lib/src/null_span.dart | 2 +- pkgs/yaml/lib/src/yaml_node.dart | 4 ++-- pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 18 +++++++++--------- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 94c880731..0c8ed7b8a 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.0.1 + +* Fix a few lingering references to the old `Span` class in documentation and + tests. + ## 2.0.0 * Switch from `source_maps`' `Span` class to `source_span`'s `SourceSpan` class. diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index 1054df168..06b42f020 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -6,7 +6,7 @@ library yaml.null_span; import 'package:source_span/source_span.dart'; -/// A [Span] with no location information. +/// A [SourceSpan] with no location information. /// /// This is used with [YamlMap.wrap] and [YamlList.wrap] to provide means of /// accessing a non-YAML map that behaves transparently like a map parsed from diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 4f770609b..6320156e1 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -117,7 +117,7 @@ class YamlList extends YamlNode with collection.ListMixin { /// Any [SourceSpan]s returned by this list or its children will be dummies /// without useful location information. However, they will have a reasonable /// implementation of [SourceSpan.getLocationMessage]. If [sourceUrl] is - /// passed, it's used as the [Span.sourceUrl]. + /// passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. factory YamlList.wrap(List dartList, {sourceUrl}) => @@ -144,7 +144,7 @@ class YamlScalar extends YamlNode { /// /// This scalar's [span] won't have useful location information. However, it /// will have a reasonable implementation of [SourceSpan.message]. If - /// [sourceUrl] is passed, it's used as the [Span.sourceUrl]. + /// [sourceUrl] is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. YamlScalar.wrap(this.value, {sourceUrl}) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 470bc2fcf..f9f784c59 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.0.0 +version: 2.0.1 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index 7d4faa6dd..712eeee47 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -18,7 +18,7 @@ main() { test("YamlMap() with a sourceUrl", () { var map = new YamlMap(sourceUrl: "source"); - expect(map.span, isNullSpan("source")); + expect(map.span, isNullSpan(Uri.parse("source"))); }); test("YamlList() with no sourceUrl", () { @@ -30,7 +30,7 @@ main() { test("YamlList() with a sourceUrl", () { var list = new YamlList(sourceUrl: "source"); - expect(list.span, isNullSpan("source")); + expect(list.span, isNullSpan(Uri.parse("source"))); }); test("YamlMap.wrap() with no sourceUrl", () { @@ -79,10 +79,11 @@ main() { "scalar": "value" }, sourceUrl: "source"); - expect(map.span, isNullSpan("source")); - expect(map["list"].span, isNullSpan("source")); - expect(map["map"].span, isNullSpan("source")); - expect(map.nodes["scalar"].span, isNullSpan("source")); + var source = Uri.parse("source"); + expect(map.span, isNullSpan(source)); + expect(map["list"].span, isNullSpan(source)); + expect(map["map"].span, isNullSpan(source)); + expect(map.nodes["scalar"].span, isNullSpan(source)); }); test("YamlList.wrap() with no sourceUrl", () { @@ -134,7 +135,7 @@ main() { expect(list.nodes[2].span, isNullSpan(isNull)); }); - solo_test("re-wrapped objects equal one another", () { + test("re-wrapped objects equal one another", () { var list = new YamlList.wrap([ [1, 2, 3], {"foo": "bar"} @@ -150,10 +151,9 @@ main() { } Matcher isNullSpan(sourceUrl) => predicate((span) { - expect(span, new isInstanceOf()); + expect(span, new isInstanceOf()); expect(span.length, equals(0)); expect(span.text, isEmpty); - expect(span.isIdentifier, isFalse); expect(span.start, equals(span.end)); expect(span.start.offset, equals(0)); expect(span.start.line, equals(0)); From 0ea30a1101fd64a80314819167192adaccac7fc1 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 29 Jul 2014 02:13:51 +0000 Subject: [PATCH 043/179] Fix an import in yaml_node_wrapper_test. R=rnystrom@google.com TBR Review URL: https://codereview.chromium.org//423033002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@38657 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 0c8ed7b8a..ee12bca94 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.2 + +* Fix an import in a test. + ## 2.0.1 * Fix a few lingering references to the old `Span` class in documentation and diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index f9f784c59..afb8a0eea 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.0.1 +version: 2.0.2-dev author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index 712eeee47..2c41a6af3 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -4,7 +4,7 @@ library yaml.node_wrapper_test; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'package:unittest/unittest.dart'; import 'package:yaml/yaml.dart'; From 5c8372b4378211033cb5f0d55fed9e8510d2ffaa Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Fri, 22 Aug 2014 08:52:09 +0000 Subject: [PATCH 044/179] Update dart:collection to version 1.0.0 R=sgjesse@google.com Review URL: https://codereview.chromium.org//463333004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@39484 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index afb8a0eea..5362b6008 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -4,7 +4,7 @@ author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dependencies: - collection: ">=0.9.2 <0.10.0" + collection: ">=0.9.2 <2.0.0" path: ">=1.2.0 <2.0.0" string_scanner: ">=0.1.0 <0.2.0" source_span: ">=1.0.0 <2.0.0" From 757ba49f8c01a1376ae3755cdd5358780a313d49 Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Fri, 29 Aug 2014 21:17:50 +0000 Subject: [PATCH 045/179] pkg/yaml prepare for release R=nweiz@google.com Review URL: https://codereview.chromium.org//518853002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@39711 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 4 +++- pkgs/yaml/pubspec.yaml | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index ee12bca94..68af5f557 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,7 +1,9 @@ -## 2.0.2 +## 2.0.1+1 * Fix an import in a test. +* Widen the version constraint on the `collection` package. + ## 2.0.1 * Fix a few lingering references to the old `Span` class in documentation and diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 5362b6008..74194e5fa 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.0.2-dev +version: 2.0.1+1 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. @@ -11,4 +11,4 @@ dependencies: dev_dependencies: unittest: ">=0.9.0 <0.12.0" environment: - sdk: ">=1.5.0-dev.0.0 <2.0.0" + sdk: '>=1.5.0 <2.0.0' From 38c641aaf63f4189037f046fb2c56fe61b882c93 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 10 Nov 2014 21:49:37 +0000 Subject: [PATCH 046/179] Rewrite the pkg/yaml parser. This increases the speed by about 10x. It also adds a number of new featurse. BUG=21317, 20859 R=rnystrom@google.com Review URL: https://codereview.chromium.org//689513002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@41649 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 18 + pkgs/yaml/lib/src/composer.dart | 183 -- pkgs/yaml/lib/src/constructor.dart | 76 - pkgs/yaml/lib/src/event.dart | 157 ++ pkgs/yaml/lib/src/loader.dart | 257 +++ pkgs/yaml/lib/src/model.dart | 259 --- pkgs/yaml/lib/src/parser.dart | 2421 ++++++---------------- pkgs/yaml/lib/src/scanner.dart | 1663 +++++++++++++++ pkgs/yaml/lib/src/style.dart | 73 + pkgs/yaml/lib/src/token.dart | 148 ++ pkgs/yaml/lib/src/utils.dart | 29 + pkgs/yaml/lib/src/visitor.dart | 30 - pkgs/yaml/lib/src/yaml_document.dart | 67 + pkgs/yaml/lib/src/yaml_node.dart | 47 +- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 11 +- pkgs/yaml/lib/yaml.dart | 78 +- pkgs/yaml/libyaml-license.txt | 19 + pkgs/yaml/pubspec.yaml | 6 +- pkgs/yaml/test/yaml_test.dart | 611 +++--- 19 files changed, 3521 insertions(+), 2632 deletions(-) delete mode 100644 pkgs/yaml/lib/src/composer.dart delete mode 100644 pkgs/yaml/lib/src/constructor.dart create mode 100644 pkgs/yaml/lib/src/event.dart create mode 100644 pkgs/yaml/lib/src/loader.dart delete mode 100644 pkgs/yaml/lib/src/model.dart create mode 100644 pkgs/yaml/lib/src/scanner.dart create mode 100644 pkgs/yaml/lib/src/style.dart create mode 100644 pkgs/yaml/lib/src/token.dart delete mode 100644 pkgs/yaml/lib/src/visitor.dart create mode 100644 pkgs/yaml/lib/src/yaml_document.dart create mode 100644 pkgs/yaml/libyaml-license.txt diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 68af5f557..f454255b6 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,21 @@ +## 2.1.0 + +* Rewrite the parser for a 10x speed improvement. + +* Support anchors and aliases (`&foo` and `*foo`). + +* Support explicit tags (e.g. `!!str`). Note that user-defined tags are still + not fully supported. + +* `%YAML` and `%TAG` directives are now parsed, although again user-defined tags + are not fully supported. + +* `YamlScalar`, `YamlList`, and `YamlMap` now expose the styles in which they + were written (for example plain vs folded, block vs flow). + +* A `yamlWarningCallback` field is exposed. This field can be used to customize + how YAML warnings are displayed. + ## 2.0.1+1 * Fix an import in a test. diff --git a/pkgs/yaml/lib/src/composer.dart b/pkgs/yaml/lib/src/composer.dart deleted file mode 100644 index 8612067e7..000000000 --- a/pkgs/yaml/lib/src/composer.dart +++ /dev/null @@ -1,183 +0,0 @@ -// 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 yaml.composer; - -import 'model.dart'; -import 'visitor.dart'; -import 'yaml_exception.dart'; - -/// Takes a parsed YAML document (what the spec calls the "serialization tree") -/// and resolves aliases, resolves tags, and parses scalars to produce the -/// "representation graph". -class Composer extends Visitor { - /// The root node of the serialization tree. - final Node _root; - - /// Map from anchor names to the most recent representation graph node with - /// that anchor. - final _anchors = {}; - - /// The next id to use for the represenation graph's anchors. - /// - /// The spec doesn't use anchors in the representation graph, but we do so - /// that the constructor can ensure that the same node in the representation - /// graph produces the same native object. - var _idCounter = 0; - - Composer(this._root); - - /// Runs the Composer to produce a representation graph. - Node compose() => _root.visit(this); - - /// Returns the anchor to which an alias node refers. - Node visitAlias(AliasNode alias) { - if (!_anchors.containsKey(alias.anchor)) { - throw new YamlException("No anchor for alias ${alias.anchor}.", - alias.span); - } - return _anchors[alias.anchor]; - } - - /// Parses a scalar node according to its tag, or auto-detects the type if no - /// tag exists. - /// - /// Currently this only supports the YAML core type schema. - Node visitScalar(ScalarNode scalar) { - if (scalar.tag.name == "!") { - return setAnchor(scalar, parseString(scalar)); - } else if (scalar.tag.name == "?") { - for (var fn in [parseNull, parseBool, parseInt, parseFloat]) { - var result = fn(scalar); - if (result != null) return result; - } - return setAnchor(scalar, parseString(scalar)); - } - - var result = _parseByTag(scalar); - if (result != null) return setAnchor(scalar, result); - throw new YamlException('Invalid literal for ${scalar.tag}.', - scalar.span); - } - - ScalarNode _parseByTag(ScalarNode scalar) { - switch (scalar.tag.name) { - case "null": return parseNull(scalar); - case "bool": return parseBool(scalar); - case "int": return parseInt(scalar); - case "float": return parseFloat(scalar); - case "str": return parseString(scalar); - } - throw new YamlException('Undefined tag: ${scalar.tag}.', scalar.span); - } - - /// Assigns a tag to the sequence and recursively composes its contents. - Node visitSequence(SequenceNode seq) { - var tagName = seq.tag.name; - if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("seq")) { - throw new YamlException("Invalid tag for sequence: ${seq.tag}.", - seq.span); - } - - var result = setAnchor(seq, - new SequenceNode(Tag.yaml('seq'), null, seq.span)); - result.content = super.visitSequence(seq); - return result; - } - - /// Assigns a tag to the mapping and recursively composes its contents. - Node visitMapping(MappingNode map) { - var tagName = map.tag.name; - if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("map")) { - throw new YamlException("Invalid tag for mapping: ${map.tag}.", - map.span); - } - - var result = setAnchor(map, - new MappingNode(Tag.yaml('map'), null, map.span)); - result.content = super.visitMapping(map); - return result; - } - - /// If the serialization tree node [anchored] has an anchor, records that - /// that anchor is pointing to the representation graph node [result]. - Node setAnchor(Node anchored, Node result) { - if (anchored.anchor == null) return result; - result.anchor = '${_idCounter++}'; - _anchors[anchored.anchor] = result; - return result; - } - - /// Parses a null scalar. - ScalarNode parseNull(ScalarNode scalar) { - if (new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(scalar.content)) { - return new ScalarNode(Tag.yaml("null"), scalar.span, value: null); - } else { - return null; - } - } - - /// Parses a boolean scalar. - ScalarNode parseBool(ScalarNode scalar) { - var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"). - firstMatch(scalar.content); - if (match == null) return null; - return new ScalarNode(Tag.yaml("bool"), scalar.span, - value: match.group(1) != null); - } - - /// Parses an integer scalar. - ScalarNode parseInt(ScalarNode scalar) { - var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(scalar.content); - if (match != null) { - return new ScalarNode(Tag.yaml("int"), scalar.span, - value: int.parse(match.group(0))); - } - - match = new RegExp(r"^0o([0-7]+)$").firstMatch(scalar.content); - if (match != null) { - int n = int.parse(match.group(1), radix: 8); - return new ScalarNode(Tag.yaml("int"), scalar.span, value: n); - } - - match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(scalar.content); - if (match != null) { - return new ScalarNode(Tag.yaml("int"), scalar.span, - value: int.parse(match.group(0))); - } - - return null; - } - - /// Parses a floating-point scalar. - ScalarNode parseFloat(ScalarNode scalar) { - var match = new RegExp( - r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"). - firstMatch(scalar.content); - if (match != null) { - // YAML allows floats of the form "0.", but Dart does not. Fix up those - // floats by removing the trailing dot. - var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), ""); - return new ScalarNode(Tag.yaml("float"), scalar.span, - value: double.parse(matchStr)); - } - - match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(scalar.content); - if (match != null) { - var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; - return new ScalarNode(Tag.yaml("float"), scalar.span, value: value); - } - - match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(scalar.content); - if (match != null) { - return new ScalarNode(Tag.yaml("float"), scalar.span, value: double.NAN); - } - - return null; - } - - /// Parses a string scalar. - ScalarNode parseString(ScalarNode scalar) => - new ScalarNode(Tag.yaml("str"), scalar.span, value: scalar.content); -} diff --git a/pkgs/yaml/lib/src/constructor.dart b/pkgs/yaml/lib/src/constructor.dart deleted file mode 100644 index 5931dae01..000000000 --- a/pkgs/yaml/lib/src/constructor.dart +++ /dev/null @@ -1,76 +0,0 @@ -// 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 yaml.constructor; - -import 'equality.dart'; -import 'model.dart'; -import 'visitor.dart'; -import 'yaml_node.dart'; - -/// Takes a parsed and composed YAML document (what the spec calls the -/// "representation graph") and creates native Dart objects that represent that -/// document. -class Constructor extends Visitor { - /// The root node of the representation graph. - final Node _root; - - /// Map from anchor names to the most recent Dart node with that anchor. - final _anchors = {}; - - Constructor(this._root); - - /// Runs the Constructor to produce a Dart object. - YamlNode construct() => _root.visit(this); - - /// Returns the value of a scalar. - YamlScalar visitScalar(ScalarNode scalar) => - new YamlScalar.internal(scalar.value, scalar.span); - - /// Converts a sequence into a List of Dart objects. - YamlList visitSequence(SequenceNode seq) { - var anchor = getAnchor(seq); - if (anchor != null) return anchor; - var nodes = []; - var dartSeq = setAnchor(seq, new YamlList.internal(nodes, seq.span)); - nodes.addAll(super.visitSequence(seq)); - return dartSeq; - } - - /// Converts a mapping into a [Map] of Dart objects. - YamlMap visitMapping(MappingNode map) { - var anchor = getAnchor(map); - if (anchor != null) return anchor; - var nodes = deepEqualsMap(); - var dartMap = setAnchor(map, new YamlMap.internal(nodes, map.span)); - super.visitMapping(map).forEach((k, v) => nodes[k] = v); - return dartMap; - } - - /// Returns a new Dart object wrapping the object that already represents - /// [anchored], if such a thing exists. - YamlNode getAnchor(Node anchored) { - if (anchored.anchor == null) return null; - var value = _anchors[anchored.anchor]; - if (value == null) return null; - - // Re-wrap [value]'s contents so that it's associated with the span of the - // anchor rather than its original definition. - if (value is YamlMap) { - return new YamlMap.internal(value.nodes, anchored.span); - } else if (value is YamlList) { - return new YamlList.internal(value.nodes, anchored.span); - } else { - assert(value is YamlScalar); - return new YamlScalar.internal(value.value, anchored.span); - } - } - - /// Records that [value] is the Dart object representing [anchored]. - YamlNode setAnchor(Node anchored, YamlNode value) { - if (anchored.anchor == null) return value; - _anchors[anchored.anchor] = value; - return value; - } -} diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart new file mode 100644 index 000000000..96e2f1666 --- /dev/null +++ b/pkgs/yaml/lib/src/event.dart @@ -0,0 +1,157 @@ +// Copyright (c) 2014, 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 yaml.event; + +import 'package:source_span/source_span.dart'; + +import 'style.dart'; +import 'yaml_document.dart'; + +/// An event emitted by a [Parser]. +class Event { + /// The event type. + final EventType type; + + /// The span associated with the event. + final FileSpan span; + + Event(this.type, this.span); + + String toString() => type.toString(); +} + +/// An event indicating the beginning of a YAML document. +class DocumentStartEvent implements Event { + get type => EventType.DOCUMENT_START; + final FileSpan span; + + /// The document's `%YAML` directive, or `null` if there was none. + final VersionDirective versionDirective; + + /// The document's `%TAG` directives, if any. + final List tagDirectives; + + /// Whether the document started implicitly (that is, without an explicit + /// `===` sequence). + final bool isImplicit; + + DocumentStartEvent(this.span, {this.versionDirective, + List tagDirectives, this.isImplicit: true}) + : tagDirectives = tagDirectives == null ? [] : tagDirectives; + + String toString() => "DOCUMENT_START"; +} + +/// An event indicating the end of a YAML document. +class DocumentEndEvent implements Event { + get type => EventType.DOCUMENT_END; + final FileSpan span; + + /// Whether the document ended implicitly (that is, without an explicit + /// `...` sequence). + final bool isImplicit; + + DocumentEndEvent(this.span, {this.isImplicit: true}); + + String toString() => "DOCUMENT_END"; +} + +/// An event indicating that an alias was referenced. +class AliasEvent implements Event { + get type => EventType.ALIAS; + final FileSpan span; + + /// The name of the anchor. + final String name; + + AliasEvent(this.span, this.name); + + String toString() => "ALIAS $name"; +} + +/// A base class for events that can have anchor and tag properties associated +/// with them. +abstract class _ValueEvent implements Event { + /// The name of the value's anchor, or `null` if it wasn't anchored. + String get anchor; + + /// The text of the value's tag, or `null` if it wasn't tagged. + String get tag; + + String toString() { + var buffer = new StringBuffer('$type'); + if (anchor != null) buffer.write(" &$anchor"); + if (tag != null) buffer.write(" $tag"); + return buffer.toString(); + } +} + +/// An event indicating a single scalar value. +class ScalarEvent extends _ValueEvent { + get type => EventType.SCALAR; + final FileSpan span; + final String anchor; + final String tag; + + /// The contents of the scalar. + final String value; + + /// The style of the scalar in the original source. + final ScalarStyle style; + + ScalarEvent(this.span, this.value, this.style, {this.anchor, this.tag}); + + String toString() => "${super.toString()} \"$value\""; +} + +/// An event indicating the beginning of a sequence. +class SequenceStartEvent extends _ValueEvent { + get type => EventType.SEQUENCE_START; + final FileSpan span; + final String anchor; + final String tag; + + /// The style of the collection in the original source. + final CollectionStyle style; + + SequenceStartEvent(this.span, this.style, {this.anchor, this.tag}); +} + +/// An event indicating the beginning of a mapping. +class MappingStartEvent extends _ValueEvent { + get type => EventType.MAPPING_START; + final FileSpan span; + final String anchor; + final String tag; + + /// The style of the collection in the original source. + final CollectionStyle style; + + MappingStartEvent(this.span, this.style, {this.anchor, this.tag}); +} + +/// An enum of types of [Event] object. +class EventType { + static const STREAM_START = const EventType._("STREAM_START"); + static const STREAM_END = const EventType._("STREAM_END"); + + static const DOCUMENT_START = const EventType._("DOCUMENT_START"); + static const DOCUMENT_END = const EventType._("DOCUMENT_END"); + + static const ALIAS = const EventType._("ALIAS"); + static const SCALAR = const EventType._("SCALAR"); + + static const SEQUENCE_START = const EventType._("SEQUENCE_START"); + static const SEQUENCE_END = const EventType._("SEQUENCE_END"); + + static const MAPPING_START = const EventType._("MAPPING_START"); + static const MAPPING_END = const EventType._("MAPPING_END"); + + final String name; + + const EventType._(this.name); + + String toString() => name; +} diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart new file mode 100644 index 000000000..d80578fc9 --- /dev/null +++ b/pkgs/yaml/lib/src/loader.dart @@ -0,0 +1,257 @@ +// Copyright (c) 2014, 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 yaml.loader; + +import 'package:source_span/source_span.dart'; + +import 'equality.dart'; +import 'event.dart'; +import 'parser.dart'; +import 'yaml_document.dart'; +import 'yaml_exception.dart'; +import 'yaml_node.dart'; + +/// A loader that reads [Event]s emitted by a [Parser] and emits +/// [YamlDocument]s. +/// +/// This is based on the libyaml loader, available at +/// https://github.com/yaml/libyaml/blob/master/src/loader.c. The license for +/// that is available in ../../libyaml-license.txt. +class Loader { + /// The underlying [Parser] that generates [Event]s. + final Parser _parser; + + /// Aliases by the alias name. + final _aliases = new Map(); + + /// The span of the entire stream emitted so far. + FileSpan get span => _span; + FileSpan _span; + + /// Creates a loader that loads [source]. + /// + /// [sourceUrl] can be a String or a [Uri]. + Loader(String source, {sourceUrl}) + : _parser = new Parser(source, sourceUrl: sourceUrl) { + var event = _parser.parse(); + _span = event.span; + assert(event.type == EventType.STREAM_START); + } + + /// Loads the next document from the stream. + /// + /// If there are no more documents, returns `null`. + YamlDocument load() { + if (_parser.isDone) return null; + + var event = _parser.parse(); + if (event.type == EventType.STREAM_END) { + _span = _span.expand(event.span); + return null; + } + + var document = _loadDocument(event); + _span = _span.expand(document.span); + _aliases.clear(); + return document; + } + + /// Composes a document object. + YamlDocument _loadDocument(DocumentStartEvent firstEvent) { + var contents = _loadNode(_parser.parse()); + + var lastEvent = _parser.parse(); + assert(lastEvent.type == EventType.DOCUMENT_END); + + return new YamlDocument.internal( + contents, + firstEvent.span.expand(lastEvent.span), + firstEvent.versionDirective, + firstEvent.tagDirectives, + startImplicit: firstEvent.isImplicit, + endImplicit: lastEvent.isImplicit); + } + + /// Composes a node. + YamlNode _loadNode(Event firstEvent) { + switch (firstEvent.type) { + case EventType.ALIAS: return _loadAlias(firstEvent); + case EventType.SCALAR: return _loadScalar(firstEvent); + case EventType.SEQUENCE_START: return _loadSequence(firstEvent); + case EventType.MAPPING_START: return _loadMapping(firstEvent); + default: throw "Unreachable"; + } + } + + /// Registers an anchor. + void _registerAnchor(String anchor, YamlNode node) { + if (anchor == null) return; + + // libyaml throws an error for duplicate anchors, but example 7.1 makes it + // clear that they should be overridden: + // http://yaml.org/spec/1.2/spec.html#id2786448. + + _aliases[anchor] = node; + } + + /// Composes a node corresponding to an alias. + YamlNode _loadAlias(AliasEvent event) { + var alias = _aliases[event.name]; + if (alias != null) return alias; + + throw new YamlException("Undefined alias.", event.span); + } + + /// Composes a scalar node. + YamlNode _loadScalar(ScalarEvent scalar) { + var node; + if (scalar.tag == "!") { + node = _parseString(scalar); + } else if (scalar.tag != null) { + node = _parseByTag(scalar); + } else { + node = _parseNull(scalar); + if (node == null) node = _parseBool(scalar); + if (node == null) node = _parseInt(scalar); + if (node == null) node = _parseFloat(scalar); + if (node == null) node = _parseString(scalar); + } + + _registerAnchor(scalar.anchor, node); + return node; + } + + /// Composes a sequence node. + YamlNode _loadSequence(SequenceStartEvent firstEvent) { + if (firstEvent.tag != "!" && firstEvent.tag != null && + firstEvent.tag != "tag:yaml.org,2002:seq") { + throw new YamlException("Invalid tag for sequence.", firstEvent.span); + } + + var children = []; + var node = new YamlList.internal( + children, firstEvent.span, firstEvent.style); + _registerAnchor(firstEvent.anchor, node); + + var event = _parser.parse(); + while (event.type != EventType.SEQUENCE_END) { + children.add(_loadNode(event)); + event = _parser.parse(); + } + + setSpan(node, firstEvent.span.expand(event.span)); + return node; + } + + /// Composes a mapping node. + YamlNode _loadMapping(MappingStartEvent firstEvent) { + if (firstEvent.tag != "!" && firstEvent.tag != null && + firstEvent.tag != "tag:yaml.org,2002:map") { + throw new YamlException("Invalid tag for mapping.", firstEvent.span); + } + + var children = deepEqualsMap(); + var node = new YamlMap.internal( + children, firstEvent.span, firstEvent.style); + _registerAnchor(firstEvent.anchor, node); + + var event = _parser.parse(); + while (event.type != EventType.MAPPING_END) { + var key = _loadNode(event); + var value = _loadNode(_parser.parse()); + children[key] = value; + event = _parser.parse(); + } + + setSpan(node, firstEvent.span.expand(event.span)); + return node; + } + + /// Parses a scalar according to its tag name. + YamlScalar _parseByTag(ScalarEvent scalar) { + switch (scalar.tag) { + case "tag:yaml.org,2002:null": return _parseNull(scalar); + case "tag:yaml.org,2002:bool": return _parseBool(scalar); + case "tag:yaml.org,2002:int": return _parseInt(scalar); + case "tag:yaml.org,2002:float": return _parseFloat(scalar); + case "tag:yaml.org,2002:str": return _parseString(scalar); + } + throw new YamlException('Undefined tag: ${scalar.tag}.', scalar.span); + } + + /// Parses a null scalar. + YamlScalar _parseNull(ScalarEvent scalar) { + // TODO(nweiz): stop using regexps. + // TODO(nweiz): add ScalarStyle and implicit metadata to the scalars. + if (new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(scalar.value)) { + return new YamlScalar.internal(null, scalar.span, scalar.style); + } else { + return null; + } + } + + /// Parses a boolean scalar. + YamlScalar _parseBool(ScalarEvent scalar) { + var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"). + firstMatch(scalar.value); + if (match == null) return null; + return new YamlScalar.internal( + match.group(1) != null, scalar.span, scalar.style); + } + + /// Parses an integer scalar. + YamlScalar _parseInt(ScalarEvent scalar) { + var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(scalar.value); + if (match != null) { + return new YamlScalar.internal( + int.parse(match.group(0)), scalar.span, scalar.style); + } + + match = new RegExp(r"^0o([0-7]+)$").firstMatch(scalar.value); + if (match != null) { + var n = int.parse(match.group(1), radix: 8); + return new YamlScalar.internal(n, scalar.span, scalar.style); + } + + match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(scalar.value); + if (match != null) { + return new YamlScalar.internal( + int.parse(match.group(0)), scalar.span, scalar.style); + } + + return null; + } + + /// Parses a floating-point scalar. + YamlScalar _parseFloat(ScalarEvent scalar) { + var match = new RegExp( + r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"). + firstMatch(scalar.value); + if (match != null) { + // YAML allows floats of the form "0.", but Dart does not. Fix up those + // floats by removing the trailing dot. + var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), ""); + return new YamlScalar.internal( + double.parse(matchStr), scalar.span, scalar.style); + } + + match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(scalar.value); + if (match != null) { + var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; + return new YamlScalar.internal(value, scalar.span, scalar.style); + } + + match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(scalar.value); + if (match != null) { + return new YamlScalar.internal(double.NAN, scalar.span, scalar.style); + } + + return null; + } + + /// Parses a string scalar. + YamlScalar _parseString(ScalarEvent scalar) => + new YamlScalar.internal(scalar.value, scalar.span, scalar.style); +} diff --git a/pkgs/yaml/lib/src/model.dart b/pkgs/yaml/lib/src/model.dart deleted file mode 100644 index 93cb49c7a..000000000 --- a/pkgs/yaml/lib/src/model.dart +++ /dev/null @@ -1,259 +0,0 @@ -// 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. - -/// This file contains the node classes for the internal representations of YAML -/// documents. These nodes are used for both the serialization tree and the -/// representation graph. -library yaml.model; - -import 'package:source_span/source_span.dart'; - -import 'equality.dart'; -import 'parser.dart'; -import 'visitor.dart'; -import 'yaml_exception.dart'; - -/// The prefix for tag types defined by the YAML spec. -const _YAML_URI_PREFIX = "tag:yaml.org,2002:"; - -/// A tag that indicates the type of a YAML node. -class Tag { - /// The name of the tag, either a URI or a local tag beginning with "!". - final String name; - - /// The kind of the tag. - final TagKind kind; - - /// Returns the standard YAML tag URI for [type]. - static String yaml(String type) => "tag:yaml.org,2002:$type"; - - const Tag(this.name, this.kind); - - const Tag.scalar(String name) - : this(name, TagKind.SCALAR); - - const Tag.sequence(String name) - : this(name, TagKind.SEQUENCE); - - const Tag.mapping(String name) - : this(name, TagKind.MAPPING); - - /// Two tags are equal if their URIs are equal. - operator ==(other) { - if (other is! Tag) return false; - return name == other.name; - } - - String toString() { - if (name.startsWith(_YAML_URI_PREFIX)) { - return '!!${name.substring(_YAML_URI_PREFIX.length)}'; - } else { - return '!<$name>'; - } - } - - int get hashCode => name.hashCode; -} - -/// An enum for kinds of tags. -class TagKind { - /// A tag indicating that the value is a scalar. - static const SCALAR = const TagKind._("scalar"); - - /// A tag indicating that the value is a sequence. - static const SEQUENCE = const TagKind._("sequence"); - - /// A tag indicating that the value is a mapping. - static const MAPPING = const TagKind._("mapping"); - - final String name; - - const TagKind._(this.name); - - String toString() => name; -} - -/// The abstract class for YAML nodes. -abstract class Node { - /// Every YAML node has a tag that describes its type. - Tag tag; - - /// Any YAML node can have an anchor associated with it. - String anchor; - - /// The source span for this node. - SourceSpan span; - - Node(this.tag, this.span, [this.anchor]); - - bool operator ==(other) { - if (other is! Node) return false; - return tag == other.tag; - } - - int get hashCode => tag.hashCode ^ anchor.hashCode; - - visit(Visitor v); -} - -/// A sequence node represents an ordered list of nodes. -class SequenceNode extends Node { - /// The nodes in the sequence. - List content; - - SequenceNode(String tagName, this.content, SourceSpan span) - : super(new Tag.sequence(tagName), span); - - /// Two sequences are equal if their tags and contents are equal. - bool operator ==(other) { - // Should be super != other; bug 2554 - if (!(super == other) || other is! SequenceNode) return false; - if (content.length != other.content.length) return false; - for (var i = 0; i < content.length; i++) { - if (content[i] != other.content[i]) return false; - } - return true; - } - - String toString() => '$tag [${content.map((e) => '$e').join(', ')}]'; - - int get hashCode => super.hashCode ^ deepHashCode(content); - - visit(Visitor v) => v.visitSequence(this); -} - -/// An alias node is a reference to an anchor. -class AliasNode extends Node { - AliasNode(String anchor, SourceSpan span) - : super(new Tag.scalar(Tag.yaml("str")), span, anchor); - - visit(Visitor v) => v.visitAlias(this); -} - -/// A scalar node represents all YAML nodes that have a single value. -class ScalarNode extends Node { - /// The string value of the scalar node, if it was created by the parser. - final String _content; - - /// The Dart value of the scalar node, if it was created by the composer. - final value; - - /// Creates a new Scalar node. - /// - /// Exactly one of [content] and [value] should be specified. Content should - /// be specified for a newly-parsed scalar that hasn't yet been composed. - /// Value should be specified for a composed scalar, although `null` is a - /// valid value. - ScalarNode(String tagName, SourceSpan span, {String content, this.value}) - : _content = content, - super(new Tag.scalar(tagName), span); - - /// Two scalars are equal if their string representations are equal. - bool operator ==(other) { - // Should be super != other; bug 2554 - if (!(super == other) || other is! ScalarNode) return false; - return content == other.content; - } - - /// Returns the string representation of the scalar. After composition, this - /// is equal to the canonical serialization of the value of the scalar. - String get content => _content != null ? _content : canonicalContent; - - /// Returns the canonical serialization of the value of the scalar. If the - /// value isn't given, the result of this will be "null". - String get canonicalContent { - if (value == null || value is bool || value is int) return '$value'; - - if (value is num) { - // 20 is the maximum value for this argument, which we use since YAML - // doesn't specify a maximum. - return value.toStringAsExponential(20). - replaceFirst(new RegExp("0+e"), "e"); - } - - if (value is String) { - // TODO(nweiz): This could be faster if we used a RegExp to check for - // special characters and short-circuited if they didn't exist. - - var escapedValue = value.codeUnits.map((c) { - switch (c) { - case Parser.TAB: return "\\t"; - case Parser.LF: return "\\n"; - case Parser.CR: return "\\r"; - case Parser.DOUBLE_QUOTE: return '\\"'; - case Parser.NULL: return "\\0"; - case Parser.BELL: return "\\a"; - case Parser.BACKSPACE: return "\\b"; - case Parser.VERTICAL_TAB: return "\\v"; - case Parser.FORM_FEED: return "\\f"; - case Parser.ESCAPE: return "\\e"; - case Parser.BACKSLASH: return "\\\\"; - case Parser.NEL: return "\\N"; - case Parser.NBSP: return "\\_"; - case Parser.LINE_SEPARATOR: return "\\L"; - case Parser.PARAGRAPH_SEPARATOR: return "\\P"; - default: - if (c < 0x20 || (c >= 0x7f && c < 0x100)) { - return "\\x${zeroPad(c.toRadixString(16).toUpperCase(), 2)}"; - } else if (c >= 0x100 && c < 0x10000) { - return "\\u${zeroPad(c.toRadixString(16).toUpperCase(), 4)}"; - } else if (c >= 0x10000) { - return "\\u${zeroPad(c.toRadixString(16).toUpperCase(), 8)}"; - } else { - return new String.fromCharCodes([c]); - } - } - }); - return '"${escapedValue.join()}"'; - } - - throw new YamlException('Unknown scalar value.', span); - } - - String toString() => '$tag "$content"'; - - /// Left-pads [str] with zeros so that it's at least [length] characters - /// long. - String zeroPad(String str, int length) { - assert(length >= str.length); - var prefix = new List.filled(length - str.length, '0'); - return '${prefix.join()}$str'; - } - - int get hashCode => super.hashCode ^ content.hashCode; - - visit(Visitor v) => v.visitScalar(this); -} - -/// A mapping node represents an unordered map of nodes to nodes. -class MappingNode extends Node { - /// The node map. - Map content; - - MappingNode(String tagName, this.content, SourceSpan span) - : super(new Tag.mapping(tagName), span); - - /// Two mappings are equal if their tags and contents are equal. - bool operator ==(other) { - // Should be super != other; bug 2554 - if (!(super == other) || other is! MappingNode) return false; - if (content.length != other.content.length) return false; - for (var key in content.keys) { - if (!other.content.containsKey(key)) return false; - if (content[key] != other.content[key]) return false; - } - return true; - } - - String toString() { - var strContent = content.keys - .map((k) => '${k}: ${content[k]}') - .join(', '); - return '$tag {$strContent}'; - } - - int get hashCode => super.hashCode ^ deepHashCode(content); - - visit(Visitor v) => v.visitMapping(this); -} diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 94f551f21..72c01dcf0 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -1,1900 +1,817 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, 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 yaml.parser; -import 'dart:collection'; - import 'package:source_span/source_span.dart'; import 'package:string_scanner/string_scanner.dart'; -import 'equality.dart'; -import 'model.dart'; +import 'event.dart'; +import 'scanner.dart'; +import 'style.dart'; +import 'token.dart'; import 'utils.dart'; +import 'yaml_document.dart'; +import 'yaml_exception.dart'; -/// Translates a string of characters into a YAML serialization tree. -/// -/// This parser is designed to closely follow the spec. All productions in the -/// spec are numbered, and the corresponding methods in the parser have the same -/// numbers. This is certainly not the most efficient way of parsing YAML, but -/// it is the easiest to write and read in the context of the spec. +/// A parser that reads [Token]s emitted by a [Scanner] and emits [Event]s. /// -/// Methods corresponding to productions are also named as in the spec, -/// translating the name of the method (although not the annotation characters) -/// into camel-case for dart style.. For example, the spec has a production -/// named `nb-ns-plain-in-line`, and the method implementing it is named -/// `nb_ns_plainInLine`. The exception to that rule is methods that just -/// recognize character classes; these are named `is*`. +/// This is based on the libyaml parser, available at +/// https://github.com/yaml/libyaml/blob/master/src/parser.c. The license for +/// that is available in ../../libyaml-license.txt. class Parser { - static const TAB = 0x9; - static const LF = 0xA; - static const CR = 0xD; - static const SP = 0x20; - static const TILDE = 0x7E; - static const NEL = 0x85; - static const PLUS = 0x2B; - static const HYPHEN = 0x2D; - static const QUESTION_MARK = 0x3F; - static const COLON = 0x3A; - static const COMMA = 0x2C; - static const LEFT_BRACKET = 0x5B; - static const RIGHT_BRACKET = 0x5D; - static const LEFT_BRACE = 0x7B; - static const RIGHT_BRACE = 0x7D; - static const HASH = 0x23; - static const AMPERSAND = 0x26; - static const ASTERISK = 0x2A; - static const EXCLAMATION = 0x21; - static const VERTICAL_BAR = 0x7C; - static const GREATER_THAN = 0x3E; - static const SINGLE_QUOTE = 0x27; - static const DOUBLE_QUOTE = 0x22; - static const PERCENT = 0x25; - static const AT = 0x40; - static const GRAVE_ACCENT = 0x60; - - static const NULL = 0x0; - static const BELL = 0x7; - static const BACKSPACE = 0x8; - static const VERTICAL_TAB = 0xB; - static const FORM_FEED = 0xC; - static const ESCAPE = 0x1B; - static const SLASH = 0x2F; - static const BACKSLASH = 0x5C; - static const UNDERSCORE = 0x5F; - static const NBSP = 0xA0; - static const LINE_SEPARATOR = 0x2028; - static const PARAGRAPH_SEPARATOR = 0x2029; - - static const NUMBER_0 = 0x30; - static const NUMBER_9 = 0x39; - - static const LETTER_A = 0x61; - static const LETTER_B = 0x62; - static const LETTER_E = 0x65; - static const LETTER_F = 0x66; - static const LETTER_N = 0x6E; - static const LETTER_R = 0x72; - static const LETTER_T = 0x74; - static const LETTER_U = 0x75; - static const LETTER_V = 0x76; - static const LETTER_X = 0x78; - - static const LETTER_CAP_A = 0x41; - static const LETTER_CAP_F = 0x46; - static const LETTER_CAP_L = 0x4C; - static const LETTER_CAP_N = 0x4E; - static const LETTER_CAP_P = 0x50; - static const LETTER_CAP_U = 0x55; - static const LETTER_CAP_X = 0x58; - - static const C_SEQUENCE_ENTRY = 4; - static const C_MAPPING_KEY = 5; - static const C_MAPPING_VALUE = 6; - static const C_COLLECT_ENTRY = 7; - static const C_SEQUENCE_START = 8; - static const C_SEQUENCE_END = 9; - static const C_MAPPING_START = 10; - static const C_MAPPING_END = 11; - static const C_COMMENT = 12; - static const C_ANCHOR = 13; - static const C_ALIAS = 14; - static const C_TAG = 15; - static const C_LITERAL = 16; - static const C_FOLDED = 17; - static const C_SINGLE_QUOTE = 18; - static const C_DOUBLE_QUOTE = 19; - static const C_DIRECTIVE = 20; - static const C_RESERVED = 21; - - static const BLOCK_OUT = 0; - static const BLOCK_IN = 1; - static const FLOW_OUT = 2; - static const FLOW_IN = 3; - static const BLOCK_KEY = 4; - static const FLOW_KEY = 5; - - static const CHOMPING_STRIP = 0; - static const CHOMPING_KEEP = 1; - static const CHOMPING_CLIP = 2; - - /// The scanner that's used to scan through the document. - final SpanScanner _scanner; - - /// Whether we're parsing a bare document (that is, one that doesn't begin - /// with `---`). Bare documents don't allow `%` immediately following - /// newlines. - bool _inBareDocument = false; - - /// The state of the scanner when it was the farthest in the document it's - /// been. - LineScannerState _farthestState; - - /// The name of the context of the farthest position that has been parsed - /// successfully before backtracking. Used for error reporting. - String _farthestContext = "document"; - - /// A stack of the names of parse contexts. Used for error reporting. - final _contextStack = ["document"]; - - /// Annotations attached to ranges of the source string that add extra - /// information to any errors that occur in the annotated range. - final _errorAnnotations = new _RangeMap(); - - /// The buffer containing the string currently being captured. - StringBuffer _capturedString; - - /// The beginning of the current section of the captured string. - int _captureStart; - - /// Whether the current string capture is being overridden. - bool _capturingAs = false; - - Parser(String yaml, sourceUrl) - : _scanner = new SpanScanner(yaml, sourceUrl: sourceUrl) { - _farthestState = _scanner.state; - } + /// The underlying [Scanner] that generates [Token]s. + final Scanner _scanner; - /// Returns the character at the current position, then moves that position - /// forward one character. - int next() => _scanner.readChar(); + /// The stack of parse states for nested contexts. + final _states = new List<_State>(); - /// Returns the code unit at the current position, or the character [i] - /// characters after the current position. - int peek([int i = 0]) => _scanner.peekChar(i); + /// The current parse state. + var _state = _State.STREAM_START; - /// The truthiness operator. Returns `false` if [obj] is `null` or `false`, - /// `true` otherwise. - bool truth(obj) => obj != null && obj != false; - - /// Consumes the current character if it matches [matcher]. Returns the result - /// of [matcher]. - bool consume(bool matcher(int)) { - if (matcher(peek())) { - next(); - return true; - } - return false; - } + /// The custom tag directives, by tag handle. + final _tagDirectives = new Map(); - /// Consumes the current character if it equals [char]. - bool consumeChar(int char) => consume((c) => c == char); + /// Whether the parser has finished parsing. + bool get isDone => _state == _State.END; - /// Calls [consumer] until it returns a falsey value. Returns a list of all - /// truthy return values of [consumer], or null if it didn't consume anything. + /// Creates a parser that parses [source]. /// - /// Conceptually, repeats a production one or more times. - List oneOrMore(consumer()) { - var first = consumer(); - if (!truth(first)) return null; - var out = [first]; - while (true) { - var el = consumer(); - if (!truth(el)) return out; - out.add(el); - } - return null; // Unreachable. - } + /// [sourceUrl] can be a String or a [Uri]. + Parser(String source, {sourceUrl}) + : _scanner = new Scanner(source, sourceUrl: sourceUrl); - /// Calls [consumer] until it returns a falsey value. Returns a list of all - /// truthy return values of [consumer], or the empty list if it didn't consume - /// anything. - /// - /// Conceptually, repeats a production any number of times. - List zeroOrMore(consumer()) { - var out = []; - var oldPos = _scanner.position; - while (true) { - var el = consumer(); - if (!truth(el) || oldPos == _scanner.position) return out; - oldPos = _scanner.position; - out.add(el); + /// Consumes and returns the next event. + Event parse() { + try { + if (isDone) throw new StateError("No more events."); + var event = _stateMachine(); + return event; + } on StringScannerException catch (error) { + throw new YamlException(error.message, error.span); } - return null; // Unreachable. } - /// Just calls [consumer] and returns its result. Used to make it explicit - /// that a production is intended to be optional. - zeroOrOne(consumer()) => consumer(); - - /// Calls each function in [consumers] until one returns a truthy value, then - /// returns that. - or(List consumers) { - for (var c in consumers) { - var res = c(); - if (truth(res)) return res; + /// Dispatches parsing based on the current state. + Event _stateMachine() { + switch (_state) { + case _State.STREAM_START: + return _parseStreamStart(); + case _State.DOCUMENT_START: + return _parseDocumentStart(); + case _State.DOCUMENT_CONTENT: + return _parseDocumentContent(); + case _State.DOCUMENT_END: + return _parseDocumentEnd(); + case _State.BLOCK_NODE: + return _parseNode(block: true); + case _State.BLOCK_NODE_OR_INDENTLESS_SEQUENCE: + return _parseNode(block: true, indentlessSequence: true); + case _State.FLOW_NODE: + return _parseNode(); + case _State.BLOCK_SEQUENCE_FIRST_ENTRY: + // Scan past the `BLOCK-SEQUENCE-FIRST-ENTRY` token to the + // `BLOCK-SEQUENCE-ENTRY` token. + _scanner.scan(); + return _parseBlockSequenceEntry(); + case _State.BLOCK_SEQUENCE_ENTRY: + return _parseBlockSequenceEntry(); + case _State.INDENTLESS_SEQUENCE_ENTRY: + return _parseIndentlessSequenceEntry(); + case _State.BLOCK_MAPPING_FIRST_KEY: + // Scan past the `BLOCK-MAPPING-FIRST-KEY` token to the + // `BLOCK-MAPPING-KEY` token. + _scanner.scan(); + return _parseBlockMappingKey(); + case _State.BLOCK_MAPPING_KEY: + return _parseBlockMappingKey(); + case _State.BLOCK_MAPPING_VALUE: + return _parseBlockMappingValue(); + case _State.FLOW_SEQUENCE_FIRST_ENTRY: + return _parseFlowSequenceEntry(first: true); + case _State.FLOW_SEQUENCE_ENTRY: + return _parseFlowSequenceEntry(); + case _State.FLOW_SEQUENCE_ENTRY_MAPPING_KEY: + return _parseFlowSequenceEntryMappingKey(); + case _State.FLOW_SEQUENCE_ENTRY_MAPPING_VALUE: + return _parseFlowSequenceEntryMappingValue(); + case _State.FLOW_SEQUENCE_ENTRY_MAPPING_END: + return _parseFlowSequenceEntryMappingEnd(); + case _State.FLOW_MAPPING_FIRST_KEY: + return _parseFlowMappingKey(first: true); + case _State.FLOW_MAPPING_KEY: + return _parseFlowMappingKey(); + case _State.FLOW_MAPPING_VALUE: + return _parseFlowMappingValue(); + case _State.FLOW_MAPPING_EMPTY_VALUE: + return _parseFlowMappingValue(empty: true); + default: + throw "Unreachable"; } - return null; } - /// Calls [consumer] and returns its result, but rolls back the parser state - /// if [consumer] returns a falsey value. - transaction(consumer()) { - var oldState = _scanner.state; - var oldCaptureStart = _captureStart; - String capturedSoFar = _capturedString == null ? null : - _capturedString.toString(); - var res = consumer(); - _refreshFarthestState(); - if (truth(res)) return res; - - _scanner.state = oldState; - _captureStart = oldCaptureStart; - _capturedString = capturedSoFar == null ? null : - new StringBuffer(capturedSoFar); - return res; + /// Parses the production: + /// + /// stream ::= + /// STREAM-START implicit_document? explicit_document* STREAM-END + /// ************ + Event _parseStreamStart() { + var token = _scanner.scan(); + assert(token.type == TokenType.STREAM_START); + + _state = _State.DOCUMENT_START; + return new Event(EventType.STREAM_START, token.span); } - /// Consumes [n] characters matching [matcher], or none if there isn't a - /// complete match. The first argument to [matcher] is the character code, the - /// second is the index (from 0 to [n] - 1). + /// Parses the productions: /// - /// Returns whether or not the characters were consumed. - bool nAtOnce(int n, bool matcher(int c, int i)) => transaction(() { - for (int i = 0; i < n; i++) { - if (!consume((c) => matcher(c, i))) return false; + /// implicit_document ::= block_node DOCUMENT-END* + /// * + /// explicit_document ::= + /// DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* + /// ************************* + Event _parseDocumentStart() { + var token = _scanner.peek(); + + // libyaml requires any document beyond the first in the stream to have an + // explicit document start indicator, but the spec allows it to be omitted + // as long as there was an end indicator. + + // Parse extra document end indicators. + while (token.type == TokenType.DOCUMENT_END) { + token = _scanner.advance(); } - return true; - }); - /// Consumes the exact characters in [str], or nothing. - /// - /// Returns whether or not the string was consumed. - bool rawString(String str) => - nAtOnce(str.length, (c, i) => str.codeUnitAt(i) == c); - - /// Consumes and returns a string of characters matching [matcher], or null if - /// there are no such characters. - String stringOf(bool matcher(int)) => - captureString(() => oneOrMore(() => consume(matcher))); - - /// Calls [consumer] and returns the string that was consumed while doing so, - /// or null if [consumer] returned a falsey value. Automatically wraps - /// [consumer] in `transaction`. - String captureString(consumer()) { - // captureString calls may not be nested - assert(_capturedString == null); - - _captureStart = _scanner.position; - _capturedString = new StringBuffer(); - var res = transaction(consumer); - if (!truth(res)) { - _captureStart = null; - _capturedString = null; - return null; + if (token.type != TokenType.VERSION_DIRECTIVE && + token.type != TokenType.TAG_DIRECTIVE && + token.type != TokenType.DOCUMENT_START && + token.type != TokenType.STREAM_END) { + // Parse an implicit document. + _processDirectives(); + _states.add(_State.DOCUMENT_END); + _state = _State.BLOCK_NODE; + return new DocumentStartEvent(token.span.start.pointSpan()); } - flushCapture(); - var result = _capturedString.toString(); - _captureStart = null; - _capturedString = null; - return result; - } - - captureAs(String replacement, consumer()) => - captureAndTransform(consumer, (_) => replacement); - - captureAndTransform(consumer(), String transformation(String captured)) { - if (_capturedString == null) return consumer(); - if (_capturingAs) return consumer(); - - flushCapture(); - _capturingAs = true; - var res = consumer(); - _capturingAs = false; - if (!truth(res)) return res; - - _capturedString.write(transformation( - _scanner.string.substring(_captureStart, _scanner.position))); - _captureStart = _scanner.position; - return res; - } - - void flushCapture() { - _capturedString.write(_scanner.string.substring( - _captureStart, _scanner.position)); - _captureStart = _scanner.position; - } - - /// Adds a tag and an anchor to [node], if they're defined. - Node addProps(Node node, Pair props) { - if (props == null || node == null) return node; - if (truth(props.first)) node.tag = props.first; - if (truth(props.last)) node.anchor = props.last; - return node; - } - - /// Creates a MappingNode from [pairs]. - MappingNode map(List> pairs, SourceSpan span) { - var content = new Map(); - pairs.forEach((pair) => content[pair.first] = pair.last); - return new MappingNode("?", content, span); - } - - /// Runs [fn] in a context named [name]. Used for error reporting. - context(String name, fn()) { - try { - _contextStack.add(name); - return fn(); - } finally { - var popped = _contextStack.removeLast(); - assert(popped == name); + if (token.type == TokenType.STREAM_END) { + _state = _State.END; + _scanner.scan(); + return new Event(EventType.STREAM_END, token.span); } - } - /// Adds [message] as extra information to any errors that occur between the - /// current position and the position of the cursor after running [fn]. The - /// cursor is reset after [fn] is run. - annotateError(String message, fn()) { - var start = _scanner.position; - var end; - transaction(() { - fn(); - end = _scanner.position; - return false; - }); - _errorAnnotations[new _Range(start, end)] = message; - } - - /// Throws an error with additional context information. - void error(String message) => - _scanner.error("$message (in $_farthestContext)."); + // Parse an explicit document. + var start = token.span; + var pair = _processDirectives(); + var versionDirective = pair.first; + var tagDirectives = pair.last; + token = _scanner.peek(); + if (token.type != TokenType.DOCUMENT_START) { + throw new YamlException("Expected document start.", token.span); + } - /// If [result] is falsey, throws an error saying that [expected] was - /// expected. - expect(result, String expected) { - if (truth(result)) return result; - error("Expected $expected"); + _states.add(_State.DOCUMENT_END); + _state = _State.DOCUMENT_CONTENT; + _scanner.scan(); + return new DocumentStartEvent(start.expand(token.span), + versionDirective: versionDirective, + tagDirectives: tagDirectives, + isImplicit: false); } - /// Throws an error saying that the parse failed. + /// Parses the productions: /// - /// Uses [_farthestState] and [_farthestContext] to provide additional - /// information. - parseFailed() { - var message = "Invalid YAML in $_farthestContext"; - _refreshFarthestState(); - _scanner.state = _farthestState; - - var extraError = _errorAnnotations[_scanner.position]; - if (extraError != null) message = "$message ($extraError)"; - _scanner.error("$message."); - } - - /// Update [_farthestState] if the scanner is farther than it's been before. - void _refreshFarthestState() { - if (_scanner.position <= _farthestState.position) return; - _farthestState = _scanner.state; - } - - /// Returns the number of spaces after the current position. - int countIndentation() { - var i = 0; - while (peek(i) == SP) i++; - return i; - } - - /// Returns the indentation for a block scalar. - int blockScalarAdditionalIndentation(_BlockHeader header, int indent) { - if (!header.autoDetectIndent) return header.additionalIndent; - - var maxSpaces = 0; - var spaces = 0; - transaction(() { - do { - spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length; - if (spaces > maxSpaces) maxSpaces = spaces; - } while (b_break()); - return false; - }); - - // If the next non-empty line isn't indented further than the start of the - // block scalar, that means the scalar is going to be empty. Returning any - // value > 0 will cause the parser not to consume any text. - if (spaces <= indent) return 1; - - // It's an error for a leading empty line to be indented more than the first - // non-empty line. - if (maxSpaces > spaces) { - _scanner.error("Leading empty lines may not be indented more than the " - "first non-empty line."); + /// explicit_document ::= + /// DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* + /// *********** + Event _parseDocumentContent() { + var token = _scanner.peek(); + + switch (token.type) { + case TokenType.VERSION_DIRECTIVE: + case TokenType.TAG_DIRECTIVE: + case TokenType.DOCUMENT_START: + case TokenType.DOCUMENT_END: + case TokenType.STREAM_END: + _state = _states.removeLast(); + return _processEmptyScalar(token.span.start); + default: + return _parseNode(block: true); } - - return spaces - indent; } - /// Returns whether the current position is at the beginning of a line. - bool get atStartOfLine => _scanner.column == 0; - - /// Given an indicator character, returns the type of that indicator (or null - /// if the indicator isn't found. - int indicatorType(int char) { - switch (char) { - case HYPHEN: return C_SEQUENCE_ENTRY; - case QUESTION_MARK: return C_MAPPING_KEY; - case COLON: return C_MAPPING_VALUE; - case COMMA: return C_COLLECT_ENTRY; - case LEFT_BRACKET: return C_SEQUENCE_START; - case RIGHT_BRACKET: return C_SEQUENCE_END; - case LEFT_BRACE: return C_MAPPING_START; - case RIGHT_BRACE: return C_MAPPING_END; - case HASH: return C_COMMENT; - case AMPERSAND: return C_ANCHOR; - case ASTERISK: return C_ALIAS; - case EXCLAMATION: return C_TAG; - case VERTICAL_BAR: return C_LITERAL; - case GREATER_THAN: return C_FOLDED; - case SINGLE_QUOTE: return C_SINGLE_QUOTE; - case DOUBLE_QUOTE: return C_DOUBLE_QUOTE; - case PERCENT: return C_DIRECTIVE; - case AT: - case GRAVE_ACCENT: - return C_RESERVED; - default: return null; + /// Parses the productions: + /// + /// implicit_document ::= block_node DOCUMENT-END* + /// ************* + /// explicit_document ::= + /// DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* + /// ************* + Event _parseDocumentEnd() { + _tagDirectives.clear(); + _state = _State.DOCUMENT_START; + + var token = _scanner.peek(); + if (token.type == TokenType.DOCUMENT_END) { + _scanner.scan(); + return new DocumentEndEvent(token.span, isImplicit: false); + } else { + return new DocumentEndEvent( + token.span.start.pointSpan(), isImplicit: true); } } - // 1 - bool isPrintable(int char) { - if (char == null) return false; - return char == TAB || - char == LF || - char == CR || - (char >= SP && char <= TILDE) || - char == NEL || - (char >= 0xA0 && char <= 0xD7FF) || - (char >= 0xE000 && char <= 0xFFFD) || - (char >= 0x10000 && char <= 0x10FFFF); - } - - // 2 - bool isJson(int char) => char != null && - (char == TAB || (char >= SP && char <= 0x10FFFF)); - - // 22 - bool c_indicator(int type) => consume((c) => indicatorType(c) == type); - - // 23 - bool isFlowIndicator(int char) { - var indicator = indicatorType(char); - return indicator == C_COLLECT_ENTRY || - indicator == C_SEQUENCE_START || - indicator == C_SEQUENCE_END || - indicator == C_MAPPING_START || - indicator == C_MAPPING_END; - } - - // 26 - bool isBreak(int char) => char == LF || char == CR; - - // 27 - bool isNonBreak(int char) => isPrintable(char) && !isBreak(char); - - // 28 - bool b_break() { - if (consumeChar(CR)) { - zeroOrOne(() => consumeChar(LF)); - return true; + /// Parses the productions: + /// + /// block_node_or_indentless_sequence ::= + /// ALIAS + /// ***** + /// | properties (block_content | indentless_block_sequence)? + /// ********** * + /// | block_content | indentless_block_sequence + /// * + /// block_node ::= ALIAS + /// ***** + /// | properties block_content? + /// ********** * + /// | block_content + /// * + /// flow_node ::= ALIAS + /// ***** + /// | properties flow_content? + /// ********** * + /// | flow_content + /// * + /// properties ::= TAG ANCHOR? | ANCHOR TAG? + /// ************************* + /// block_content ::= block_collection | flow_collection | SCALAR + /// ****** + /// flow_content ::= flow_collection | SCALAR + /// ****** + Event _parseNode({bool block: false, bool indentlessSequence: false}) { + var token = _scanner.peek(); + + if (token is AliasToken) { + _scanner.scan(); + _state = _states.removeLast(); + return new AliasEvent(token.span, token.name); } - return consumeChar(LF); - } - - // 29 - bool b_asLineFeed() => captureAs("\n", () => b_break()); - - // 30 - bool b_nonContent() => captureAs("", () => b_break()); - - // 33 - bool isSpace(int char) => char == SP || char == TAB; - - // 34 - bool isNonSpace(int char) => isNonBreak(char) && !isSpace(char); - - // 35 - bool isDecDigit(int char) => char != null && char >= NUMBER_0 && - char <= NUMBER_9; - - // 36 - bool isHexDigit(int char) { - if (char == null) return false; - return isDecDigit(char) || - (char >= LETTER_A && char <= LETTER_F) || - (char >= LETTER_CAP_A && char <= LETTER_CAP_F); - } - - // 41 - bool c_escape() => captureAs("", () => consumeChar(BACKSLASH)); - - // 42 - bool ns_escNull() => captureAs("\x00", () => consumeChar(NUMBER_0)); - - // 43 - bool ns_escBell() => captureAs("\x07", () => consumeChar(LETTER_A)); - - // 44 - bool ns_escBackspace() => captureAs("\b", () => consumeChar(LETTER_B)); - - // 45 - bool ns_escHorizontalTab() => captureAs("\t", () { - return consume((c) => c == LETTER_T || c == TAB); - }); - - // 46 - bool ns_escLineFeed() => captureAs("\n", () => consumeChar(LETTER_N)); - - // 47 - bool ns_escVerticalTab() => captureAs("\v", () => consumeChar(LETTER_V)); - - // 48 - bool ns_escFormFeed() => captureAs("\f", () => consumeChar(LETTER_F)); - - // 49 - bool ns_escCarriageReturn() => captureAs("\r", () => consumeChar(LETTER_R)); - - // 50 - bool ns_escEscape() => captureAs("\x1B", () => consumeChar(LETTER_E)); - - // 51 - bool ns_escSpace() => consumeChar(SP); - - // 52 - bool ns_escDoubleQuote() => consumeChar(DOUBLE_QUOTE); - - // 53 - bool ns_escSlash() => consumeChar(SLASH); - - // 54 - bool ns_escBackslash() => consumeChar(BACKSLASH); - // 55 - bool ns_escNextLine() => captureAs("\x85", () => consumeChar(LETTER_CAP_N)); - - // 56 - bool ns_escNonBreakingSpace() => - captureAs("\xA0", () => consumeChar(UNDERSCORE)); - - // 57 - bool ns_escLineSeparator() => - captureAs("\u2028", () => consumeChar(LETTER_CAP_L)); - - // 58 - bool ns_escParagraphSeparator() => - captureAs("\u2029", () => consumeChar(LETTER_CAP_P)); - - // 59 - bool ns_esc8Bit() => ns_escNBit(LETTER_X, 2); - - // 60 - bool ns_esc16Bit() => ns_escNBit(LETTER_U, 4); - - // 61 - bool ns_esc32Bit() => ns_escNBit(LETTER_CAP_U, 8); + var anchor; + var tagToken; + var span = token.span.start.pointSpan(); + parseAnchor() { + anchor = token.name; + span = span.expand(token.span); + token = _scanner.advance(); + } - // Helper method for 59 - 61 - bool ns_escNBit(int char, int digits) { - if (!captureAs('', () => consumeChar(char))) return false; - var captured = captureAndTransform( - () => nAtOnce(digits, (c, _) => isHexDigit(c)), - (hex) => new String.fromCharCodes([int.parse("0x$hex")])); - return expect(captured, "$digits hexidecimal digits"); - } + parseTag() { + tagToken = token; + span = span.expand(token.span); + token = _scanner.advance(); + } - // 62 - bool c_ns_escChar() => context('escape sequence', () => transaction(() { - if (!truth(c_escape())) return false; - return truth(or([ - ns_escNull, ns_escBell, ns_escBackspace, ns_escHorizontalTab, - ns_escLineFeed, ns_escVerticalTab, ns_escFormFeed, ns_escCarriageReturn, - ns_escEscape, ns_escSpace, ns_escDoubleQuote, ns_escSlash, - ns_escBackslash, ns_escNextLine, ns_escNonBreakingSpace, - ns_escLineSeparator, ns_escParagraphSeparator, ns_esc8Bit, ns_esc16Bit, - ns_esc32Bit - ])); - })); - - // 63 - bool s_indent(int indent) { - var result = nAtOnce(indent, (c, i) => c == SP); - if (peek() == TAB) { - annotateError("tab characters are not allowed as indentation in YAML", - () => zeroOrMore(() => consume(isSpace))); + if (token is AnchorToken) { + parseAnchor(); + if (token is TagToken) parseTag(); + } else if (token is TagToken) { + parseTag(); + if (token is AnchorToken) parseAnchor(); } - return result; - } - // 64 - bool s_indentLessThan(int indent) { - for (int i = 0; i < indent - 1; i++) { - if (!consumeChar(SP)) { - if (peek() == TAB) { - annotateError("tab characters are not allowed as indentation in YAML", - () { - for (; i < indent - 1; i++) { - if (!consume(isSpace)) break; - } - }); + var tag; + if (tagToken != null) { + if (tagToken.handle == null) { + tag = tagToken.suffix; + } else { + var tagDirective = _tagDirectives[tagToken.handle]; + if (tagDirective == null) { + throw new YamlException("Undefined tag handle.", tagToken.span); } - break; + + tag = tagDirective.prefix + tagToken.suffix; } } - return true; - } - // 65 - bool s_indentLessThanOrEqualTo(int indent) => s_indentLessThan(indent + 1); - - // 66 - bool s_separateInLine() => transaction(() { - return captureAs('', () => - truth(oneOrMore(() => consume(isSpace))) || atStartOfLine); - }); - - // 67 - bool s_linePrefix(int indent, int ctx) => captureAs("", () { - switch (ctx) { - case BLOCK_OUT: - case BLOCK_IN: - return s_blockLinePrefix(indent); - case FLOW_OUT: - case FLOW_IN: - return s_flowLinePrefix(indent); + if (indentlessSequence && token.type == TokenType.BLOCK_ENTRY) { + _state = _State.INDENTLESS_SEQUENCE_ENTRY; + return new SequenceStartEvent( + span.expand(token.span), CollectionStyle.BLOCK, + anchor: anchor, tag: tag); } - }); - - // 68 - bool s_blockLinePrefix(int indent) => s_indent(indent); - - // 69 - bool s_flowLinePrefix(int indent) => captureAs('', () { - if (!truth(s_indent(indent))) return false; - zeroOrOne(s_separateInLine); - return true; - }); - - // 70 - bool l_empty(int indent, int ctx) => transaction(() { - var start = or([ - () => s_linePrefix(indent, ctx), - () => s_indentLessThan(indent) - ]); - if (!truth(start)) return false; - return b_asLineFeed(); - }); - - // 71 - bool b_asSpace() => captureAs(" ", () => consume(isBreak)); - - // 72 - bool b_l_trimmed(int indent, int ctx) => transaction(() { - if (!truth(b_nonContent())) return false; - return truth(oneOrMore(() => captureAs("\n", () => l_empty(indent, ctx)))); - }); - - // 73 - bool b_l_folded(int indent, int ctx) => - or([() => b_l_trimmed(indent, ctx), b_asSpace]); - - // 74 - bool s_flowFolded(int indent) => transaction(() { - zeroOrOne(s_separateInLine); - if (!truth(b_l_folded(indent, FLOW_IN))) return false; - return s_flowLinePrefix(indent); - }); - - // 75 - bool c_nb_commentText() { - if (!truth(c_indicator(C_COMMENT))) return false; - zeroOrMore(() => consume(isNonBreak)); - return true; - } - // 76 - bool b_comment() => _scanner.isDone || b_nonContent(); + if (token is ScalarToken) { + // All non-plain scalars have the "!" tag by default. + if (tag == null && token.style != ScalarStyle.PLAIN) tag = "!"; - // 77 - bool s_b_comment() { - if (truth(s_separateInLine())) { - zeroOrOne(c_nb_commentText); + _state = _states.removeLast(); + _scanner.scan(); + return new ScalarEvent( + span.expand(token.span), token.value, token.style, + anchor: anchor, tag: tag); } - return b_comment(); - } - - // 78 - bool l_comment() => transaction(() { - if (!truth(s_separateInLine())) return false; - zeroOrOne(c_nb_commentText); - return b_comment(); - }); - - // 79 - bool s_l_comments() { - if (!truth(s_b_comment()) && !atStartOfLine) return false; - zeroOrMore(l_comment); - return true; - } - // 80 - bool s_separate(int indent, int ctx) { - switch (ctx) { - case BLOCK_OUT: - case BLOCK_IN: - case FLOW_OUT: - case FLOW_IN: - return s_separateLines(indent); - case BLOCK_KEY: - case FLOW_KEY: - return s_separateInLine(); - default: throw 'Invalid context "$ctx".'; + if (token.type == TokenType.FLOW_SEQUENCE_START) { + _state = _State.FLOW_SEQUENCE_FIRST_ENTRY; + return new SequenceStartEvent( + span.expand(token.span), CollectionStyle.FLOW, + anchor: anchor, tag: tag); } - } - - // 81 - bool s_separateLines(int indent) { - return transaction(() => s_l_comments() && s_flowLinePrefix(indent)) || - s_separateInLine(); - } - // 82 - bool l_directive() => false; // TODO(nweiz): implement - - // 96 - Pair c_ns_properties(int indent, int ctx) { - var tag, anchor; - tag = c_ns_tagProperty(); - if (truth(tag)) { - anchor = transaction(() { - if (!truth(s_separate(indent, ctx))) return null; - return c_ns_anchorProperty(); - }); - return new Pair(tag, anchor); + if (token.type == TokenType.FLOW_MAPPING_START) { + _state = _State.FLOW_MAPPING_FIRST_KEY; + return new MappingStartEvent( + span.expand(token.span), CollectionStyle.FLOW, + anchor: anchor, tag: tag); } - anchor = c_ns_anchorProperty(); - if (truth(anchor)) { - tag = transaction(() { - if (!truth(s_separate(indent, ctx))) return null; - return c_ns_tagProperty(); - }); - return new Pair(tag, anchor); + if (block && token.type == TokenType.BLOCK_SEQUENCE_START) { + _state = _State.BLOCK_SEQUENCE_FIRST_ENTRY; + return new SequenceStartEvent( + span.expand(token.span), CollectionStyle.BLOCK, + anchor: anchor, tag: tag); } - return null; - } - - // 97 - Tag c_ns_tagProperty() => null; // TODO(nweiz): implement - // 101 - String c_ns_anchorProperty() => null; // TODO(nweiz): implement - - // 102 - bool isAnchorChar(int char) => isNonSpace(char) && !isFlowIndicator(char); + if (block && token.type == TokenType.BLOCK_MAPPING_START) { + _state = _State.BLOCK_MAPPING_FIRST_KEY; + return new MappingStartEvent( + span.expand(token.span), CollectionStyle.BLOCK, + anchor: anchor, tag: tag); + } - // 103 - String ns_anchorName() => - captureString(() => oneOrMore(() => consume(isAnchorChar))); + if (anchor != null || tag != null) { + _state = _states.removeLast(); + return new ScalarEvent( + span, '', ScalarStyle.PLAIN, + anchor: anchor, tag: tag); + } - // 104 - Node c_ns_aliasNode() { - var start = _scanner.state; - if (!truth(c_indicator(C_ALIAS))) return null; - var name = expect(ns_anchorName(), 'anchor name'); - return new AliasNode(name, _scanner.spanFrom(start)); + throw new YamlException("Expected node content.", span); } - // 105 - ScalarNode e_scalar() => new ScalarNode("?", _scanner.emptySpan, content: ""); - - // 106 - ScalarNode e_node() => e_scalar(); - - // 107 - bool nb_doubleChar() => or([ - c_ns_escChar, - () => consume((c) => isJson(c) && c != BACKSLASH && c != DOUBLE_QUOTE) - ]); - - // 108 - bool ns_doubleChar() => !isSpace(peek()) && truth(nb_doubleChar()); - - // 109 - Node c_doubleQuoted(int indent, int ctx) => context('string', () { - return transaction(() { - var start = _scanner.state; - if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; - var contents = nb_doubleText(indent, ctx); - if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null; - return new ScalarNode("!", _scanner.spanFrom(start), content: contents); - }); - }); - - // 110 - String nb_doubleText(int indent, int ctx) => captureString(() { - switch (ctx) { - case FLOW_OUT: - case FLOW_IN: - nb_doubleMultiLine(indent); - break; - case BLOCK_KEY: - case FLOW_KEY: - nb_doubleOneLine(); - break; + /// Parses the productions: + /// + /// block_sequence ::= + /// BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END + /// ******************** *********** * ********* + Event _parseBlockSequenceEntry() { + var token = _scanner.peek(); + + if (token.type == TokenType.BLOCK_ENTRY) { + token = _scanner.advance(); + + if (token.type == TokenType.BLOCK_ENTRY || + token.type == TokenType.BLOCK_END) { + _state = _State.BLOCK_SEQUENCE_ENTRY; + return _processEmptyScalar(token.span.end); + } else { + _states.add(_State.BLOCK_SEQUENCE_ENTRY); + return _parseNode(block: true); + } } - return true; - }); - // 111 - void nb_doubleOneLine() { - zeroOrMore(nb_doubleChar); - } + if (token.type == TokenType.BLOCK_END) { + _scanner.scan(); + _state = _states.removeLast(); + return new Event(EventType.SEQUENCE_END, token.span); + } - // 112 - bool s_doubleEscaped(int indent) => transaction(() { - zeroOrMore(() => consume(isSpace)); - if (!captureAs("", () => consumeChar(BACKSLASH))) return false; - if (!truth(b_nonContent())) return false; - zeroOrMore(() => captureAs("\n", () => l_empty(indent, FLOW_IN))); - return s_flowLinePrefix(indent); - }); - - // 113 - bool s_doubleBreak(int indent) => or([ - () => s_doubleEscaped(indent), - () => s_flowFolded(indent) - ]); - - // 114 - void nb_ns_doubleInLine() { - zeroOrMore(() => transaction(() { - zeroOrMore(() => consume(isSpace)); - return ns_doubleChar(); - })); + throw new YamlException("While parsing a block collection, expected '-'.", + token.span.start.pointSpan()); } - // 115 - bool s_doubleNextLine(int indent) { - if (!truth(s_doubleBreak(indent))) return false; - zeroOrOne(() { - if (!truth(ns_doubleChar())) return; - nb_ns_doubleInLine(); - or([ - () => s_doubleNextLine(indent), - () => zeroOrMore(() => consume(isSpace)) - ]); - }); - return true; - } + /// Parses the productions: + /// + /// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ + /// *********** * + Event _parseIndentlessSequenceEntry() { + var token = _scanner.peek(); + + if (token.type != TokenType.BLOCK_ENTRY) { + _state = _states.removeLast(); + return new Event(EventType.SEQUENCE_END, token.span.start.pointSpan()); + } - // 116 - void nb_doubleMultiLine(int indent) { - nb_ns_doubleInLine(); - or([ - () => s_doubleNextLine(indent), - () => zeroOrMore(() => consume(isSpace)) - ]); + var start = token.span.start; + token = _scanner.advance(); + + if (token.type == TokenType.BLOCK_ENTRY || + token.type == TokenType.KEY || + token.type == TokenType.VALUE || + token.type == TokenType.BLOCK_END) { + _state = _State.INDENTLESS_SEQUENCE_ENTRY; + return _processEmptyScalar(start); + } else { + _states.add(_State.INDENTLESS_SEQUENCE_ENTRY); + return _parseNode(block: true); + } } - // 117 - bool c_quotedQuote() => captureAs("'", () => rawString("''")); - - // 118 - bool nb_singleChar() => or([ - c_quotedQuote, - () => consume((c) => isJson(c) && c != SINGLE_QUOTE) - ]); - - // 119 - bool ns_singleChar() => !isSpace(peek()) && truth(nb_singleChar()); - - // 120 - Node c_singleQuoted(int indent, int ctx) => context('string', () { - return transaction(() { - var start = _scanner.state; - if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; - var contents = nb_singleText(indent, ctx); - if (!truth(c_indicator(C_SINGLE_QUOTE))) return null; - return new ScalarNode("!", _scanner.spanFrom(start), content: contents); - }); - }); - - // 121 - String nb_singleText(int indent, int ctx) => captureString(() { - switch (ctx) { - case FLOW_OUT: - case FLOW_IN: - nb_singleMultiLine(indent); - break; - case BLOCK_KEY: - case FLOW_KEY: - nb_singleOneLine(indent); - break; + /// Parses the productions: + /// + /// block_mapping ::= BLOCK-MAPPING_START + /// ******************* + /// ((KEY block_node_or_indentless_sequence?)? + /// *** * + /// (VALUE block_node_or_indentless_sequence?)?)* + /// + /// BLOCK-END + /// ********* + Event _parseBlockMappingKey() { + var token = _scanner.peek(); + if (token.type == TokenType.KEY) { + var start = token.span.start; + token = _scanner.advance(); + + if (token.type == TokenType.KEY || + token.type == TokenType.VALUE || + token.type == TokenType.BLOCK_END) { + _state = _State.BLOCK_MAPPING_VALUE; + return _processEmptyScalar(start); + } else { + _states.add(_State.BLOCK_MAPPING_VALUE); + return _parseNode(block: true, indentlessSequence: true); + } } - return true; - }); - // 122 - void nb_singleOneLine(int indent) { - zeroOrMore(nb_singleChar); - } + // libyaml doesn't allow empty keys without an explicit key indicator, but + // the spec does. See example 8.18: + // http://yaml.org/spec/1.2/spec.html#id2798896. + if (token.type == TokenType.VALUE) { + _state = _State.BLOCK_MAPPING_VALUE; + return _processEmptyScalar(token.span.start); + } - // 123 - void nb_ns_singleInLine() { - zeroOrMore(() => transaction(() { - zeroOrMore(() => consume(isSpace)); - return ns_singleChar(); - })); - } + if (token.type == TokenType.BLOCK_END) { + _scanner.scan(); + _state = _states.removeLast(); + return new Event(EventType.MAPPING_END, token.span); + } - // 124 - bool s_singleNextLine(int indent) { - if (!truth(s_flowFolded(indent))) return false; - zeroOrOne(() { - if (!truth(ns_singleChar())) return; - nb_ns_singleInLine(); - or([ - () => s_singleNextLine(indent), - () => zeroOrMore(() => consume(isSpace)) - ]); - }); - return true; + throw new YamlException("Expected a key while parsing a block mapping.", + token.span.start.pointSpan()); } - // 125 - void nb_singleMultiLine(int indent) { - nb_ns_singleInLine(); - or([ - () => s_singleNextLine(indent), - () => zeroOrMore(() => consume(isSpace)) - ]); - } + /// Parses the productions: + /// + /// block_mapping ::= BLOCK-MAPPING_START + /// + /// ((KEY block_node_or_indentless_sequence?)? + /// + /// (VALUE block_node_or_indentless_sequence?)?)* + /// ***** * + /// BLOCK-END + /// + Event _parseBlockMappingValue() { + var token = _scanner.peek(); - // 126 - bool ns_plainFirst(int ctx) { - var char = peek(); - var indicator = indicatorType(char); - if (indicator == C_RESERVED) { - error("Reserved indicators can't start a plain scalar"); + if (token.type != TokenType.VALUE) { + _state = _State.BLOCK_MAPPING_KEY; + return _processEmptyScalar(token.span.start); } - var match = (isNonSpace(char) && indicator == null) || - ((indicator == C_MAPPING_KEY || - indicator == C_MAPPING_VALUE || - indicator == C_SEQUENCE_ENTRY) && - isPlainSafe(ctx, peek(1))); - - if (match) next(); - return match; - } - // 127 - bool isPlainSafe(int ctx, int char) { - switch (ctx) { - case FLOW_OUT: - case BLOCK_KEY: - // 128 - return isNonSpace(char); - case FLOW_IN: - case FLOW_KEY: - // 129 - return isNonSpace(char) && !isFlowIndicator(char); - default: throw 'Invalid context "$ctx".'; + var start = token.span.start; + token = _scanner.advance(); + if (token.type == TokenType.KEY || + token.type == TokenType.VALUE || + token.type == TokenType.BLOCK_END) { + _state = _State.BLOCK_MAPPING_KEY; + return _processEmptyScalar(start); + } else { + _states.add(_State.BLOCK_MAPPING_KEY); + return _parseNode(block: true, indentlessSequence: true); } } - // 130 - bool ns_plainChar(int ctx) { - var char = peek(); - var indicator = indicatorType(char); - var safeChar = isPlainSafe(ctx, char) && indicator != C_MAPPING_VALUE && - indicator != C_COMMENT; - var nonCommentHash = isNonSpace(peek(-1)) && indicator == C_COMMENT; - var nonMappingColon = indicator == C_MAPPING_VALUE && - isPlainSafe(ctx, peek(1)); - var match = safeChar || nonCommentHash || nonMappingColon; - - if (match) next(); - return match; - } + /// Parses the productions: + /// + /// flow_sequence ::= FLOW-SEQUENCE-START + /// ******************* + /// (flow_sequence_entry FLOW-ENTRY)* + /// * ********** + /// flow_sequence_entry? + /// * + /// FLOW-SEQUENCE-END + /// ***************** + /// flow_sequence_entry ::= + /// flow_node | KEY flow_node? (VALUE flow_node?)? + /// * + Event _parseFlowSequenceEntry({bool first: false}) { + if (first) _scanner.scan(); + var token = _scanner.peek(); + + if (token.type != TokenType.FLOW_SEQUENCE_END) { + if (!first) { + if (token.type != TokenType.FLOW_ENTRY) { + throw new YamlException( + "While parsing a flow sequence, expected ',' or ']'.", + token.span.start.pointSpan()); + } - // 131 - String ns_plain(int indent, int ctx) => context('plain scalar', () { - return captureString(() { - switch (ctx) { - case FLOW_OUT: - case FLOW_IN: - return ns_plainMultiLine(indent, ctx); - case BLOCK_KEY: - case FLOW_KEY: - return ns_plainOneLine(ctx); - default: throw 'Invalid context "$ctx".'; + token = _scanner.advance(); } - }); - }); - - // 132 - void nb_ns_plainInLine(int ctx) { - zeroOrMore(() => transaction(() { - zeroOrMore(() => consume(isSpace)); - return ns_plainChar(ctx); - })); - } - // 133 - bool ns_plainOneLine(int ctx) { - if (truth(c_forbidden())) return false; - if (!truth(ns_plainFirst(ctx))) return false; - nb_ns_plainInLine(ctx); - return true; - } + if (token.type == TokenType.KEY) { + _state = _State.FLOW_SEQUENCE_ENTRY_MAPPING_KEY; + _scanner.scan(); + return new MappingStartEvent( + token.span, CollectionStyle.FLOW); + } else if (token.type != TokenType.FLOW_SEQUENCE_END) { + _states.add(_State.FLOW_SEQUENCE_ENTRY); + return _parseNode(); + } + } - // 134 - bool s_ns_plainNextLine(int indent, int ctx) => transaction(() { - if (!truth(s_flowFolded(indent))) return false; - if (truth(c_forbidden())) return false; - if (!truth(ns_plainChar(ctx))) return false; - nb_ns_plainInLine(ctx); - return true; - }); - - // 135 - bool ns_plainMultiLine(int indent, int ctx) { - if (!truth(ns_plainOneLine(ctx))) return false; - zeroOrMore(() => s_ns_plainNextLine(indent, ctx)); - return true; - } + _scanner.scan(); + _state = _states.removeLast(); + return new Event(EventType.SEQUENCE_END, token.span); + } - // 136 - int inFlow(int ctx) { - switch (ctx) { - case FLOW_OUT: - case FLOW_IN: - return FLOW_IN; - case BLOCK_KEY: - case FLOW_KEY: - return FLOW_KEY; + /// Parses the productions: + /// + /// flow_sequence_entry ::= + /// flow_node | KEY flow_node? (VALUE flow_node?)? + /// *** * + Event _parseFlowSequenceEntryMappingKey() { + var token = _scanner.peek(); + + if (token.type == TokenType.VALUE || + token.type == TokenType.FLOW_ENTRY || + token.type == TokenType.FLOW_SEQUENCE_END) { + // libyaml consumes the token here, but that seems like a bug, since it + // always causes [_parseFlowSequenceEntryMappingValue] to emit an empty + // scalar. + + var start = token.span.start; + _state = _State.FLOW_SEQUENCE_ENTRY_MAPPING_VALUE; + return _processEmptyScalar(start); + } else { + _states.add(_State.FLOW_SEQUENCE_ENTRY_MAPPING_VALUE); + return _parseNode(); } - throw "unreachable"; } - // 137 - SequenceNode c_flowSequence(int indent, int ctx) => transaction(() { - var start = _scanner.state; - if (!truth(c_indicator(C_SEQUENCE_START))) return null; - zeroOrOne(() => s_separate(indent, ctx)); - var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx))); - if (!truth(c_indicator(C_SEQUENCE_END))) return null; - return new SequenceNode("?", new List.from(content), - _scanner.spanFrom(start)); - }); - - // 138 - Iterable ns_s_flowSeqEntries(int indent, int ctx) { - var first = ns_flowSeqEntry(indent, ctx); - if (!truth(first)) return new Queue(); - zeroOrOne(() => s_separate(indent, ctx)); - - var rest; - if (truth(c_indicator(C_COLLECT_ENTRY))) { - zeroOrOne(() => s_separate(indent, ctx)); - rest = zeroOrOne(() => ns_s_flowSeqEntries(indent, ctx)); + /// Parses the productions: + /// + /// flow_sequence_entry ::= + /// flow_node | KEY flow_node? (VALUE flow_node?)? + /// ***** * + Event _parseFlowSequenceEntryMappingValue() { + var token = _scanner.peek(); + + if (token.type == TokenType.VALUE) { + token = _scanner.advance(); + if (token.type != TokenType.FLOW_ENTRY && + token.type != TokenType.FLOW_SEQUENCE_END) { + _states.add(_State.FLOW_SEQUENCE_ENTRY_MAPPING_END); + return _parseNode(); + } } - if (rest == null) rest = new Queue(); - rest.addFirst(first); - - return rest; + _state = _State.FLOW_SEQUENCE_ENTRY_MAPPING_END; + return _processEmptyScalar(token.span.start); } - // 139 - Node ns_flowSeqEntry(int indent, int ctx) => or([ - () => ns_flowPair(indent, ctx), - () => ns_flowNode(indent, ctx) - ]); - - // 140 - Node c_flowMapping(int indent, int ctx) { - var start = _scanner.state; - if (!truth(c_indicator(C_MAPPING_START))) return null; - zeroOrOne(() => s_separate(indent, ctx)); - var content = zeroOrOne(() => ns_s_flowMapEntries(indent, inFlow(ctx))); - if (!truth(c_indicator(C_MAPPING_END))) return null; - return new MappingNode("?", content, _scanner.spanFrom(start)); + /// Parses the productions: + /// + /// flow_sequence_entry ::= + /// flow_node | KEY flow_node? (VALUE flow_node?)? + /// * + Event _parseFlowSequenceEntryMappingEnd() { + _state = _State.FLOW_SEQUENCE_ENTRY; + return new Event(EventType.MAPPING_END, + _scanner.peek().span.start.pointSpan()); } - // 141 - Map ns_s_flowMapEntries(int indent, int ctx) { - var first = ns_flowMapEntry(indent, ctx); - if (!truth(first)) return deepEqualsMap(); - zeroOrOne(() => s_separate(indent, ctx)); + /// Parses the productions: + /// + /// flow_mapping ::= FLOW-MAPPING-START + /// ****************** + /// (flow_mapping_entry FLOW-ENTRY)* + /// * ********** + /// flow_mapping_entry? + /// ****************** + /// FLOW-MAPPING-END + /// **************** + /// flow_mapping_entry ::= + /// flow_node | KEY flow_node? (VALUE flow_node?)? + /// * *** * + Event _parseFlowMappingKey({bool first: false}) { + if (first) _scanner.scan(); + var token = _scanner.peek(); + + if (token.type != TokenType.FLOW_MAPPING_END) { + if (!first) { + if (token.type != TokenType.FLOW_ENTRY) { + throw new YamlException( + "While parsing a flow mapping, expected ',' or '}'.", + token.span.start.pointSpan()); + } + + token = _scanner.advance(); + } - var rest; - if (truth(c_indicator(C_COLLECT_ENTRY))) { - zeroOrOne(() => s_separate(indent, ctx)); - rest = ns_s_flowMapEntries(indent, ctx); + if (token.type == TokenType.KEY) { + token = _scanner.advance(); + if (token.type != TokenType.VALUE && + token.type != TokenType.FLOW_ENTRY && + token.type != TokenType.FLOW_MAPPING_END) { + _states.add(_State.FLOW_MAPPING_VALUE); + return _parseNode(); + } else { + _state = _State.FLOW_MAPPING_VALUE; + return _processEmptyScalar(token.span.start); + } + } else if (token.type != TokenType.FLOW_MAPPING_END) { + _states.add(_State.FLOW_MAPPING_EMPTY_VALUE); + return _parseNode(); + } } - if (rest == null) rest = deepEqualsMap(); + _scanner.scan(); + _state = _states.removeLast(); + return new Event(EventType.MAPPING_END, token.span); + } - // TODO(nweiz): Duplicate keys should be an error. This includes keys with - // different representations but the same value (e.g. 10 vs 0xa). To make - // this user-friendly we'll probably also want to associate nodes with a - // source range. - if (!rest.containsKey(first.first)) rest[first.first] = first.last; + /// Parses the productions: + /// + /// flow_mapping_entry ::= + /// flow_node | KEY flow_node? (VALUE flow_node?)? + /// * ***** * + Event _parseFlowMappingValue({bool empty: false}) { + var token = _scanner.peek(); + + if (empty) { + _state = _State.FLOW_MAPPING_KEY; + return _processEmptyScalar(token.span.start); + } - return rest; - } + if (token.type == TokenType.VALUE) { + token = _scanner.advance(); + if (token.type != TokenType.FLOW_ENTRY && + token.type != TokenType.FLOW_MAPPING_END) { + _states.add(_State.FLOW_MAPPING_KEY); + return _parseNode(); + } + } - // 142 - Pair ns_flowMapEntry(int indent, int ctx) => or([ - () => transaction(() { - if (!truth(c_indicator(C_MAPPING_KEY))) return false; - if (!truth(s_separate(indent, ctx))) return false; - return ns_flowMapExplicitEntry(indent, ctx); - }), - () => ns_flowMapImplicitEntry(indent, ctx) - ]); - - // 143 - Pair ns_flowMapExplicitEntry(int indent, int ctx) => or([ - () => ns_flowMapImplicitEntry(indent, ctx), - () => new Pair(e_node(), e_node()) - ]); - - // 144 - Pair ns_flowMapImplicitEntry(int indent, int ctx) => or([ - () => ns_flowMapYamlKeyEntry(indent, ctx), - () => c_ns_flowMapEmptyKeyEntry(indent, ctx), - () => c_ns_flowMapJsonKeyEntry(indent, ctx) - ]); - - // 145 - Pair ns_flowMapYamlKeyEntry(int indent, int ctx) { - var key = ns_flowYamlNode(indent, ctx); - if (!truth(key)) return null; - var value = or([ - () => transaction(() { - zeroOrOne(() => s_separate(indent, ctx)); - return c_ns_flowMapSeparateValue(indent, ctx); - }), - e_node - ]); - return new Pair(key, value); + _state = _State.FLOW_MAPPING_KEY; + return _processEmptyScalar(token.span.start); } - // 146 - Pair c_ns_flowMapEmptyKeyEntry(int indent, int ctx) { - var value = c_ns_flowMapSeparateValue(indent, ctx); - if (!truth(value)) return null; - return new Pair(e_node(), value); - } + /// Generate an empty scalar event. + Event _processEmptyScalar(SourceLocation location) => + new ScalarEvent(location.pointSpan(), '', ScalarStyle.PLAIN); - // 147 - Node c_ns_flowMapSeparateValue(int indent, int ctx) => transaction(() { - if (!truth(c_indicator(C_MAPPING_VALUE))) return null; - if (isPlainSafe(ctx, peek())) return null; - - return or([ - () => transaction(() { - if (!s_separate(indent, ctx)) return null; - return ns_flowNode(indent, ctx); - }), - e_node - ]); - }); - - // 148 - Pair c_ns_flowMapJsonKeyEntry(int indent, int ctx) { - var key = c_flowJsonNode(indent, ctx); - if (!truth(key)) return null; - var value = or([ - () => transaction(() { - zeroOrOne(() => s_separate(indent, ctx)); - return c_ns_flowMapAdjacentValue(indent, ctx); - }), - e_node - ]); - return new Pair(key, value); - } + /// Parses directives. + Pair> _processDirectives() { + var token = _scanner.peek(); - // 149 - Node c_ns_flowMapAdjacentValue(int indent, int ctx) { - if (!truth(c_indicator(C_MAPPING_VALUE))) return null; - return or([ - () => transaction(() { - zeroOrOne(() => s_separate(indent, ctx)); - return ns_flowNode(indent, ctx); - }), - e_node - ]); - } + var versionDirective; + var tagDirectives = []; + var reservedDirectives = []; + while (token.type == TokenType.VERSION_DIRECTIVE || + token.type == TokenType.TAG_DIRECTIVE) { + if (token is VersionDirectiveToken) { + if (versionDirective != null) { + throw new YamlException("Duplicate %YAML directive.", token.span); + } - // 150 - Node ns_flowPair(int indent, int ctx) { - var start = _scanner.state; - var pair = or([ - () => transaction(() { - if (!truth(c_indicator(C_MAPPING_KEY))) return null; - if (!truth(s_separate(indent, ctx))) return null; - return ns_flowMapExplicitEntry(indent, ctx); - }), - () => ns_flowPairEntry(indent, ctx) - ]); - if (!truth(pair)) return null; - - return map([pair], _scanner.spanFrom(start)); - } + if (token.major != 1 || token.minor == 0) { + throw new YamlException( + "Incompatible YAML document. This parser only supports YAML 1.1 " + "and 1.2.", + token.span); + } else if (token.minor > 2) { + // TODO(nweiz): Print to stderr when issue 6943 is fixed and dart:io + // is available. + warn("Warning: this parser only supports YAML 1.1 and 1.2.", + token.span); + } - // 151 - Pair ns_flowPairEntry(int indent, int ctx) => or([ - () => ns_flowPairYamlKeyEntry(indent, ctx), - () => c_ns_flowMapEmptyKeyEntry(indent, ctx), - () => c_ns_flowPairJsonKeyEntry(indent, ctx) - ]); - - // 152 - Pair ns_flowPairYamlKeyEntry(int indent, int ctx) => - transaction(() { - var key = ns_s_implicitYamlKey(FLOW_KEY); - if (!truth(key)) return null; - var value = c_ns_flowMapSeparateValue(indent, ctx); - if (!truth(value)) return null; - return new Pair(key, value); - }); - - // 153 - Pair c_ns_flowPairJsonKeyEntry(int indent, int ctx) => - transaction(() { - var key = c_s_implicitJsonKey(FLOW_KEY); - if (!truth(key)) return null; - var value = c_ns_flowMapAdjacentValue(indent, ctx); - if (!truth(value)) return null; - return new Pair(key, value); - }); - - // 154 - Node ns_s_implicitYamlKey(int ctx) => transaction(() { - // TODO(nweiz): this is supposed to be limited to 1024 characters. - - // The indentation parameter is "null" since it's unused in this path - var node = ns_flowYamlNode(null, ctx); - if (!truth(node)) return null; - zeroOrOne(s_separateInLine); - return node; - }); - - // 155 - Node c_s_implicitJsonKey(int ctx) => transaction(() { - // TODO(nweiz): this is supposed to be limited to 1024 characters. - - // The indentation parameter is "null" since it's unused in this path - var node = c_flowJsonNode(null, ctx); - if (!truth(node)) return null; - zeroOrOne(s_separateInLine); - return node; - }); - - // 156 - Node ns_flowYamlContent(int indent, int ctx) { - var start = _scanner.state; - var str = ns_plain(indent, ctx); - if (!truth(str)) return null; - return new ScalarNode("?", _scanner.spanFrom(start), content: str); - } + versionDirective = new VersionDirective(token.major, token.minor); + } else if (token is TagDirectiveToken) { + var tagDirective = new TagDirective(token.handle, token.prefix); + _appendTagDirective(tagDirective, token.span); + tagDirectives.add(tagDirective); + } - // 157 - Node c_flowJsonContent(int indent, int ctx) => or([ - () => c_flowSequence(indent, ctx), - () => c_flowMapping(indent, ctx), - () => c_singleQuoted(indent, ctx), - () => c_doubleQuoted(indent, ctx) - ]); - - // 158 - Node ns_flowContent(int indent, int ctx) => or([ - () => ns_flowYamlContent(indent, ctx), - () => c_flowJsonContent(indent, ctx) - ]); - - // 159 - Node ns_flowYamlNode(int indent, int ctx) => or([ - c_ns_aliasNode, - () => ns_flowYamlContent(indent, ctx), - () { - var props = c_ns_properties(indent, ctx); - if (!truth(props)) return null; - var node = or([ - () => transaction(() { - if (!truth(s_separate(indent, ctx))) return null; - return ns_flowYamlContent(indent, ctx); - }), - e_scalar - ]); - return addProps(node, props); + token = _scanner.advance(); } - ]); - - // 160 - Node c_flowJsonNode(int indent, int ctx) => transaction(() { - var props; - zeroOrOne(() => transaction(() { - props = c_ns_properties(indent, ctx); - if (!truth(props)) return null; - return s_separate(indent, ctx); - })); - - return addProps(c_flowJsonContent(indent, ctx), props); - }); - - // 161 - Node ns_flowNode(int indent, int ctx) => or([ - c_ns_aliasNode, - () => ns_flowContent(indent, ctx), - () => transaction(() { - var props = c_ns_properties(indent, ctx); - if (!truth(props)) return null; - var node = or([ - () => transaction(() => s_separate(indent, ctx) ? - ns_flowContent(indent, ctx) : null), - e_scalar]); - return addProps(node, props); - }) - ]); - - // 162 - _BlockHeader c_b_blockHeader() => transaction(() { - var indentation = c_indentationIndicator(); - var chomping = c_chompingIndicator(); - if (!truth(indentation)) indentation = c_indentationIndicator(); - if (!truth(s_b_comment())) return null; - - return new _BlockHeader(indentation, chomping); - }); - - // 163 - int c_indentationIndicator() { - if (!isDecDigit(peek())) return null; - return next() - NUMBER_0; - } - - // 164 - int c_chompingIndicator() { - switch (peek()) { - case HYPHEN: - next(); - return CHOMPING_STRIP; - case PLUS: - next(); - return CHOMPING_KEEP; - default: - return CHOMPING_CLIP; + + _appendTagDirective( + new TagDirective("!", "!"), + token.span.start.pointSpan(), + allowDuplicates: true); + _appendTagDirective( + new TagDirective("!!", "tag:yaml.org,2002:"), + token.span.start.pointSpan(), + allowDuplicates: true); + + return new Pair(versionDirective, tagDirectives); + } + + /// Adds a tag directive to the directives stack. + void _appendTagDirective(TagDirective newDirective, FileSpan span, + {bool allowDuplicates: false}) { + if (_tagDirectives.containsKey(newDirective.handle)) { + if (allowDuplicates) return; + throw new YamlException("Duplicate %TAG directive.", span); } - } - // 165 - bool b_chompedLast(int chomping) { - if (_scanner.isDone) return true; - switch (chomping) { - case CHOMPING_STRIP: - return b_nonContent(); - case CHOMPING_CLIP: - case CHOMPING_KEEP: - return b_asLineFeed(); - } - throw "unreachable"; + _tagDirectives[newDirective.handle] = newDirective; } +} - // 166 - void l_chompedEmpty(int indent, int chomping) { - switch (chomping) { - case CHOMPING_STRIP: - case CHOMPING_CLIP: - l_stripEmpty(indent); - break; - case CHOMPING_KEEP: - l_keepEmpty(indent); - break; - } - } +/// The possible states for the parser. +class _State { + /// Expect [TokenType.STREAM_START]. + static const STREAM_START = const _State("STREAM_START"); - // 167 - void l_stripEmpty(int indent) { - captureAs('', () { - zeroOrMore(() => transaction(() { - if (!truth(s_indentLessThanOrEqualTo(indent))) return false; - return b_nonContent(); - })); - zeroOrOne(() => l_trailComments(indent)); - return true; - }); - } + /// Expect the beginning of an implicit document. + static const IMPLICIT_DOCUMENT_START = + const _State("IMPLICIT_DOCUMENT_START"); - // 168 - void l_keepEmpty(int indent) { - zeroOrMore(() => captureAs('\n', () => l_empty(indent, BLOCK_IN))); - zeroOrOne(() => captureAs('', () => l_trailComments(indent))); - } + /// Expect [TokenType.DOCUMENT_START]. + static const DOCUMENT_START = const _State("DOCUMENT_START"); - // 169 - bool l_trailComments(int indent) => transaction(() { - if (!truth(s_indentLessThanOrEqualTo(indent))) return false; - if (!truth(c_nb_commentText())) return false; - if (!truth(b_comment())) return false; - zeroOrMore(l_comment); - return true; - }); - - // 170 - Node c_l_literal(int indent) => transaction(() { - var start = _scanner.state; - if (!truth(c_indicator(C_LITERAL))) return null; - var header = c_b_blockHeader(); - if (!truth(header)) return null; - - var additionalIndent = blockScalarAdditionalIndentation(header, indent); - var content = l_literalContent(indent + additionalIndent, header.chomping); - if (!truth(content)) return null; - - return new ScalarNode("!", _scanner.spanFrom(start), content: content); - }); - - // 171 - bool l_nb_literalText(int indent) => transaction(() { - zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN))); - if (!truth(captureAs("", () => s_indent(indent)))) return false; - return truth(oneOrMore(() => consume(isNonBreak))); - }); - - // 172 - bool b_nb_literalNext(int indent) => transaction(() { - if (!truth(b_asLineFeed())) return false; - return l_nb_literalText(indent); - }); - - // 173 - String l_literalContent(int indent, int chomping) => captureString(() { - transaction(() { - if (!truth(l_nb_literalText(indent))) return false; - zeroOrMore(() => b_nb_literalNext(indent)); - return b_chompedLast(chomping); - }); - l_chompedEmpty(indent, chomping); - return true; - }); - - // 174 - Node c_l_folded(int indent) => transaction(() { - var start = _scanner.state; - if (!truth(c_indicator(C_FOLDED))) return null; - var header = c_b_blockHeader(); - if (!truth(header)) return null; - - var additionalIndent = blockScalarAdditionalIndentation(header, indent); - var content = l_foldedContent(indent + additionalIndent, header.chomping); - if (!truth(content)) return null; - - return new ScalarNode("!", _scanner.spanFrom(start), content: content); - }); - - // 175 - bool s_nb_foldedText(int indent) => transaction(() { - if (!truth(captureAs('', () => s_indent(indent)))) return false; - if (!truth(consume(isNonSpace))) return false; - zeroOrMore(() => consume(isNonBreak)); - return true; - }); - - // 176 - bool l_nb_foldedLines(int indent) { - if (!truth(s_nb_foldedText(indent))) return false; - zeroOrMore(() => transaction(() { - if (!truth(b_l_folded(indent, BLOCK_IN))) return false; - return s_nb_foldedText(indent); - })); - return true; - } + /// Expect the content of a document. + static const DOCUMENT_CONTENT = const _State("DOCUMENT_CONTENT"); - // 177 - bool s_nb_spacedText(int indent) => transaction(() { - if (!truth(captureAs('', () => s_indent(indent)))) return false; - if (!truth(consume(isSpace))) return false; - zeroOrMore(() => consume(isNonBreak)); - return true; - }); - - // 178 - bool b_l_spaced(int indent) { - if (!truth(b_asLineFeed())) return false; - zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN))); - return true; - } + /// Expect [TokenType.DOCUMENT_END]. + static const DOCUMENT_END = const _State("DOCUMENT_END"); - // 179 - bool l_nb_spacedLines(int indent) { - if (!truth(s_nb_spacedText(indent))) return false; - zeroOrMore(() => transaction(() { - if (!truth(b_l_spaced(indent))) return false; - return s_nb_spacedText(indent); - })); - return true; - } + /// Expect a block node. + static const BLOCK_NODE = const _State("BLOCK_NODE"); - // 180 - bool l_nb_sameLines(int indent) => transaction(() { - zeroOrMore(() => captureAs('\n', () => l_empty(indent, BLOCK_IN))); - return or([ - () => l_nb_foldedLines(indent), - () => l_nb_spacedLines(indent) - ]); - }); - - // 181 - bool l_nb_diffLines(int indent) { - if (!truth(l_nb_sameLines(indent))) return false; - zeroOrMore(() => transaction(() { - if (!truth(b_asLineFeed())) return false; - return l_nb_sameLines(indent); - })); - return true; - } + /// Expect a block node or indentless sequence. + static const BLOCK_NODE_OR_INDENTLESS_SEQUENCE = + const _State("BLOCK_NODE_OR_INDENTLESS_SEQUENCE"); - // 182 - String l_foldedContent(int indent, int chomping) => captureString(() { - transaction(() { - if (!truth(l_nb_diffLines(indent))) return false; - return b_chompedLast(chomping); - }); - l_chompedEmpty(indent, chomping); - return true; - }); - - // 183 - SequenceNode l_blockSequence(int indent) => context('sequence', () { - var additionalIndent = countIndentation() - indent; - if (additionalIndent <= 0) return null; - - var start = _scanner.state; - var content = oneOrMore(() => transaction(() { - if (!truth(s_indent(indent + additionalIndent))) return null; - return c_l_blockSeqEntry(indent + additionalIndent); - })); - if (!truth(content)) return null; - - return new SequenceNode("?", content, _scanner.spanFrom(start)); - }); - - // 184 - Node c_l_blockSeqEntry(int indent) => transaction(() { - if (!truth(c_indicator(C_SEQUENCE_ENTRY))) return null; - if (isNonSpace(peek())) return null; - - return s_l_blockIndented(indent, BLOCK_IN); - }); - - // 185 - Node s_l_blockIndented(int indent, int ctx) { - var additionalIndent = countIndentation(); - return or([ - () => transaction(() { - if (!truth(s_indent(additionalIndent))) return null; - return or([ - () => ns_l_compactSequence(indent + 1 + additionalIndent), - () => ns_l_compactMapping(indent + 1 + additionalIndent)]); - }), - () => s_l_blockNode(indent, ctx), - () => s_l_comments() ? e_node() : null]); - } + /// Expect a flow node. + static const FLOW_NODE = const _State("FLOW_NODE"); - // 186 - Node ns_l_compactSequence(int indent) => context('sequence', () { - var start = _scanner.state; - var first = c_l_blockSeqEntry(indent); - if (!truth(first)) return null; - - var content = zeroOrMore(() => transaction(() { - if (!truth(s_indent(indent))) return null; - return c_l_blockSeqEntry(indent); - })); - content.insert(0, first); - - return new SequenceNode("?", content, _scanner.spanFrom(start)); - }); - - // 187 - Node l_blockMapping(int indent) => context('mapping', () { - var additionalIndent = countIndentation() - indent; - if (additionalIndent <= 0) return null; - - var start = _scanner.state; - var pairs = oneOrMore(() => transaction(() { - if (!truth(s_indent(indent + additionalIndent))) return null; - return ns_l_blockMapEntry(indent + additionalIndent); - })); - if (!truth(pairs)) return null; - - return map(pairs, _scanner.spanFrom(start)); - }); - - // 188 - Pair ns_l_blockMapEntry(int indent) => or([ - () => c_l_blockMapExplicitEntry(indent), - () => ns_l_blockMapImplicitEntry(indent) - ]); - - // 189 - Pair c_l_blockMapExplicitEntry(int indent) { - var key = c_l_blockMapExplicitKey(indent); - if (!truth(key)) return null; - - var value = or([ - () => l_blockMapExplicitValue(indent), - e_node - ]); - - return new Pair(key, value); - } + /// Expect the first entry of a block sequence. + static const BLOCK_SEQUENCE_FIRST_ENTRY = + const _State("BLOCK_SEQUENCE_FIRST_ENTRY"); - // 190 - Node c_l_blockMapExplicitKey(int indent) => transaction(() { - if (!truth(c_indicator(C_MAPPING_KEY))) return null; - return s_l_blockIndented(indent, BLOCK_OUT); - }); - - // 191 - Node l_blockMapExplicitValue(int indent) => transaction(() { - if (!truth(s_indent(indent))) return null; - if (!truth(c_indicator(C_MAPPING_VALUE))) return null; - return s_l_blockIndented(indent, BLOCK_OUT); - }); - - // 192 - Pair ns_l_blockMapImplicitEntry(int indent) => transaction(() { - var key = or([ns_s_blockMapImplicitKey, e_node]); - var value = c_l_blockMapImplicitValue(indent); - return truth(value) ? new Pair(key, value) : null; - }); - - // 193 - Node ns_s_blockMapImplicitKey() => context('mapping key', () => or([ - () => c_s_implicitJsonKey(BLOCK_KEY), - () => ns_s_implicitYamlKey(BLOCK_KEY) - ])); - - // 194 - Node c_l_blockMapImplicitValue(int indent) => context('mapping value', () => - transaction(() { - if (!truth(c_indicator(C_MAPPING_VALUE))) return null; - return or([ - () => s_l_blockNode(indent, BLOCK_OUT), - () => s_l_comments() ? e_node() : null - ]); - })); - - // 195 - Node ns_l_compactMapping(int indent) => context('mapping', () { - var start = _scanner.state; - var first = ns_l_blockMapEntry(indent); - if (!truth(first)) return null; - - var pairs = zeroOrMore(() => transaction(() { - if (!truth(s_indent(indent))) return null; - return ns_l_blockMapEntry(indent); - })); - pairs.insert(0, first); - - return map(pairs, _scanner.spanFrom(start)); - }); - - // 196 - Node s_l_blockNode(int indent, int ctx) => or([ - () => s_l_blockInBlock(indent, ctx), - () => s_l_flowInBlock(indent) - ]); - - // 197 - Node s_l_flowInBlock(int indent) => transaction(() { - if (!truth(s_separate(indent + 1, FLOW_OUT))) return null; - var node = ns_flowNode(indent + 1, FLOW_OUT); - if (!truth(node)) return null; - if (!truth(s_l_comments())) return null; - return node; - }); - - // 198 - Node s_l_blockInBlock(int indent, int ctx) => or([ - () => s_l_blockScalar(indent, ctx), - () => s_l_blockCollection(indent, ctx) - ]); - - // 199 - Node s_l_blockScalar(int indent, int ctx) => transaction(() { - if (!truth(s_separate(indent + 1, ctx))) return null; - var props = transaction(() { - var innerProps = c_ns_properties(indent + 1, ctx); - if (!truth(innerProps)) return null; - if (!truth(s_separate(indent + 1, ctx))) return null; - return innerProps; - }); - - var node = or([() => c_l_literal(indent), () => c_l_folded(indent)]); - if (!truth(node)) return null; - return addProps(node, props); - }); - - // 200 - Node s_l_blockCollection(int indent, int ctx) => transaction(() { - var props = transaction(() { - if (!truth(s_separate(indent + 1, ctx))) return null; - return c_ns_properties(indent + 1, ctx); - }); - - if (!truth(s_l_comments())) return null; - return or([ - () => l_blockSequence(seqSpaces(indent, ctx)), - () => l_blockMapping(indent)]); - }); - - // 201 - int seqSpaces(int indent, int ctx) => ctx == BLOCK_OUT ? indent - 1 : indent; - - // 202 - void l_documentPrefix() { - zeroOrMore(l_comment); - } + /// Expect an entry of a block sequence. + static const BLOCK_SEQUENCE_ENTRY = const _State("BLOCK_SEQUENCE_ENTRY"); - // 203 - bool c_directivesEnd() => rawString("---"); - - // 204 - bool c_documentEnd() => rawString("..."); - - // 205 - bool l_documentSuffix() => transaction(() { - if (!truth(c_documentEnd())) return false; - return s_l_comments(); - }); - - // 206 - bool c_forbidden() { - if (!_inBareDocument || !atStartOfLine) return false; - var forbidden = false; - transaction(() { - if (!truth(or([c_directivesEnd, c_documentEnd]))) return; - var char = peek(); - forbidden = isBreak(char) || isSpace(char) || _scanner.isDone; - return; - }); - return forbidden; - } + /// Expect an entry of an indentless sequence. + static const INDENTLESS_SEQUENCE_ENTRY = + const _State("INDENTLESS_SEQUENCE_ENTRY"); - // 207 - Node l_bareDocument() { - try { - _inBareDocument = true; - return s_l_blockNode(-1, BLOCK_IN); - } finally { - _inBareDocument = false; - } - } + /// Expect the first key of a block mapping. + static const BLOCK_MAPPING_FIRST_KEY = + const _State("BLOCK_MAPPING_FIRST_KEY"); - // 208 - Node l_explicitDocument() { - if (!truth(c_directivesEnd())) return null; - var doc = l_bareDocument(); - if (truth(doc)) return doc; + /// Expect a block mapping key. + static const BLOCK_MAPPING_KEY = const _State("BLOCK_MAPPING_KEY"); - doc = e_node(); - s_l_comments(); - return doc; - } + /// Expect a block mapping value. + static const BLOCK_MAPPING_VALUE = const _State("BLOCK_MAPPING_VALUE"); - // 209 - Node l_directiveDocument() { - if (!truth(oneOrMore(l_directive))) return null; - var doc = l_explicitDocument(); - if (doc != null) return doc; - parseFailed(); - return null; // Unreachable. - } + /// Expect the first entry of a flow sequence. + static const FLOW_SEQUENCE_FIRST_ENTRY = + const _State("FLOW_SEQUENCE_FIRST_ENTRY"); - // 210 - Node l_anyDocument() => - or([l_directiveDocument, l_explicitDocument, l_bareDocument]); - - // 211 - Pair, SourceSpan> l_yamlStream() { - var start = _scanner.state; - var docs = []; - zeroOrMore(l_documentPrefix); - var first = zeroOrOne(l_anyDocument); - if (!truth(first)) first = e_node(); - docs.add(first); - - zeroOrMore(() { - var doc; - if (truth(oneOrMore(l_documentSuffix))) { - zeroOrMore(l_documentPrefix); - doc = zeroOrOne(l_anyDocument); - } else { - zeroOrMore(l_documentPrefix); - doc = zeroOrOne(l_explicitDocument); - } - if (truth(doc)) docs.add(doc); - return doc; - }); + /// Expect an entry of a flow sequence. + static const FLOW_SEQUENCE_ENTRY = const _State("FLOW_SEQUENCE_ENTRY"); - if (!_scanner.isDone) parseFailed(); - return new Pair(docs, _scanner.spanFrom(start)); - } -} + /// Expect a key of an ordered mapping. + static const FLOW_SEQUENCE_ENTRY_MAPPING_KEY = + const _State("FLOW_SEQUENCE_ENTRY_MAPPING_KEY"); -/// The information in the header for a block scalar. -class _BlockHeader { - final int additionalIndent; - final int chomping; + /// Expect a value of an ordered mapping. + static const FLOW_SEQUENCE_ENTRY_MAPPING_VALUE = + const _State("FLOW_SEQUENCE_ENTRY_MAPPING_VALUE"); - _BlockHeader(this.additionalIndent, this.chomping); + /// Expect the and of an ordered mapping entry. + static const FLOW_SEQUENCE_ENTRY_MAPPING_END = + const _State("FLOW_SEQUENCE_ENTRY_MAPPING_END"); - bool get autoDetectIndent => additionalIndent == null; -} + /// Expect the first key of a flow mapping. + static const FLOW_MAPPING_FIRST_KEY = const _State("FLOW_MAPPING_FIRST_KEY"); -/// A range of characters in the YAML document, from [start] to [end] -/// (inclusive). -class _Range { - /// The first character in the range. - final int start; + /// Expect a key of a flow mapping. + static const FLOW_MAPPING_KEY = const _State("FLOW_MAPPING_KEY"); - /// The last character in the range. - final int end; + /// Expect a value of a flow mapping. + static const FLOW_MAPPING_VALUE = const _State("FLOW_MAPPING_VALUE"); - _Range(this.start, this.end); + /// Expect an empty value of a flow mapping. + static const FLOW_MAPPING_EMPTY_VALUE = + const _State("FLOW_MAPPING_EMPTY_VALUE"); - /// Returns whether or not [pos] lies within this range. - bool contains(int pos) => pos >= start && pos <= end; -} + /// Expect nothing. + static const END = const _State("END"); -/// A map that associates [E] values with [_Range]s. It's efficient to create -/// new associations, but finding the value associated with a position is more -/// expensive. -class _RangeMap { - /// The ranges and their associated elements. - final List> _contents = >[]; - - _RangeMap(); - - /// Returns the value associated with the range in which [pos] lies, or null - /// if there is no such range. If there's more than one such range, the most - /// recently set one is used. - E operator[](int pos) { - // Iterate backwards through contents so the more recent range takes - // precedence. - for (var pair in _contents.reversed) { - if (pair.first.contains(pos)) return pair.last; - } - return null; - } + final String name; + + const _State(this.name); - /// Associates [value] with [range]. - operator[]=(_Range range, E value) => - _contents.add(new Pair<_Range, E>(range, value)); + String toString() => name; } diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart new file mode 100644 index 000000000..00685539c --- /dev/null +++ b/pkgs/yaml/lib/src/scanner.dart @@ -0,0 +1,1663 @@ +// Copyright (c) 2014, 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 yaml.scanner; + +import 'package:collection/collection.dart'; +import 'package:string_scanner/string_scanner.dart'; +import 'package:source_span/source_span.dart'; + +import 'style.dart'; +import 'token.dart'; +import 'utils.dart'; +import 'yaml_exception.dart'; + +/// A scanner that reads a string of Unicode characters and emits [Token]s. +/// +/// This is based on the libyaml scanner, available at +/// https://github.com/yaml/libyaml/blob/master/src/scanner.c. The license for +/// that is available in ../../libyaml-license.txt. +class Scanner { + static const TAB = 0x9; + static const LF = 0xA; + static const CR = 0xD; + static const SP = 0x20; + static const DOLLAR = 0x24; + static const LEFT_PAREN = 0x28; + static const RIGHT_PAREN = 0x29; + static const PLUS = 0x2B; + static const COMMA = 0x2C; + static const HYPHEN = 0x2D; + static const PERIOD = 0x2E; + static const QUESTION = 0x3F; + static const COLON = 0x3A; + static const SEMICOLON = 0x3B; + static const EQUALS = 0x3D; + static const LEFT_SQUARE = 0x5B; + static const RIGHT_SQUARE = 0x5D; + static const LEFT_CURLY = 0x7B; + static const RIGHT_CURLY = 0x7D; + static const HASH = 0x23; + static const AMPERSAND = 0x26; + static const ASTERISK = 0x2A; + static const EXCLAMATION = 0x21; + static const VERTICAL_BAR = 0x7C; + static const LEFT_ANGLE = 0x3C; + static const RIGHT_ANGLE = 0x3E; + static const SINGLE_QUOTE = 0x27; + static const DOUBLE_QUOTE = 0x22; + static const PERCENT = 0x25; + static const AT = 0x40; + static const GRAVE_ACCENT = 0x60; + static const TILDE = 0x7E; + + static const NULL = 0x0; + static const BELL = 0x7; + static const BACKSPACE = 0x8; + static const VERTICAL_TAB = 0xB; + static const FORM_FEED = 0xC; + static const ESCAPE = 0x1B; + static const SLASH = 0x2F; + static const BACKSLASH = 0x5C; + static const UNDERSCORE = 0x5F; + static const NEL = 0x85; + static const NBSP = 0xA0; + static const LINE_SEPARATOR = 0x2028; + static const PARAGRAPH_SEPARATOR = 0x2029; + static const BOM = 0xFEFF; + + static const NUMBER_0 = 0x30; + static const NUMBER_9 = 0x39; + + static const LETTER_A = 0x61; + static const LETTER_B = 0x62; + static const LETTER_E = 0x65; + static const LETTER_F = 0x66; + static const LETTER_N = 0x6E; + static const LETTER_R = 0x72; + static const LETTER_T = 0x74; + static const LETTER_U = 0x75; + static const LETTER_V = 0x76; + static const LETTER_X = 0x78; + static const LETTER_Z = 0x7A; + + static const LETTER_CAP_A = 0x41; + static const LETTER_CAP_F = 0x46; + static const LETTER_CAP_L = 0x4C; + static const LETTER_CAP_N = 0x4E; + static const LETTER_CAP_P = 0x50; + static const LETTER_CAP_U = 0x55; + static const LETTER_CAP_X = 0x58; + static const LETTER_CAP_Z = 0x5A; + + /// The underlying [SpanScanner] used to read characters from the source text. + /// + /// This is also used to track line and column information and to generate + /// [SourceSpan]s. + final SpanScanner _scanner; + + /// Whether this scanner has produced a [TokenType.STREAM_START] token + /// indicating the beginning of the YAML stream. + var _streamStartProduced = false; + + /// Whether this scanner has produced a [TokenType.STREAM_END] token + /// indicating the end of the YAML stream. + var _streamEndProduced = false; + + /// The queue of tokens yet to be emitted. + /// + /// These are queued up in advance so that [TokenType.KEY] tokens can be + /// inserted once the scanner determines that a series of tokens represents a + /// mapping key. + final _tokens = new QueueList(); + + /// The number of tokens that have been emitted. + /// + /// This doesn't count tokens in [tokens]. + var _tokensParsed = 0; + + /// Whether the next token in [_tokens] is ready to be returned. + /// + /// It might not be ready if there may still be a [TokenType.KEY] inserted + /// before it. + var _tokenAvailable = false; + + /// The stack of indent levels for the current nested block contexts. + /// + /// The YAML spec specifies that the initial indentation level is -1 spaces. + final _indents = [-1]; + + /// Whether a simple key is allowed in this context. + /// + /// A simple key refers to any mapping key that doesn't have an explicit "?". + var _simpleKeyAllowed = true; + + /// The stack of potential simple keys for each level of flow nesting. + /// + /// Entries in this list may be `null`, indicating that there is no valid + /// simple key for the associated level of nesting. + /// + /// When a ":" is parsed and there's a simple key available, a [TokenType.KEY] + /// token is inserted in [_tokens] before that key's token. This allows the + /// parser to tell that the key is intended to be a mapping key. + final _simpleKeys = <_SimpleKey>[null]; + + /// The current indentation level. + int get _indent => _indents.last; + + /// Whether the scanner's currently positioned in a block-level structure (as + /// opposed to flow-level). + bool get _inBlockContext => _simpleKeys.length == 1; + + /// Whether the current character is a line break or the end of the source. + bool get _isBreakOrEnd => _scanner.isDone || _isBreak; + + /// Whether the current character is a line break. + bool get _isBreak => _isBreakAt(0); + + /// Whether the current character is whitespace or the end of the source. + bool get _isBlankOrEnd => _isBlankOrEndAt(0); + + /// Whether the current character is whitespace. + bool get _isBlank => _isBlankAt(0); + + /// Whether the current character is a valid tag name character. + /// + /// See http://yaml.org/spec/1.2/spec.html#ns-tag-name. + bool get _isTagChar { + var char = _scanner.peekChar(); + if (char == null) return false; + switch (char) { + case HYPHEN: + case SEMICOLON: + case SLASH: + case COLON: + case AT: + case AMPERSAND: + case EQUALS: + case PLUS: + case DOLLAR: + case PERIOD: + case TILDE: + case QUESTION: + case ASTERISK: + case SINGLE_QUOTE: + case LEFT_PAREN: + case RIGHT_PAREN: + case PERCENT: + return true; + default: + return (char >= NUMBER_0 && char <= NUMBER_9) || + (char >= LETTER_A && char <= LETTER_Z) || + (char >= LETTER_CAP_A && char <= LETTER_CAP_Z); + } + } + + /// Whether the current character is a valid anchor name character. + /// + /// See http://yaml.org/spec/1.2/spec.html#ns-anchor-name. + bool get _isAnchorChar { + if (!_isNonSpace) return false; + + switch (_scanner.peekChar()) { + case COMMA: + case LEFT_SQUARE: + case RIGHT_SQUARE: + case LEFT_CURLY: + case RIGHT_CURLY: + return false; + default: + return true; + } + } + + /// Whether the character at the current position is a decimal digit. + bool get _isDigit { + var char = _scanner.peekChar(); + return char != null && (char >= NUMBER_0 && char <= NUMBER_9); + } + + /// Whether the character at the current position is a hexidecimal + /// digit. + bool get _isHex { + var char = _scanner.peekChar(); + if (char == null) return false; + return (char >= NUMBER_0 && char <= NUMBER_9) || + (char >= LETTER_A && char <= LETTER_F) || + (char >= LETTER_CAP_A && char <= LETTER_CAP_F); + } + + /// Whether the character at the current position is a plain character. + /// + /// See http://yaml.org/spec/1.2/spec.html#ns-plain-char(c). + bool get _isPlainChar => _isPlainCharAt(0); + + /// Whether the character at the current position is a printable character + /// other than a line break or byte-order mark. + /// + /// See http://yaml.org/spec/1.2/spec.html#nb-char. + bool get _isNonBreak { + var char = _scanner.peekChar(); + if (char == null) return false; + switch (char) { + case LF: + case CR: + case BOM: + return false; + case TAB: + case NEL: + return true; + default: + return (char >= 0x00020 && char <= 0x00007E) || + (char >= 0x000A0 && char <= 0x00D7FF) || + (char >= 0x0E000 && char <= 0x00FFFD) || + (char >= 0x10000 && char <= 0x10FFFF); + } + } + + /// Whether the character at the current position is a printable character + /// other than whitespace. + /// + /// See http://yaml.org/spec/1.2/spec.html#nb-char. + bool get _isNonSpace { + var char = _scanner.peekChar(); + if (char == null) return false; + switch (char) { + case LF: + case CR: + case BOM: + case SP: + return false; + case NEL: + return true; + default: + return (char >= 0x00020 && char <= 0x00007E) || + (char >= 0x000A0 && char <= 0x00D7FF) || + (char >= 0x0E000 && char <= 0x00FFFD) || + (char >= 0x10000 && char <= 0x10FFFF); + } + } + + /// Returns Whether or not the current character begins a documentation + /// indicator. + /// + /// If so, this sets the scanner's last match to that indicator. + bool get _isDocumentIndicator { + return _scanner.column == 0 && _isBlankOrEndAt(3) && + (_scanner.matches('---') || _scanner.matches('...')); + } + + /// Creates a scanner that scans [source]. + /// + /// [sourceUrl] can be a String or a [Uri]. + Scanner(String source, {sourceUrl}) + : _scanner = new SpanScanner(source, sourceUrl: sourceUrl); + + /// Consumes and returns the next token. + Token scan() { + if (_streamEndProduced) throw new StateError("Out of tokens."); + if (!_tokenAvailable) _fetchMoreTokens(); + + var token = _tokens.removeFirst(); + _tokenAvailable = false; + _tokensParsed++; + _streamEndProduced = token is Token && + token.type == TokenType.STREAM_END; + return token; + } + + /// Consumes the next token and returns the one after that. + Token advance() { + scan(); + return peek(); + } + + /// Returns the next token without consuming it. + Token peek() { + if (_streamEndProduced) return null; + if (!_tokenAvailable) _fetchMoreTokens(); + return _tokens.first; + } + + /// Ensures that [_tokens] contains at least one token which can be returned. + void _fetchMoreTokens() { + while (true) { + if (_tokens.isNotEmpty) { + _staleSimpleKeys(); + + // If the current token could be a simple key, we need to scan more + // tokens until we determine whether it is or not. Otherwise we might + // not emit the `KEY` token before we emit the value of the key. + if (!_simpleKeys.any((key) => + key != null && key.tokenNumber == _tokensParsed)) { + break; + } + } + + _fetchNextToken(); + } + _tokenAvailable = true; + } + + /// The dispatcher for token fetchers. + void _fetchNextToken() { + if (!_streamStartProduced) { + _fetchStreamStart(); + return; + } + + _scanToNextToken(); + _staleSimpleKeys(); + _unrollIndent(_scanner.column); + + if (_scanner.isDone) { + _fetchStreamEnd(); + return; + } + + if (_scanner.column == 0) { + if (_scanner.peekChar() == PERCENT) { + _fetchDirective(); + return; + } + + if (_isBlankOrEndAt(3)) { + if (_scanner.matches('---')) { + _fetchDocumentIndicator(TokenType.DOCUMENT_START); + return; + } + + if (_scanner.matches('...')) { + _fetchDocumentIndicator(TokenType.DOCUMENT_END); + return; + } + } + } + + switch (_scanner.peekChar()) { + case LEFT_SQUARE: + _fetchFlowCollectionStart(TokenType.FLOW_SEQUENCE_START); + return; + case LEFT_CURLY: + _fetchFlowCollectionStart(TokenType.FLOW_MAPPING_START); + return; + case RIGHT_SQUARE: + _fetchFlowCollectionEnd(TokenType.FLOW_SEQUENCE_END); + return; + case RIGHT_CURLY: + _fetchFlowCollectionEnd(TokenType.FLOW_MAPPING_END); + return; + case COMMA: + _fetchFlowEntry(); + return; + case ASTERISK: + _fetchAnchor(anchor: false); + return; + case AMPERSAND: + _fetchAnchor(anchor: true); + return; + case EXCLAMATION: + _fetchTag(); + return; + case SINGLE_QUOTE: + _fetchFlowScalar(singleQuote: true); + return; + case DOUBLE_QUOTE: + _fetchFlowScalar(singleQuote: false); + return; + case VERTICAL_BAR: + if (!_inBlockContext) _invalidScalarCharacter(); + _fetchBlockScalar(literal: true); + return; + case RIGHT_ANGLE: + if (!_inBlockContext) _invalidScalarCharacter(); + _fetchBlockScalar(literal: false); + return; + case PERCENT: + case AT: + case GRAVE_ACCENT: + _invalidScalarCharacter(); + return; + + // These characters may sometimes begin plain scalars. + case HYPHEN: + if (_isPlainCharAt(1)) { + _fetchPlainScalar(); + } else { + _fetchBlockEntry(); + } + return; + case QUESTION: + if (_isPlainCharAt(1)) { + _fetchPlainScalar(); + } else { + _fetchKey(); + } + return; + case COLON: + if (!_inBlockContext && _tokens.isNotEmpty) { + // If a colon follows a "JSON-like" value (an explicit map or list, or + // a quoted string) it isn't required to have whitespace after it + // since it unambiguously describes a map. + var token = _tokens.last; + if (token.type == TokenType.FLOW_SEQUENCE_END || + token.type == TokenType.FLOW_MAPPING_END || + (token.type == TokenType.SCALAR && token.style.isQuoted)) { + _fetchValue(); + return; + } + } + + if (_isPlainCharAt(1)) { + _fetchPlainScalar(); + } else { + _fetchValue(); + } + return; + default: + if (!_isNonBreak) _invalidScalarCharacter(); + + _fetchPlainScalar(); + return; + } + + throw 'Inaccessible'; + } + + /// Throws an error about a disallowed character. + void _invalidScalarCharacter() => + _scanner.error("Unexpected character.", length: 1); + + /// Checks the list of potential simple keys and remove the positions that + /// cannot contain simple keys anymore. + void _staleSimpleKeys() { + for (var i = 0; i < _simpleKeys.length; i++) { + var key = _simpleKeys[i]; + if (key == null) continue; + + // libyaml requires that all simple keys be a single line and no longer + // than 1024 characters. However, in section 7.4.2 of the spec + // (http://yaml.org/spec/1.2/spec.html#id2790832), these restrictions are + // only applied when the curly braces are omitted. It's difficult to + // retain enough context to know which keys need to have the restriction + // placed on them, so for now we go the other direction and allow + // everything but multiline simple keys in a block context. + if (!_inBlockContext) continue; + + if (key.location.line == _scanner.line) continue; + + if (key.required) { + throw new YamlException("Expected ':'.", _scanner.emptySpan); + } + + _simpleKeys[i] = null; + } + } + + /// Checks if a simple key may start at the current position and saves it if + /// so. + void _saveSimpleKey() { + // A simple key is required at the current position if the scanner is in the + // block context and the current column coincides with the indentation + // level. + var required = _inBlockContext && _indent == _scanner.column; + + // A simple key is required only when it is the first token in the current + // line. Therefore it is always allowed. But we add a check anyway. + assert(_simpleKeyAllowed || !required); + + if (!_simpleKeyAllowed) return; + + // If the current position may start a simple key, save it. + _removeSimpleKey(); + _simpleKeys[_simpleKeys.length - 1] = new _SimpleKey( + _tokensParsed + _tokens.length, + _scanner.location, + required: required); + } + + /// Removes a potential simple key at the current flow level. + void _removeSimpleKey() { + var key = _simpleKeys.last; + if (key != null && key.required) { + throw new YamlException("Could not find expected ':' for simple key.", + key.location.pointSpan()); + } + + _simpleKeys[_simpleKeys.length - 1] = null; + } + + /// Increases the flow level and resizes the simple key list. + void _increaseFlowLevel() { + _simpleKeys.add(null); + } + + /// Decreases the flow level. + void _decreaseFlowLevel() { + if (_inBlockContext) return; + _simpleKeys.removeLast(); + } + + /// Pushes the current indentation level to the stack and sets the new level + /// if [column] is greater than [_indent]. + /// + /// If it is, appends or inserts the specified token into [_tokens]. If + /// [tokenNumber] is provided, the corresponding token will be replaced; + /// otherwise, the token will be added at the end. + void _rollIndent(int column, TokenType type, SourceLocation location, + {int tokenNumber}) { + if (!_inBlockContext) return; + if (_indent != -1 && _indent >= column) return; + + // Push the current indentation level to the stack and set the new + // indentation level. + _indents.add(column); + + // Create a token and insert it into the queue. + var token = new Token(type, location.pointSpan()); + if (tokenNumber == null) { + _tokens.add(token); + } else { + _tokens.insert(tokenNumber - _tokensParsed, token); + } + } + + /// Pops indentation levels from [_indents] until the current level becomes + /// less than or equal to [column]. + /// + /// For each indentation level, appends a [TokenType.BLOCK_END] token. + void _unrollIndent(int column) { + if (!_inBlockContext) return; + + while (_indent > column) { + _tokens.add(new Token(TokenType.BLOCK_END, _scanner.emptySpan)); + _indents.removeLast(); + } + } + + /// Pops indentation levels from [_indents] until the current level resets to + /// -1. + /// + /// For each indentation level, appends a [TokenType.BLOCK_END] token. + void _resetIndent() => _unrollIndent(-1); + + /// Produces a [TokenType.STREAM_START] token. + void _fetchStreamStart() { + // Much of libyaml's initialization logic here is done in variable + // initializers instead. + _streamStartProduced = true; + _tokens.add(new Token(TokenType.STREAM_START, _scanner.emptySpan)); + } + + /// Produces a [TokenType.STREAM_END] token. + void _fetchStreamEnd() { + _resetIndent(); + _removeSimpleKey(); + _simpleKeyAllowed = false; + _tokens.add(new Token(TokenType.STREAM_END, _scanner.emptySpan)); + } + + /// Produces a [TokenType.VERSION_DIRECTIVE] or [TokenType.TAG_DIRECTIVE] + /// token. + void _fetchDirective() { + _resetIndent(); + _removeSimpleKey(); + _simpleKeyAllowed = false; + var directive = _scanDirective(); + if (directive != null) _tokens.add(directive); + } + + /// Produces a [TokenType.DOCUMENT_START] or [TokenType.DOCUMENT_END] token. + void _fetchDocumentIndicator(TokenType type) { + _resetIndent(); + _removeSimpleKey(); + _simpleKeyAllowed = false; + + // Consume the indicator token. + var start = _scanner.state; + _scanner.readChar(); + _scanner.readChar(); + _scanner.readChar(); + + _tokens.add(new Token(type, _scanner.spanFrom(start))); + } + + /// Produces a [TokenType.FLOW_SEQUENCE_START] or + /// [TokenType.FLOW_MAPPING_START] token. + void _fetchFlowCollectionStart(TokenType type) { + _saveSimpleKey(); + _increaseFlowLevel(); + _simpleKeyAllowed = true; + _addCharToken(type); + } + + /// Produces a [TokenType.FLOW_SEQUENCE_END] or [TokenType.FLOW_MAPPING_END] + /// token. + void _fetchFlowCollectionEnd(TokenType type) { + _removeSimpleKey(); + _decreaseFlowLevel(); + _simpleKeyAllowed = false; + _addCharToken(type); + } + + /// Produces a [TokenType.FLOW_ENTRY] token. + void _fetchFlowEntry() { + _removeSimpleKey(); + _simpleKeyAllowed = true; + _addCharToken(TokenType.FLOW_ENTRY); + } + + /// Produces a [TokenType.BLOCK_ENTRY] token. + void _fetchBlockEntry() { + if (_inBlockContext) { + if (!_simpleKeyAllowed) { + throw new YamlException( + "Block sequence entries are not allowed in this context.", + _scanner.emptySpan); + } + + _rollIndent( + _scanner.column, + TokenType.BLOCK_SEQUENCE_START, + _scanner.emptySpan.start); + } else { + // It is an error for the '-' indicator to occur in the flow context, but + // we let the Parser detect and report it because it's able to point to + // the context. + } + + _removeSimpleKey(); + _simpleKeyAllowed = true; + _addCharToken(TokenType.BLOCK_ENTRY); + } + + /// Produces the [TokenType.KEY] token. + void _fetchKey() { + if (_inBlockContext) { + if (!_simpleKeyAllowed) { + throw new YamlException("Mapping keys are not allowed in this context.", + _scanner.emptySpan); + } + + _rollIndent( + _scanner.column, + TokenType.BLOCK_MAPPING_START, + _scanner.emptySpan.start); + } + + // Simple keys are allowed after `?` in a block context. + _simpleKeyAllowed = _inBlockContext; + _addCharToken(TokenType.KEY); + } + + /// Produces the [TokenType.VALUE] token. + void _fetchValue() { + var simpleKey = _simpleKeys.last; + if (simpleKey != null) { + // Add a [TokenType.KEY] directive before the first token of the simple + // key so the parser knows that it's part of a key/value pair. + _tokens.insert(simpleKey.tokenNumber - _tokensParsed, + new Token(TokenType.KEY, simpleKey.location.pointSpan())); + + // In the block context, we may need to add the + // [TokenType.BLOCK_MAPPING_START] token. + _rollIndent( + simpleKey.location.column, + TokenType.BLOCK_MAPPING_START, + simpleKey.location, + tokenNumber: simpleKey.tokenNumber); + + // Remove the simple key. + _simpleKeys[_simpleKeys.length - 1] = null; + + // A simple key cannot follow another simple key. + _simpleKeyAllowed = false; + } else if (_inBlockContext) { + // If we're here, we've found the ':' indicator following a complex key. + + if (!_simpleKeyAllowed) { + throw new YamlException( + "Mapping values are not allowed in this context.", + _scanner.emptySpan); + } + + _rollIndent( + _scanner.column, + TokenType.BLOCK_MAPPING_START, + _scanner.location); + _simpleKeyAllowed = true; + } else if (_simpleKeyAllowed) { + // If we're here, we've found the ':' indicator with an empty key. This + // behavior differs from libyaml, which disallows empty implicit keys. + _simpleKeyAllowed = false; + _addCharToken(TokenType.KEY); + } + + _addCharToken(TokenType.VALUE); + } + + /// Adds a token with [type] to [_tokens]. + /// + /// The span of the new token is the current character. + void _addCharToken(TokenType type) { + var start = _scanner.state; + _scanner.readChar(); + _tokens.add(new Token(type, _scanner.spanFrom(start))); + } + + /// Produces a [TokenType.ALIAS] or [TokenType.ANCHOR] token. + void _fetchAnchor({bool anchor: true}) { + _saveSimpleKey(); + _simpleKeyAllowed = false; + _tokens.add(_scanAnchor(anchor: anchor)); + } + + /// Produces a [TokenType.TAG] token. + void _fetchTag() { + _saveSimpleKey(); + _simpleKeyAllowed = false; + _tokens.add(_scanTag()); + } + + /// Produces a [TokenType.SCALAR] token with style [ScalarStyle.LITERAL] or + /// [ScalarStyle.FOLDED]. + void _fetchBlockScalar({bool literal: false}) { + _removeSimpleKey(); + _simpleKeyAllowed = true; + _tokens.add(_scanBlockScalar(literal: literal)); + } + + /// Produces a [TokenType.SCALAR] token with style [ScalarStyle.SINGLE_QUOTED] + /// or [ScalarStyle.DOUBLE_QUOTED]. + void _fetchFlowScalar({bool singleQuote: false}) { + _saveSimpleKey(); + _simpleKeyAllowed = false; + _tokens.add(_scanFlowScalar(singleQuote: singleQuote)); + } + + /// Produces a [TokenType.SCALAR] token with style [ScalarStyle.PLAIN]. + void _fetchPlainScalar() { + _saveSimpleKey(); + _simpleKeyAllowed = false; + _tokens.add(_scanPlainScalar()); + } + + /// Eats whitespace and comments until the next token is found. + void _scanToNextToken() { + var afterLineBreak = false; + while (true) { + // Allow the BOM to start a line. + if (_scanner.column == 0) _scanner.scan("\uFEFF"); + + // Eat whitespace. + // + // libyaml disallows tabs after "-", "?", or ":", but the spec allows + // them. See section 6.2: http://yaml.org/spec/1.2/spec.html#id2778241. + while (_scanner.peekChar() == SP || + ((!_inBlockContext || !afterLineBreak) && + _scanner.peekChar() == TAB)) { + _scanner.readChar(); + } + + if (_scanner.peekChar() == TAB) { + _scanner.error("Tab characters are not allowed as indentation.", + length: 1); + } + + // Eat a comment until a line break. + _skipComment(); + + // If we're at a line break, eat it. + if (_isBreak) { + _skipLine(); + + // In the block context, a new line may start a simple key. + if (_inBlockContext) _simpleKeyAllowed = true; + afterLineBreak = true; + } else { + // Otherwise we've found a token. + break; + } + } + } + + /// Scans a [TokenType.YAML_DIRECTIVE] or [TokenType.TAG_DIRECTIVE] token. + /// + /// %YAML 1.2 # a comment \n + /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + /// %TAG !yaml! tag:yaml.org,2002: \n + /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Token _scanDirective() { + var start = _scanner.state; + + // Eat '%'. + _scanner.readChar(); + + var token; + var name = _scanDirectiveName(); + if (name == "YAML") { + token = _scanVersionDirectiveValue(start); + } else if (name == "TAG") { + token = _scanTagDirectiveValue(start); + } else { + warn("Warning: unknown directive.", _scanner.spanFrom(start)); + + // libyaml doesn't support unknown directives, but the spec says to ignore + // them and warn: http://yaml.org/spec/1.2/spec.html#id2781147. + while (!_isBreakOrEnd) { + _scanner.readChar(); + } + + return null; + } + + // Eat the rest of the line, including any comments. + _skipBlanks(); + _skipComment(); + + if (!_isBreakOrEnd) { + throw new YamlException( + "Expected comment or line break after directive.", + _scanner.spanFrom(start)); + } + + _skipLine(); + return token; + } + + /// Scans a directive name. + /// + /// %YAML 1.2 # a comment \n + /// ^^^^ + /// %TAG !yaml! tag:yaml.org,2002: \n + /// ^^^ + String _scanDirectiveName() { + // libyaml only allows word characters in directive names, but the spec + // disagrees: http://yaml.org/spec/1.2/spec.html#ns-directive-name. + var start = _scanner.position; + while (_isNonSpace) { + _scanner.readChar(); + } + + var name = _scanner.substring(start); + if (name.isEmpty) { + throw new YamlException("Expected directive name.", _scanner.emptySpan); + } else if (!_isBlankOrEnd) { + throw new YamlException( + "Unexpected character in directive name.", _scanner.emptySpan); + } + + return name; + } + + /// Scans the value of a version directive. + /// + /// %YAML 1.2 # a comment \n + /// ^^^^^^ + Token _scanVersionDirectiveValue(LineScannerState start) { + _skipBlanks(); + + var major = _scanVersionDirectiveNumber(); + _scanner.expect('.'); + var minor = _scanVersionDirectiveNumber(); + + return new VersionDirectiveToken(_scanner.spanFrom(start), major, minor); + } + + /// Scans the version number of a version directive. + /// + /// %YAML 1.2 # a comment \n + /// ^ + /// %YAML 1.2 # a comment \n + /// ^ + int _scanVersionDirectiveNumber() { + var start = _scanner.position; + while (_isDigit) { + _scanner.readChar(); + } + + var number = _scanner.substring(start); + if (number.isEmpty) { + throw new YamlException("Expected version number.", _scanner.emptySpan); + } + + return int.parse(number); + } + + /// Scans the value of a tag directive. + /// + /// %TAG !yaml! tag:yaml.org,2002: \n + /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Token _scanTagDirectiveValue(LineScannerState start) { + _skipBlanks(); + + var handle = _scanTagHandle(directive: true); + if (!_isBlank) { + throw new YamlException("Expected whitespace.", _scanner.emptySpan); + } + + _skipBlanks(); + + var prefix = _scanTagUri(); + if (!_isBlankOrEnd) { + throw new YamlException("Expected whitespace.", _scanner.emptySpan); + } + + return new TagDirectiveToken(_scanner.spanFrom(start), handle, prefix); + } + + /// Scans a [TokenType.ANCHOR] token. + Token _scanAnchor({bool anchor: true}) { + var start = _scanner.state; + + // Eat the indicator character. + _scanner.readChar(); + + // libyaml only allows word characters in anchor names, but the spec + // disagrees: http://yaml.org/spec/1.2/spec.html#ns-anchor-char. + var startPosition = _scanner.position; + while (_isAnchorChar) { + _scanner.readChar(); + } + var name = _scanner.substring(startPosition); + + var next = _scanner.peekChar(); + if (name.isEmpty || + (!_isBlankOrEnd && next != QUESTION && next != COLON && + next != COMMA && next != RIGHT_SQUARE && next != RIGHT_CURLY && + next != PERCENT && next != AT && next != GRAVE_ACCENT)) { + throw new YamlException("Expected alphanumeric character.", + _scanner.emptySpan); + } + + if (anchor) { + return new AnchorToken(_scanner.spanFrom(start), name); + } else { + return new AliasToken(_scanner.spanFrom(start), name); + } + } + + /// Scans a [TokenType.TAG] token. + Token _scanTag() { + var handle; + var suffix; + var start = _scanner.state; + + // Check if the tag is in the canonical form. + if (_scanner.peekChar(1) == LEFT_ANGLE) { + // Eat '!<'. + _scanner.readChar(); + _scanner.readChar(); + + handle = ''; + suffix = _scanTagUri(); + + _scanner.expect('>'); + } else { + // The tag has either the '!suffix' or the '!handle!suffix' form. + + // First, try to scan a handle. + handle = _scanTagHandle(); + + if (handle.length > 1 && handle.startsWith('!') && handle.endsWith('!')) { + suffix = _scanTagUri(flowSeparators: false); + } else { + suffix = _scanTagUri(head: handle, flowSeparators: false); + + // There was no explicit handle. + if (suffix.isEmpty) { + // This is the special '!' tag. + handle = null; + suffix = '!'; + } else { + handle = '!'; + } + } + } + + // libyaml insists on whitespace after a tag, but example 7.2 indicates + // that it's not required: http://yaml.org/spec/1.2/spec.html#id2786720. + + return new TagToken(_scanner.spanFrom(start), handle, suffix); + } + + /// Scans a tag handle. + String _scanTagHandle({bool directive: false}) { + _scanner.expect('!'); + + var buffer = new StringBuffer('!'); + + // libyaml only allows word characters in tags, but the spec disagrees: + // http://yaml.org/spec/1.2/spec.html#ns-tag-char. + var start = _scanner.position; + while (_isTagChar) { + _scanner.readChar(); + } + buffer.write(_scanner.substring(start)); + + if (_scanner.peekChar() == EXCLAMATION) { + buffer.writeCharCode(_scanner.readChar()); + } else { + // It's either the '!' tag or not really a tag handle. If it's a %TAG + // directive, it's an error. If it's a tag token, it must be part of a + // URI. + if (directive && buffer.toString() != '!') _scanner.expect('!'); + } + + return buffer.toString(); + } + + /// Scans a tag URI. + /// + /// [head] is the initial portion of the tag that's already been scanned. + /// [flowSeparators] indicates whether the tag URI can contain flow + /// separators. + String _scanTagUri({String head, bool flowSeparators: true}) { + var length = head == null ? 0 : head.length; + var buffer = new StringBuffer(); + + // Copy the head if needed. + // + // Note that we don't copy the leading '!' character. + if (length > 1) buffer.write(head.substring(1)); + + // The set of characters that may appear in URI is as follows: + // + // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', + // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', + // '%'. + // + // In a shorthand tag annotation, the flow separators ',', '[', and ']' are + // disallowed. + var start = _scanner.position; + var char = _scanner.peekChar(); + while (_isTagChar || (flowSeparators && + (char == COMMA || char == LEFT_SQUARE || char == RIGHT_SQUARE))) { + _scanner.readChar(); + char = _scanner.peekChar(); + } + + // libyaml manually decodes the URL, but we don't have to do that. + return Uri.decodeFull(_scanner.substring(start)); + } + + /// Scans a block scalar. + Token _scanBlockScalar({bool literal: false}) { + var start = _scanner.state; + + // Eat the indicator '|' or '>'. + _scanner.readChar(); + + // Check for a chomping indicator. + var chomping = _Chomping.CLIP; + var increment = 0; + var char = _scanner.peekChar(); + if (char == PLUS || char == HYPHEN) { + chomping = char == PLUS ? _Chomping.KEEP : _Chomping.STRIP; + _scanner.readChar(); + + // Check for an indentation indicator. + if (_isDigit) { + // Check that the indentation is greater than 0. + if (_scanner.peekChar() == NUMBER_0) { + throw new YamlException( + "0 may not be used as an indentation indicator.", + _scanner.spanFrom(start)); + } + + increment = _scanner.readChar() - NUMBER_0; + } + } else if (_isDigit) { + // Do the same as above, but in the opposite order. + if (_scanner.peekChar() == NUMBER_0) { + throw new YamlException( + "0 may not be used as an indentation indicator.", + _scanner.spanFrom(start)); + } + + increment = _scanner.readChar() - NUMBER_0; + + char = _scanner.peekChar(); + if (char == PLUS || char == HYPHEN) { + chomping = char == PLUS ? _Chomping.KEEP : _Chomping.STRIP; + _scanner.readChar(); + } + } + + // Eat whitespace and comments to the end of the line. + _skipBlanks(); + _skipComment(); + + // Check if we're at the end of the line. + if (!_isBreakOrEnd) { + throw new YamlException("Expected comment or line break.", + _scanner.emptySpan); + } + + _skipLine(); + + // If the block scalar has an explicit indentation indicator, add that to + // the current indentation to get the indentation level for the scalar's + // contents. + var indent = 0; + if (increment != 0) { + indent = _indent >= 0 ? _indent + increment : increment; + } + + // Scan the leading line breaks to determine the indentation level if + // needed. + var pair = _scanBlockScalarBreaks(indent); + indent = pair.first; + var trailingBreaks = pair.last; + + // Scan the block scalar contents. + var buffer = new StringBuffer(); + var leadingBreak = ''; + var leadingBlank = false; + var trailingBlank = false; + while (_scanner.column == indent && !_scanner.isDone) { + // Check for a document indicator. libyaml doesn't do this, but the spec + // mandates it. See example 9.5: + // http://yaml.org/spec/1.2/spec.html#id2801606. + if (_isDocumentIndicator) break; + + // We are at the beginning of a non-empty line. + + // Is there trailing whitespace? + trailingBlank = _isBlank; + + // Check if we need to fold the leading line break. + if (!literal && leadingBreak.isNotEmpty && !leadingBlank && + !trailingBlank) { + // Do we need to join the lines with a space? + if (trailingBreaks.isEmpty) buffer.writeCharCode(SP); + } else { + buffer.write(leadingBreak); + } + leadingBreak = ''; + + // Append the remaining line breaks. + buffer.write(trailingBreaks); + + // Is there leading whitespace? + leadingBlank = _isBlank; + + var startPosition = _scanner.position; + while (!_isBreakOrEnd) { + _scanner.readChar(); + } + buffer.write(_scanner.substring(startPosition)); + + // libyaml always reads a line here, but this breaks on block scalars at + // the end of the document that end without newlines. See example 8.1: + // http://yaml.org/spec/1.2/spec.html#id2793888. + if (!_scanner.isDone) leadingBreak = _readLine(); + + // Eat the following indentation and spaces. + var pair = _scanBlockScalarBreaks(indent); + indent = pair.first; + trailingBreaks = pair.last; + } + + // Chomp the tail. + if (chomping != _Chomping.STRIP) buffer.write(leadingBreak); + if (chomping == _Chomping.KEEP) buffer.write(trailingBreaks); + + return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), + literal ? ScalarStyle.LITERAL : ScalarStyle.FOLDED); + } + + /// Scans indentation spaces and line breaks for a block scalar. + /// + /// Determines the intendation level if needed. Returns the new indentation + /// level and the text of the line breaks. + Pair _scanBlockScalarBreaks(int indent) { + var maxIndent = 0; + var breaks = new StringBuffer(); + + while (true) { + while ((indent == 0 || _scanner.column < indent) && + _scanner.peekChar() == SP) { + _scanner.readChar(); + } + + if (_scanner.column > maxIndent) maxIndent = _scanner.column; + + // libyaml throws an error here if a tab character is detected, but the + // spec treats tabs like any other non-space character. See example 8.2: + // http://yaml.org/spec/1.2/spec.html#id2794311. + + if (!_isBreak) break; + breaks.write(_readLine()); + } + + if (indent == 0) { + indent = maxIndent; + if (indent < _indent + 1) indent = _indent + 1; + + // libyaml forces indent to be at least 1 here, but that doesn't seem to + // be supported by the spec. + } + + return new Pair(indent, breaks.toString()); + } + + // Scans a quoted scalar. + Token _scanFlowScalar({bool singleQuote: false}) { + var start = _scanner.state; + var buffer = new StringBuffer(); + + // Eat the left quote. + _scanner.readChar(); + + while (true) { + // Check that there are no document indicators at the beginning of the + // line. + if (_isDocumentIndicator) { + _scanner.error("Unexpected document indicator."); + } + + if (_scanner.isDone) { + throw new YamlException("Unexpected end of file.", _scanner.emptySpan); + } + + var leadingBlanks = false; + while (!_isBlankOrEnd) { + var char = _scanner.peekChar(); + if (singleQuote && char == SINGLE_QUOTE && + _scanner.peekChar(1) == SINGLE_QUOTE) { + // An escaped single quote. + _scanner.readChar(); + _scanner.readChar(); + buffer.writeCharCode(SINGLE_QUOTE); + } else if (char == (singleQuote ? SINGLE_QUOTE : DOUBLE_QUOTE)) { + // The closing quote. + break; + } else if (!singleQuote && char == BACKSLASH && _isBreakAt(1)) { + // An escaped newline. + _scanner.readChar(); + _skipLine(); + leadingBlanks = true; + break; + } else if (!singleQuote && char == BACKSLASH) { + var escapeStart = _scanner.state; + + // An escape sequence. + var codeLength = null; + switch (_scanner.peekChar(1)) { + case NUMBER_0: + buffer.writeCharCode(NULL); + break; + case LETTER_A: + buffer.writeCharCode(BELL); + break; + case LETTER_B: + buffer.writeCharCode(BACKSPACE); + break; + case LETTER_T: + case TAB: + buffer.writeCharCode(TAB); + break; + case LETTER_N: + buffer.writeCharCode(LF); + break; + case LETTER_V: + buffer.writeCharCode(VERTICAL_TAB); + break; + case LETTER_F: + buffer.writeCharCode(FORM_FEED); + break; + case LETTER_R: + buffer.writeCharCode(CR); + break; + case LETTER_E: + buffer.writeCharCode(ESCAPE); + break; + case SP: + case DOUBLE_QUOTE: + case SLASH: + case BACKSLASH: + // libyaml doesn't support an escaped forward slash, but it was + // added in YAML 1.2. See section 5.7: + // http://yaml.org/spec/1.2/spec.html#id2776092 + buffer.writeCharCode(_scanner.peekChar(1)); + break; + case LETTER_CAP_N: + buffer.writeCharCode(NEL); + break; + case UNDERSCORE: + buffer.writeCharCode(NBSP); + break; + case LETTER_CAP_L: + buffer.writeCharCode(LINE_SEPARATOR); + break; + case LETTER_CAP_P: + buffer.writeCharCode(PARAGRAPH_SEPARATOR); + break; + case LETTER_X: + codeLength = 2; + break; + case LETTER_U: + codeLength = 4; + break; + case LETTER_CAP_U: + codeLength = 8; + break; + default: + throw new YamlException("Unknown escape character.", + _scanner.spanFrom(escapeStart)); + } + + _scanner.readChar(); + _scanner.readChar(); + + if (codeLength != null) { + var value = 0; + for (var i = 0; i < codeLength; i++) { + if (!_isHex) { + _scanner.readChar(); + throw new YamlException( + "Expected $codeLength-digit hexidecimal number.", + _scanner.spanFrom(escapeStart)); + } + + value = (value << 4) + _asHex(_scanner.readChar()); + } + + // Check the value and write the character. + if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) { + throw new YamlException( + "Invalid Unicode character escape code.", + _scanner.spanFrom(escapeStart)); + } + + buffer.writeCharCode(value); + } + } else { + buffer.writeCharCode(_scanner.readChar()); + } + } + + // Check if we're at the end of a scalar. + if (_scanner.peekChar() == (singleQuote ? SINGLE_QUOTE : DOUBLE_QUOTE)) { + break; + } + + var whitespace = new StringBuffer(); + var leadingBreak = ''; + var trailingBreaks = new StringBuffer(); + while (_isBlank || _isBreak) { + if (_isBlank) { + // Consume a space or a tab. + if (!leadingBlanks) { + whitespace.writeCharCode(_scanner.readChar()); + } else { + _scanner.readChar(); + } + } else { + // Check if it's a first line break. + if (!leadingBlanks) { + whitespace.clear(); + leadingBreak = _readLine(); + leadingBlanks = true; + } else { + trailingBreaks.write(_readLine()); + } + } + } + + // Join the whitespace or fold line breaks. + if (leadingBlanks) { + if (leadingBreak.isNotEmpty && trailingBreaks.isEmpty) { + buffer.writeCharCode(SP); + } else { + buffer.write(trailingBreaks); + } + } else { + buffer.write(whitespace); + whitespace.clear(); + } + } + + // Eat the right quote. + _scanner.readChar(); + + return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), + singleQuote ? ScalarStyle.SINGLE_QUOTED : ScalarStyle.DOUBLE_QUOTED); + } + + /// Scans a plain scalar. + Token _scanPlainScalar() { + var start = _scanner.state; + var buffer = new StringBuffer(); + var leadingBreak = ''; + var trailingBreaks = ''; + var whitespace = new StringBuffer(); + var indent = _indent + 1; + + while (true) { + // Check for a document indicator. + if (_isDocumentIndicator) break; + + // Check for a comment. + if (_scanner.peekChar() == HASH) break; + + if (_isPlainChar) { + // Join the whitespace or fold line breaks. + if (leadingBreak.isNotEmpty) { + if (trailingBreaks.isEmpty) { + buffer.writeCharCode(SP); + } else { + buffer.write(trailingBreaks); + } + leadingBreak = ''; + trailingBreaks = ''; + } else { + buffer.write(whitespace); + whitespace.clear(); + } + } + + // libyaml's notion of valid identifiers differs substantially from YAML + // 1.2's. We use [_isPlainChar] instead of libyaml's character here. + var startPosition = _scanner.position; + while (_isPlainChar) { + _scanner.readChar(); + } + buffer.write(_scanner.substring(startPosition)); + + // Is it the end? + if (!_isBlank && !_isBreak) break; + + while (_isBlank || _isBreak) { + if (_isBlank) { + // Check for a tab character messing up the intendation. + if (leadingBreak.isNotEmpty && _scanner.column < indent && + _scanner.peekChar() == TAB) { + _scanner.error("Expected a space but found a tab.", length: 1); + } + + if (leadingBreak.isEmpty) { + whitespace.writeCharCode(_scanner.readChar()); + } else { + _scanner.readChar(); + } + } else { + // Check if it's a first line break. + if (leadingBreak.isEmpty) { + leadingBreak = _readLine(); + whitespace.clear(); + } else { + trailingBreaks = _readLine(); + } + } + } + + // Check the indentation level. + if (_inBlockContext && _scanner.column < indent) break; + } + + // Allow a simple key after a plain scalar with leading blanks. + if (leadingBreak.isNotEmpty) _simpleKeyAllowed = true; + + return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), + ScalarStyle.PLAIN); + } + + /// Moves past the current line break, if there is one. + void _skipLine() { + var char = _scanner.peekChar(); + if (char != CR && char != LF) return; + _scanner.readChar(); + if (char == CR && _scanner.peekChar() == LF) _scanner.readChar(); + } + + // Moves past the current line break and returns a newline. + String _readLine() { + var char = _scanner.peekChar(); + + // libyaml supports NEL, PS, and LS characters as line separators, but this + // is explicitly forbidden in section 5.4 of the YAML spec. + if (char != CR && char != LF) { + throw new YamlException("Expected newline.", _scanner.emptySpan); + } + + _scanner.readChar(); + // CR LF | CR | LF -> LF + if (char == CR && _scanner.peekChar() == LF) _scanner.readChar(); + return "\n"; + } + + // Returns whether the character at [offset] is whitespace. + bool _isBlankAt(int offset) { + var char = _scanner.peekChar(offset); + return char == SP || char == TAB; + } + + // Returns whether the character at [offset] is a line break. + bool _isBreakAt(int offset) { + // Libyaml considers NEL, LS, and PS to be line breaks as well, but that's + // contrary to the spec. + var char = _scanner.peekChar(offset); + return char == CR || char == LF; + } + + // Returns whether the character at [offset] is whitespace or past the end of + // the source. + bool _isBlankOrEndAt(int offset) { + var char = _scanner.peekChar(offset); + return char == null || char == SP || char == TAB || char == CR || + char == LF; + } + + /// Returns whether the character at [offset] is a plain character. + /// + /// See http://yaml.org/spec/1.2/spec.html#ns-plain-char(c). + bool _isPlainCharAt(int offset) { + switch (_scanner.peekChar(offset)) { + case COLON: + return _isPlainSafeAt(offset + 1); + case HASH: + var previous = _scanner.peekChar(offset - 1); + return previous != SP && previous != TAB; + default: + return _isPlainSafeAt(offset); + } + } + + /// Returns whether the character at [offset] is a plain-safe character. + /// + /// See http://yaml.org/spec/1.2/spec.html#ns-plain-safe(c). + bool _isPlainSafeAt(int offset) { + var char = _scanner.peekChar(offset); + switch (char) { + case COMMA: + case LEFT_SQUARE: + case RIGHT_SQUARE: + case LEFT_CURLY: + case RIGHT_CURLY: + // These characters are delimiters in a flow context and thus are only + // safe in a block context. + return _inBlockContext; + case SP: + case TAB: + case LF: + case CR: + case BOM: + return false; + case NEL: + return true; + default: + return char != null && + ((char >= 0x00020 && char <= 0x00007E) || + (char >= 0x000A0 && char <= 0x00D7FF) || + (char >= 0x0E000 && char <= 0x00FFFD) || + (char >= 0x10000 && char <= 0x10FFFF)); + } + } + + /// Returns the hexidecimal value of [char]. + int _asHex(int char) { + if (char <= NUMBER_9) return char - NUMBER_0; + if (char <= LETTER_CAP_F) return 10 + char - LETTER_CAP_A; + return 10 + char - LETTER_A; + } + + /// Moves the scanner past any blank characters. + void _skipBlanks() { + while (_isBlank) { + _scanner.readChar(); + } + } + + /// Moves the scanner past a comment, if one starts at the current position. + void _skipComment() { + if (_scanner.peekChar() != HASH) return; + while (!_isBreakOrEnd) { + _scanner.readChar(); + } + } +} + +/// A record of the location of a potential simple key. +class _SimpleKey { + /// The index of the token that begins the simple key. + /// + /// This is the index relative to all tokens emitted, rather than relative to + /// [_tokens]. + final int tokenNumber; + + /// The source location of the beginning of the simple key. + /// + /// This is used for error reporting and for determining when a simple key is + /// no longer on the current line. + final SourceLocation location; + + /// Whether this key must exist for the document to be scanned. + final bool required; + + _SimpleKey(this.tokenNumber, this.location, {bool required}) + : required = required; +} + +/// An enum of chomping indicators that describe how to handle trailing +/// whitespace for a block scalar. +/// +/// See http://yaml.org/spec/1.2/spec.html#id2794534. +class _Chomping { + /// All trailing whitespace is discarded. + static const STRIP = const _Chomping("STRIP"); + + /// A single trailing newline is retained. + static const CLIP = const _Chomping("CLIP"); + + /// All trailing whitespace is preserved. + static const KEEP = const _Chomping("KEEP"); + + final String name; + + const _Chomping(this.name); + + String toString() => name; +} diff --git a/pkgs/yaml/lib/src/style.dart b/pkgs/yaml/lib/src/style.dart new file mode 100644 index 000000000..6305fce79 --- /dev/null +++ b/pkgs/yaml/lib/src/style.dart @@ -0,0 +1,73 @@ +// Copyright (c) 2014, 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 yaml.style; + +/// An enum of source scalar styles. +class ScalarStyle { + /// No source style was specified. + /// + /// This usually indicates a scalar constructed with [YamlScalar.wrap]. + static const ANY = const ScalarStyle._("ANY"); + + /// The plain scalar style, unquoted and without a prefix. + /// + /// See http://yaml.org/spec/1.2/spec.html#style/flow/plain. + static const PLAIN = const ScalarStyle._("PLAIN"); + + /// The literal scalar style, with a `|` prefix. + /// + /// See http://yaml.org/spec/1.2/spec.html#id2795688. + static const LITERAL = const ScalarStyle._("LITERAL"); + + + /// The folded scalar style, with a `>` prefix. + /// + /// See http://yaml.org/spec/1.2/spec.html#id2796251. + static const FOLDED = const ScalarStyle._("FOLDED"); + + /// The single-quoted scalar style. + /// + /// See http://yaml.org/spec/1.2/spec.html#style/flow/single-quoted. + static const SINGLE_QUOTED = const ScalarStyle._("SINGLE_QUOTED"); + + /// The double-quoted scalar style. + /// + /// See http://yaml.org/spec/1.2/spec.html#style/flow/double-quoted. + static const DOUBLE_QUOTED = const ScalarStyle._("DOUBLE_QUOTED"); + + final String name; + + /// Whether this is a quoted style ([SINGLE_QUOTED] or [DOUBLE_QUOTED]). + bool get isQuoted => this == SINGLE_QUOTED || this == DOUBLE_QUOTED; + + const ScalarStyle._(this.name); + + String toString() => name; +} + +/// An enum of collection styles. +class CollectionStyle { + /// No source style was specified. + /// + /// This usually indicates a collection constructed with [YamlList.wrap] or + /// [YamlMap.wrap]. + static const ANY = const CollectionStyle._("ANY"); + + /// The indentation-based block style. + /// + /// See http://yaml.org/spec/1.2/spec.html#id2797293. + static const BLOCK = const CollectionStyle._("BLOCK"); + + /// The delimiter-based block style. + /// + /// See http://yaml.org/spec/1.2/spec.html#id2790088. + static const FLOW = const CollectionStyle._("FLOW"); + + final String name; + + const CollectionStyle._(this.name); + + String toString() => name; +} diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart new file mode 100644 index 000000000..20ae547c6 --- /dev/null +++ b/pkgs/yaml/lib/src/token.dart @@ -0,0 +1,148 @@ +// Copyright (c) 2014, 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 yaml.token; + +import 'package:source_span/source_span.dart'; + +import 'style.dart'; + +/// A token emitted by a [Scanner]. +class Token { + /// The token type. + final TokenType type; + + /// The span associated with the token. + final FileSpan span; + + Token(this.type, this.span); + + String toString() => type.toString(); +} + +/// A token representing a `%YAML` directive. +class VersionDirectiveToken implements Token { + get type => TokenType.VERSION_DIRECTIVE; + final FileSpan span; + + /// The declared major version of the document. + final int major; + + /// The declared minor version of the document. + final int minor; + + VersionDirectiveToken(this.span, this.major, this.minor); + + String toString() => "VERSION_DIRECTIVE $major.$minor"; +} + +/// A token representing a `%TAG` directive. +class TagDirectiveToken implements Token { + get type => TokenType.TAG_DIRECTIVE; + final FileSpan span; + + /// The tag handle used in the document. + final String handle; + + /// The tag prefix that the handle maps to. + final String prefix; + + TagDirectiveToken(this.span, this.handle, this.prefix); + + String toString() => "TAG_DIRECTIVE $handle $prefix"; +} + +/// A token representing an anchor (`&foo`). +class AnchorToken implements Token { + get type => TokenType.ANCHOR; + final FileSpan span; + + /// The name of the anchor. + final String name; + + AnchorToken(this.span, this.name); + + String toString() => "ANCHOR $name"; +} + +/// A token representing an alias (`*foo`). +class AliasToken implements Token { + get type => TokenType.ALIAS; + final FileSpan span; + + /// The name of the anchor. + final String name; + + AliasToken(this.span, this.name); + + String toString() => "ALIAS $name"; +} + +/// A token representing a tag (`!foo`). +class TagToken implements Token { + get type => TokenType.TAG; + final FileSpan span; + + /// The tag handle. + final String handle; + + /// The tag suffix, or `null`. + final String suffix; + + TagToken(this.span, this.handle, this.suffix); + + String toString() => "TAG $handle $suffix"; +} + +/// A tkoen representing a scalar value. +class ScalarToken implements Token { + get type => TokenType.SCALAR; + final FileSpan span; + + /// The contents of the scalar. + final String value; + + /// The style of the scalar in the original source. + final ScalarStyle style; + + ScalarToken(this.span, this.value, this.style); + + String toString() => "SCALAR $style \"$value\""; +} + +/// An enum of types of [Token] object. +class TokenType { + static const STREAM_START = const TokenType._("STREAM_START"); + static const STREAM_END = const TokenType._("STREAM_END"); + + static const VERSION_DIRECTIVE = const TokenType._("VERSION_DIRECTIVE"); + static const TAG_DIRECTIVE = const TokenType._("TAG_DIRECTIVE"); + static const DOCUMENT_START = const TokenType._("DOCUMENT_START"); + static const DOCUMENT_END = const TokenType._("DOCUMENT_END"); + + static const BLOCK_SEQUENCE_START = const TokenType._("BLOCK_SEQUENCE_START"); + static const BLOCK_MAPPING_START = const TokenType._("BLOCK_MAPPING_START"); + static const BLOCK_END = const TokenType._("BLOCK_END"); + + static const FLOW_SEQUENCE_START = const TokenType._("FLOW_SEQUENCE_START"); + static const FLOW_SEQUENCE_END = const TokenType._("FLOW_SEQUENCE_END"); + static const FLOW_MAPPING_START = const TokenType._("FLOW_MAPPING_START"); + static const FLOW_MAPPING_END = const TokenType._("FLOW_MAPPING_END"); + + static const BLOCK_ENTRY = const TokenType._("BLOCK_ENTRY"); + static const FLOW_ENTRY = const TokenType._("FLOW_ENTRY"); + static const KEY = const TokenType._("KEY"); + static const VALUE = const TokenType._("VALUE"); + + static const ALIAS = const TokenType._("ALIAS"); + static const ANCHOR = const TokenType._("ANCHOR"); + static const TAG = const TokenType._("TAG"); + static const SCALAR = const TokenType._("SCALAR"); + + final String name; + + const TokenType._(this.name); + + String toString() => name; +} diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 84c1113a0..445221fe4 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -4,6 +4,8 @@ library yaml.utils; +import 'package:source_span/source_span.dart'; + /// A pair of values. class Pair { final E first; @@ -13,3 +15,30 @@ class Pair { String toString() => '($first, $last)'; } + +/// Print a warning. +/// +/// If [span] is passed, associates the warning with that span. +void warn(String message, [SourceSpan span]) => + yamlWarningCallback(message, span); + +/// A callback for emitting a warning. +/// +/// [message] is the text of the warning. If [span] is passed, it's the portion +/// of the document that the warning is associated with and should be included +/// in the printed warning. +typedef YamlWarningCallback(String message, [SourceSpan span]); + +/// A callback for emitting a warning. +/// +/// In a very few cases, the YAML spec indicates that an implementation should +/// emit a warning. To do so, it calls this callback. The default implementation +/// prints a message using [print]. +YamlWarningCallback yamlWarningCallback = (message, [span]) { + // TODO(nweiz): Print to stderr with color when issue 6943 is fixed and + // dart:io is available. + if (span != null) message = span.message(message); + print(message); +}; + + diff --git a/pkgs/yaml/lib/src/visitor.dart b/pkgs/yaml/lib/src/visitor.dart deleted file mode 100644 index 3f4c45538..000000000 --- a/pkgs/yaml/lib/src/visitor.dart +++ /dev/null @@ -1,30 +0,0 @@ -// 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 yaml.visitor; - -import 'equality.dart'; -import 'model.dart'; - -/// The visitor pattern for YAML documents. -class Visitor { - /// Returns [alias]. - visitAlias(AliasNode alias) => alias; - - /// Returns [scalar]. - visitScalar(ScalarNode scalar) => scalar; - - /// Visits each node in [seq] and returns a list of the results. - visitSequence(SequenceNode seq) - => seq.content.map((e) => e.visit(this)).toList(); - - /// Visits each key and value in [map] and returns a map of the results. - visitMapping(MappingNode map) { - var out = deepEqualsMap(); - for (var key in map.content.keys) { - out[key.visit(this)] = map.content[key].visit(this); - } - return out; - } -} diff --git a/pkgs/yaml/lib/src/yaml_document.dart b/pkgs/yaml/lib/src/yaml_document.dart new file mode 100644 index 000000000..4c249a0c1 --- /dev/null +++ b/pkgs/yaml/lib/src/yaml_document.dart @@ -0,0 +1,67 @@ +// Copyright (c) 2014, 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 yaml.yaml_document; + +import 'dart:collection'; + +import 'package:source_span/source_span.dart'; + +import 'yaml_node.dart'; + +/// A YAML document, complete with metadata. +class YamlDocument { + /// The contents of the document. + final YamlNode contents; + + /// The span covering the entire document. + final SourceSpan span; + + /// The version directive for the document, if any. + final VersionDirective versionDirective; + + /// The tag directives for the document. + final List tagDirectives; + + /// Whether the beginning of the document was implicit (versus explicit via + /// `===`). + final bool startImplicit; + + /// Whether the end of the document was implicit (versus explicit via `...`). + final bool endImplicit; + + /// Users of the library should not use this constructor. + YamlDocument.internal(this.contents, this.span, this.versionDirective, + List tagDirectives, {this.startImplicit: false, + this.endImplicit: false}) + : tagDirectives = new UnmodifiableListView(tagDirectives); + + String toString() => contents.toString(); +} + +/// A directive indicating which version of YAML a document was written to. +class VersionDirective { + /// The major version number. + final int major; + + /// The minor version number. + final int minor; + + VersionDirective(this.major, this.minor); + + String toString() => "%YAML $major.$minor"; +} + +/// A directive describing a custom tag handle. +class TagDirective { + /// The handle for use in the document. + final String handle; + + /// The prefix that the handle maps to. + final String prefix; + + TagDirective(this.handle, this.prefix); + + String toString() => "%TAG $handle $prefix"; +} diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 6320156e1..027bc1b32 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -10,6 +10,7 @@ import 'package:collection/collection.dart'; import 'package:source_span/source_span.dart'; import 'null_span.dart'; +import 'style.dart'; import 'yaml_node_wrapper.dart'; /// An interface for parsed nodes from a YAML source tree. @@ -26,7 +27,9 @@ abstract class YamlNode { /// /// [SourceSpan.message] can be used to produce a human-friendly message about /// this node. - SourceSpan get span; + SourceSpan get span => _span; + + SourceSpan _span; /// The inner value of this node. /// @@ -38,8 +41,6 @@ abstract class YamlNode { /// A read-only [Map] parsed from YAML. class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { - final SourceSpan span; - /// A view of [this] where the keys and values are guaranteed to be /// [YamlNode]s. /// @@ -50,6 +51,9 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// `dynamic` `map.nodes["foo"]` will still work. final Map nodes; + /// The style used for the map in the original document. + final CollectionStyle style; + Map get value => this; Iterable get keys => nodes.keys.map((node) => node.value); @@ -77,8 +81,10 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { new YamlMapWrapper(dartMap, sourceUrl); /// Users of the library should not use this constructor. - YamlMap.internal(Map nodes, this.span) - : nodes = new UnmodifiableMapView(nodes); + YamlMap.internal(Map nodes, SourceSpan span, this.style) + : nodes = new UnmodifiableMapView(nodes) { + _span = span; + } operator [](key) { var node = nodes[key]; @@ -89,10 +95,11 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { // TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed. /// A read-only [List] parsed from YAML. class YamlList extends YamlNode with collection.ListMixin { - final SourceSpan span; - final List nodes; + /// The style used for the list in the original document. + final CollectionStyle style; + List get value => this; int get length => nodes.length; @@ -124,8 +131,10 @@ class YamlList extends YamlNode with collection.ListMixin { new YamlListWrapper(dartList, sourceUrl); /// Users of the library should not use this constructor. - YamlList.internal(List nodes, this.span) - : nodes = new UnmodifiableListView(nodes); + YamlList.internal(List nodes, SourceSpan span, this.style) + : nodes = new UnmodifiableListView(nodes) { + _span = span; + } operator [](int index) => nodes[index].value; @@ -136,10 +145,11 @@ class YamlList extends YamlNode with collection.ListMixin { /// A wrapped scalar value parsed from YAML. class YamlScalar extends YamlNode { - final SourceSpan span; - final value; + /// The style used for the scalar in the original document. + final ScalarStyle style; + /// Wraps a Dart value in a [YamlScalar]. /// /// This scalar's [span] won't have useful location information. However, it @@ -148,10 +158,21 @@ class YamlScalar extends YamlNode { /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. YamlScalar.wrap(this.value, {sourceUrl}) - : span = new NullSpan(sourceUrl); + : style = ScalarStyle.ANY { + _span = new NullSpan(sourceUrl); + } /// Users of the library should not use this constructor. - YamlScalar.internal(this.value, this.span); + YamlScalar.internal(this.value, SourceSpan span, this.style) { + _span = span; + } String toString() => value.toString(); } + +/// Sets the source span of a [YamlNode]. +/// +/// This method is not exposed publicly. +void setSpan(YamlNode node, SourceSpan span) { + node._span = span; +} diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index d000dcb8e..be96ba4d5 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -10,12 +10,15 @@ import 'package:collection/collection.dart' as pkg_collection; import 'package:source_span/source_span.dart'; import 'null_span.dart'; +import 'style.dart'; import 'yaml_node.dart'; /// A wrapper that makes a normal Dart map behave like a [YamlMap]. class YamlMapWrapper extends MapBase with pkg_collection.UnmodifiableMapMixin implements YamlMap { + final CollectionStyle style = CollectionStyle.ANY; + final Map _dartMap; final SourceSpan span; @@ -55,8 +58,8 @@ class _YamlMapNodes extends MapBase final SourceSpan _span; - Iterable get keys => - _dartMap.keys.map((key) => new YamlScalar.internal(key, _span)); + Iterable get keys => _dartMap.keys.map((key) => + new YamlScalar.internal(key, _span, ScalarStyle.ANY)); _YamlMapNodes(this._dartMap, this._span); @@ -76,6 +79,8 @@ class _YamlMapNodes extends MapBase // TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed. /// A wrapper that makes a normal Dart list behave like a [YamlList]. class YamlListWrapper extends ListBase implements YamlList { + final CollectionStyle style = CollectionStyle.ANY; + final List _dartList; final SourceSpan span; @@ -146,5 +151,5 @@ class _YamlListNodes extends ListBase { YamlNode _nodeForValue(value, SourceSpan span) { if (value is Map) return new YamlMapWrapper._(value, span); if (value is List) return new YamlListWrapper._(value, span); - return new YamlScalar.internal(value, span); + return new YamlScalar.internal(value, span, ScalarStyle.ANY); } diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index e45dd6ebe..9af329a20 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -4,16 +4,17 @@ library yaml; -import 'package:string_scanner/string_scanner.dart'; - -import 'src/composer.dart'; -import 'src/constructor.dart'; -import 'src/parser.dart'; +import 'src/loader.dart'; +import 'src/style.dart'; +import 'src/yaml_document.dart'; import 'src/yaml_exception.dart'; import 'src/yaml_node.dart'; +export 'src/style.dart'; +export 'src/utils.dart' show YamlWarningCallback, yamlWarningCallback; +export 'src/yaml_document.dart'; export 'src/yaml_exception.dart'; -export 'src/yaml_node.dart'; +export 'src/yaml_node.dart' hide setSpan; /// Loads a single document from a YAML string. /// @@ -39,13 +40,29 @@ loadYaml(String yaml, {sourceUrl}) => /// This is just like [loadYaml], except that where [loadYaml] would return a /// normal Dart value this returns a [YamlNode] instead. This allows the caller /// to be confident that the return value will always be a [YamlNode]. -YamlNode loadYamlNode(String yaml, {sourceUrl}) { - var stream = loadYamlStream(yaml, sourceUrl: sourceUrl); - if (stream.length != 1) { - throw new YamlException("Expected 1 document, were ${stream.length}.", - stream.span); +YamlNode loadYamlNode(String yaml, {sourceUrl}) => + loadYamlDocument(yaml, sourceUrl: sourceUrl).contents; + +/// Loads a single document from a YAML string as a [YamlDocument]. +/// +/// This is just like [loadYaml], except that where [loadYaml] would return a +/// normal Dart value this returns a [YamlDocument] instead. This allows the +/// caller to access document metadata. +YamlDocument loadYamlDocument(String yaml, {sourceUrl}) { + var loader = new Loader(yaml, sourceUrl: sourceUrl); + var document = loader.load(); + if (document == null) { + return new YamlDocument.internal( + new YamlScalar.internal(null, loader.span, ScalarStyle.ANY), + loader.span, null, const []); } - return stream.nodes[0]; + + var nextDocument = loader.load(); + if (nextDocument != null) { + throw new YamlException("Only expected one document.", nextDocument.span); + } + + return document; } /// Loads a stream of documents from a YAML string. @@ -62,15 +79,34 @@ YamlNode loadYamlNode(String yaml, {sourceUrl}) { /// If [sourceUrl] is passed, it's used as the URL from which the YAML /// originated for error reporting. It can be a [String], a [Uri], or `null`. YamlList loadYamlStream(String yaml, {sourceUrl}) { - var pair; - try { - pair = new Parser(yaml, sourceUrl).l_yamlStream(); - } on StringScannerException catch (error) { - throw new YamlException(error.message, error.span); + var loader = new Loader(yaml, sourceUrl: sourceUrl); + + var documents = []; + var document = loader.load(); + while (document != null) { + documents.add(document); + document = loader.load(); + } + + return new YamlList.internal( + documents.map((document) => document.contents).toList(), + loader.span, + CollectionStyle.ANY); +} + +/// Loads a stream of documents from a YAML string. +/// +/// This is like [loadYamlStream], except that it returns [YamlDocument]s with +/// metadata wrapping the document contents. +List loadYamlDocuments(String yaml, {sourceUrl}) { + var loader = new Loader(yaml, sourceUrl: sourceUrl); + + var documents = []; + var document = loader.load(); + while (document != null) { + documents.add(document); + document = loader.load(); } - var nodes = pair.first - .map((doc) => new Constructor(new Composer(doc).compose()).construct()) - .toList(); - return new YamlList.internal(nodes, pair.last); + return documents; } diff --git a/pkgs/yaml/libyaml-license.txt b/pkgs/yaml/libyaml-license.txt new file mode 100644 index 000000000..050ced23f --- /dev/null +++ b/pkgs/yaml/libyaml-license.txt @@ -0,0 +1,19 @@ +Copyright (c) 2006 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 74194e5fa..d0d51c5f6 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,12 +1,12 @@ name: yaml -version: 2.0.1+1 +version: 2.1.0 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dependencies: - collection: ">=0.9.2 <2.0.0" + collection: ">=1.1.0 <2.0.0" path: ">=1.2.0 <2.0.0" - string_scanner: ">=0.1.0 <0.2.0" + string_scanner: ">=0.1.2 <0.2.0" source_span: ">=1.0.0 <2.0.0" dev_dependencies: unittest: ">=0.9.0 <0.12.0" diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 4fbb10878..2d9a0e806 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -4,7 +4,6 @@ library yaml.test; -// TODO(rnystrom): rewrite tests so that they don't need "Expect". import 'package:unittest/unittest.dart'; import 'package:yaml/yaml.dart'; @@ -16,7 +15,7 @@ main() { group('has a friendly error message for', () { var tabError = predicate((e) => - e.toString().contains('tab characters are not allowed as indentation')); + e.toString().contains('Tab characters are not allowed as indentation')); test('using a tab as indentation', () { expect(() => loadYaml('foo:\n\tbar'), @@ -32,6 +31,29 @@ main() { }); }); + group("refuses documents that declare version", () { + test("1.0", () { + expectYamlFails(""" + %YAML 1.0 + --- text + """); + }); + + test("1.3", () { + expectYamlFails(""" + %YAML 1.3 + --- text + """); + }); + + test("2.0", () { + expectYamlFails(""" + %YAML 2.0 + --- text + """); + }); + }); + // The following tests are all taken directly from the YAML spec // (http://www.yaml.org/spec/1.2/spec.html). Most of them are code examples // that are directly included in the spec, but additional tests are derived @@ -173,21 +195,21 @@ main() { - Ken Griffey"""); }); - // test('[Example 2.10]', () { - // expectYamlLoads({ - // "hr": ["Mark McGwire", "Sammy Sosa"], - // "rbi": ["Sammy Sosa", "Ken Griffey"] - // }, - // """ - // --- - // hr: - // - Mark McGwire - // # Following node labeled SS - // - &SS Sammy Sosa - // rbi: - // - *SS # Subsequent occurrence - // - Ken Griffey"""); - // }); + test('[Example 2.10]', () { + expectYamlLoads({ + "hr": ["Mark McGwire", "Sammy Sosa"], + "rbi": ["Sammy Sosa", "Ken Griffey"] + }, + """ + --- + hr: + - Mark McGwire + # Following node labeled SS + - &SS Sammy Sosa + rbi: + - *SS # Subsequent occurrence + - Ken Griffey"""); + }); test('[Example 2.11]', () { var doc = deepEqualsMap(); @@ -536,12 +558,12 @@ main() { """); }); - // test('[Example 5.9]', () { - // expectYamlLoads("text", - // """ - // %YAML 1.2 - // --- text"""); - // }); + test('[Example 5.9]', () { + expectYamlLoads("text", + """ + %YAML 1.2 + --- text"""); + }); test('[Example 5.10]', () { expectYamlFails("commercial-at: @text"); @@ -886,179 +908,179 @@ main() { }); group('6.8: Directives', () { - // // TODO(nweiz): assert that this produces a warning - // test('[Example 6.13]', () { - // expectYamlLoads("foo", - // ''' - // %FOO bar baz # Should be ignored - // # with a warning. - // --- "foo"'''); - // }); + // TODO(nweiz): assert that this produces a warning + test('[Example 6.13]', () { + expectYamlLoads("foo", + ''' + %FOO bar baz # Should be ignored + # with a warning. + --- "foo"'''); + }); - // // TODO(nweiz): assert that this produces a warning - // test('[Example 6.14]', () { - // expectYamlLoads("foo", - // ''' - // %YAML 1.3 # Attempt parsing - // # with a warning - // --- - // "foo"'''); - // }); + // TODO(nweiz): assert that this produces a warning. + test('[Example 6.14]', () { + expectYamlLoads("foo", + ''' + %YAML 1.3 # Attempt parsing + # with a warning + --- + "foo"'''); + }); - // test('[Example 6.15]', () { - // expectYamlFails( - // """ - // %YAML 1.2 - // %YAML 1.1 - // foo"""); - // }); + test('[Example 6.15]', () { + expectYamlFails( + """ + %YAML 1.2 + %YAML 1.1 + foo"""); + }); - // test('[Example 6.16]', () { - // expectYamlLoads("foo", - // ''' - // %TAG !yaml! tag:yaml.org,2002: - // --- - // !yaml!str "foo"'''); - // }); + test('[Example 6.16]', () { + expectYamlLoads("foo", + ''' + %TAG !yaml! tag:yaml.org,2002: + --- + !yaml!str "foo"'''); + }); - // test('[Example 6.17]', () { - // ExpectYamlFails( - // """ - // %TAG ! !foo - // %TAG ! !foo - // bar"""); - // }); + test('[Example 6.17]', () { + expectYamlFails( + """ + %TAG ! !foo + %TAG ! !foo + bar"""); + }); // Examples 6.18 through 6.22 test custom tag URIs, which this // implementation currently doesn't plan to support. }); group('6.9: Node Properties', () { - // test('may be specified in any order', () { - // expectYamlLoads(["foo", "bar"], - // """ - // - !!str &a1 foo - // - &a2 !!str bar"""); - // }); + test('may be specified in any order', () { + expectYamlLoads(["foo", "bar"], + """ + - !!str &a1 foo + - &a2 !!str bar"""); + }); - // test('[Example 6.23]', () { - // expectYamlLoads({ - // "foo": "bar", - // "baz": "foo" - // }, - // ''' - // !!str &a1 "foo": - // !!str bar - // &a2 baz : *a1'''); - // }); + test('[Example 6.23]', () { + expectYamlLoads({ + "foo": "bar", + "baz": "foo" + }, + ''' + !!str &a1 "foo": + !!str bar + &a2 baz : *a1'''); + }); - // // Example 6.24 tests custom tag URIs, which this implementation currently - // // doesn't plan to support. + // Example 6.24 tests custom tag URIs, which this implementation currently + // doesn't plan to support. - // test('[Example 6.25]', () { - // expectYamlFails("- ! foo"); - // expectYamlFails("- !<\$:?> foo"); - // }); + test('[Example 6.25]', () { + expectYamlFails("- ! foo"); + expectYamlFails("- !<\$:?> foo"); + }); - // // Examples 6.26 and 6.27 test custom tag URIs, which this implementation - // // currently doesn't plan to support. + // Examples 6.26 and 6.27 test custom tag URIs, which this implementation + // currently doesn't plan to support. - // test('[Example 6.28]', () { - // expectYamlLoads(["12", 12, "12"], - // ''' - // # Assuming conventional resolution: - // - "12" - // - 12 - // - ! 12'''); - // }); + test('[Example 6.28]', () { + expectYamlLoads(["12", 12, "12"], + ''' + # Assuming conventional resolution: + - "12" + - 12 + - ! 12'''); + }); - // test('[Example 6.29]', () { - // expectYamlLoads({ - // "First occurrence": "Value", - // "Second occurrence": "anchor" - // }, - // """ - // First occurrence: &anchor Value - // Second occurrence: *anchor"""); - // }); + test('[Example 6.29]', () { + expectYamlLoads({ + "First occurrence": "Value", + "Second occurrence": "Value" + }, + """ + First occurrence: &anchor Value + Second occurrence: *anchor"""); + }); }); // Chapter 7: Flow Styles group('7.1: Alias Nodes', () { - // test("must not use an anchor that doesn't previously occur", () { - // expectYamlFails( - // """ - // - *anchor - // - &anchor foo"""); - // }); + test("must not use an anchor that doesn't previously occur", () { + expectYamlFails( + """ + - *anchor + - &anchor foo"""); + }); - // test("don't have to exist for a given anchor node", () { - // expectYamlLoads(["foo"], "- &anchor foo"); - // }); + test("don't have to exist for a given anchor node", () { + expectYamlLoads(["foo"], "- &anchor foo"); + }); - // group('must not specify', () { - // test('tag properties', () => expectYamlFails( - // """ - // - &anchor foo - // - !str *anchor"""); + group('must not specify', () { + test('tag properties', () => expectYamlFails( + """ + - &anchor foo + - !str *anchor""")); - // test('anchor properties', () => expectYamlFails( - // """ - // - &anchor foo - // - &anchor2 *anchor"""); + test('anchor properties', () => expectYamlFails( + """ + - &anchor foo + - &anchor2 *anchor""")); - // test('content', () => expectYamlFails( - // """ - // - &anchor foo - // - *anchor bar"""))); - // }); + test('content', () => expectYamlFails( + """ + - &anchor foo + - *anchor bar""")); + }); - // test('must preserve structural equality', () { - // var doc = loadYaml(cleanUpLiteral( - // """ - // anchor: &anchor [a, b, c] - // alias: *anchor"""); - // var anchorList = doc['anchor']; - // var aliasList = doc['alias']; - // expect(anchorList, same(aliasList)); + test('must preserve structural equality', () { + var doc = loadYaml(cleanUpLiteral( + """ + anchor: &anchor [a, b, c] + alias: *anchor""")); + var anchorList = doc['anchor']; + var aliasList = doc['alias']; + expect(anchorList, same(aliasList)); - // doc = loadYaml(cleanUpLiteral( - // """ - // ? &anchor [a, b, c] - // : ? *anchor - // : bar"""); - // anchorList = doc.keys[0]; - // aliasList = doc[['a', 'b', 'c']].keys[0]; - // expect(anchorList, same(aliasList)); - // }); + doc = loadYaml(cleanUpLiteral( + """ + ? &anchor [a, b, c] + : ? *anchor + : bar""")); + anchorList = doc.keys.first; + aliasList = doc[['a', 'b', 'c']].keys.first; + expect(anchorList, same(aliasList)); + }); - // test('[Example 7.1]', () { - // expectYamlLoads({ - // "First occurence": "Foo", - // "Second occurence": "Foo", - // "Override anchor": "Bar", - // "Reuse anchor": "Bar", - // }, - // """ - // First occurrence: &anchor Foo - // Second occurrence: *anchor - // Override anchor: &anchor Bar - // Reuse anchor: *anchor"""); - // }); + test('[Example 7.1]', () { + expectYamlLoads({ + "First occurrence": "Foo", + "Second occurrence": "Foo", + "Override anchor": "Bar", + "Reuse anchor": "Bar", + }, + """ + First occurrence: &anchor Foo + Second occurrence: *anchor + Override anchor: &anchor Bar + Reuse anchor: *anchor"""); + }); }); group('7.2: Empty Nodes', () { - // test('[Example 7.2]', () { - // expectYamlLoads({ - // "foo": "", - // "": "bar" - // }, - // """ - // { - // foo : !!str, - // !!str : bar, - // }"""); - // }); + test('[Example 7.2]', () { + expectYamlLoads({ + "foo": "", + "": "bar" + }, + """ + { + foo : !!str, + !!str : bar, + }"""); + }); test('[Example 7.3]', () { var doc = deepEqualsMap({"foo": null}); @@ -1284,17 +1306,18 @@ main() { - [ {JSON: like}:adjacent ]"""); }); - test('[Example 7.22]', () { - expectYamlFails( - """ - [ foo - bar: invalid ]"""); - - // TODO(nweiz): enable this when we throw an error for long keys - // var dotList = new List.filled(1024, ' '); - // var dots = dotList.join(); - // expectYamlFails('[ "foo...$dots...bar": invalid ]'); - }); + // TODO(nweiz): enable this when we throw an error for long or multiline + // keys. + // test('[Example 7.22]', () { + // expectYamlFails( + // """ + // [ foo + // bar: invalid ]"""); + // + // var dotList = new List.filled(1024, ' '); + // var dots = dotList.join(); + // expectYamlFails('[ "foo...$dots...bar": invalid ]'); + // }); }); group('7.5: Flow Nodes', () { @@ -1308,15 +1331,15 @@ main() { - c"""); }); - // test('[Example 7.24]', () { - // expectYamlLoads(["a", "b", "c", "c", ""], - // """ - // - !!str "a" - // - 'b' - // - &anchor "c" - // - *anchor - // - !!str"""); - // }); + test('[Example 7.24]', () { + expectYamlLoads(["a", "b", "c", "c", ""], + """ + - !!str "a" + - 'b' + - &anchor "c" + - *anchor + - !!str"""); + }); }); // Chapter 8: Block Styles @@ -1569,41 +1592,43 @@ main() { : moon: white"""); }); - // test('[Example 8.20]', () { - // expectYamlLoads(["flow in block", "Block scalar\n", {"foo": "bar"}], - // ''' - // - - // "flow in block" - // - > - // Block scalar - // - !!map # Block collection - // foo : bar'''); - // }); + test('[Example 8.20]', () { + expectYamlLoads(["flow in block", "Block scalar\n", {"foo": "bar"}], + ''' + - + "flow in block" + - > + Block scalar + - !!map # Block collection + foo : bar'''); + }); - // test('[Example 8.21]', () { - // expectYamlLoads({"literal": "value", "folded": "value"}, - // """ - // literal: |2 - // value - // folded: - // !!str - // >1 - // value"""); - // }); + test('[Example 8.21]', () { + // The spec doesn't include a newline after "value" in the parsed map, but + // the block scalar is clipped so it should be retained. + expectYamlLoads({"literal": "value\n", "folded": "value"}, + """ + literal: |2 + value + folded: + !!str + >1 + value"""); + }); - // test('[Example 8.22]', () { - // expectYamlLoads({ - // "sequence": ["entry", ["nested"]], - // "mapping": {"foo": "bar"} - // }, - // """ - // sequence: !!seq - // - entry - // - !!seq - // - nested - // mapping: !!map - // foo: bar"""); - // }); + test('[Example 8.22]', () { + expectYamlLoads({ + "sequence": ["entry", ["nested"]], + "mapping": {"foo": "bar"} + }, + """ + sequence: !!seq + - entry + - !!seq + - nested + mapping: !!map + foo: bar"""); + }); }); // Chapter 9: YAML Character Stream @@ -1611,14 +1636,14 @@ main() { // Example 9.1 tests the use of a BOM, which this implementation currently // doesn't plan to support. - // test('[Example 9.2]', () { - // expectYamlLoads("Document", - // """ - // %YAML 1.2 - // --- - // Document - // ... # Suffix"""); - // }); + test('[Example 9.2]', () { + expectYamlLoads("Document", + """ + %YAML 1.2 + --- + Document + ... # Suffix"""); + }); test('[Example 9.3]', () { // The spec example indicates that the comment after "%!PS-Adobe-2.0" @@ -1653,81 +1678,83 @@ main() { ..."""); }); - // test('[Example 9.5]', () { - // expectYamlStreamLoads(["%!PS-Adobe-2.0\n", null], - // """ - // %YAML 1.2 - // --- | - // %!PS-Adobe-2.0 - // ... - // %YAML1.2 - // --- - // # Empty - // ..."""); - // }); + test('[Example 9.5]', () { + // The spec doesn't have a space between the second + // "YAML" and "1.2", but this seems to be a typo. + expectYamlStreamLoads(["%!PS-Adobe-2.0\n", null], + """ + %YAML 1.2 + --- | + %!PS-Adobe-2.0 + ... + %YAML 1.2 + --- + # Empty + ..."""); + }); - // test('[Example 9.6]', () { - // expectYamlStreamLoads(["Document", null, {"matches %": 20}], - // """ - // Document - // --- - // # Empty - // ... - // %YAML 1.2 - // --- - // matches %: 20"""); - // }); + test('[Example 9.6]', () { + expectYamlStreamLoads(["Document", null, {"matches %": 20}], + """ + Document + --- + # Empty + ... + %YAML 1.2 + --- + matches %: 20"""); + }); }); // Chapter 10: Recommended Schemas group('10.1: Failsafe Schema', () { - // test('[Example 10.1]', () { - // expectYamlStreamLoads({ - // "Block style": { - // "Clark": "Evans", - // "Ingy": "döt Net", - // "Oren": "Ben-Kiki" - // }, - // "Flow style": { - // "Clark": "Evans", - // "Ingy": "döt Net", - // "Oren": "Ben-Kiki" - // } - // }, - // """ - // Block style: !!map - // Clark : Evans - // Ingy : döt Net - // Oren : Ben-Kiki + test('[Example 10.1]', () { + expectYamlLoads({ + "Block style": { + "Clark": "Evans", + "Ingy": "döt Net", + "Oren": "Ben-Kiki" + }, + "Flow style": { + "Clark": "Evans", + "Ingy": "döt Net", + "Oren": "Ben-Kiki" + } + }, + """ + Block style: !!map + Clark : Evans + Ingy : döt Net + Oren : Ben-Kiki - // Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }"""); - // }); + Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }"""); + }); - // test('[Example 10.2]', () { - // expectYamlStreamLoads({ - // "Block style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"], - // "Flow style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"] - // }, - // """ - // Block style: !!seq - // - Clark Evans - // - Ingy döt Net - // - Oren Ben-Kiki + test('[Example 10.2]', () { + expectYamlLoads({ + "Block style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"], + "Flow style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"] + }, + """ + Block style: !!seq + - Clark Evans + - Ingy döt Net + - Oren Ben-Kiki - // Flow style: !!seq [ Clark Evans, Ingy döt Net, Oren Ben-Kiki ]"""); - // }); + Flow style: !!seq [ Clark Evans, Ingy döt Net, Oren Ben-Kiki ]"""); + }); - // test('[Example 10.3]', () { - // expectYamlStreamLoads({ - // "Block style": "String: just a theory.", - // "Flow style": "String: just a theory." - // }, - // ''' - // Block style: !!str |- - // String: just a theory. + test('[Example 10.3]', () { + expectYamlLoads({ + "Block style": "String: just a theory.", + "Flow style": "String: just a theory." + }, + ''' + Block style: !!str |- + String: just a theory. - // Flow style: !!str "String: just a theory."'''); - // }); + Flow style: !!str "String: just a theory."'''); + }); }); group('10.2: JSON Schema', () { From b423d1f1e6204df1c2bd6ea3859d17d53d0c7304 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 12 Dec 2014 01:50:49 +0000 Subject: [PATCH 047/179] Don't include extra whitespace in YAML scalar spans. R=rnystrom@google.com BUG=21841 Review URL: https://codereview.chromium.org//797103002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@42307 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/lib/src/scanner.dart | 8 ++++++-- pkgs/yaml/pubspec.yaml | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index f454255b6..80548ed2f 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.1 + +* Properly scope `SourceSpan`s for scalar values surrounded by whitespace. + ## 2.1.0 * Rewrite the parser for a 10x speed improvement. diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 00685539c..6c702c80e 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -1156,6 +1156,7 @@ class Scanner { var leadingBreak = ''; var leadingBlank = false; var trailingBlank = false; + var end = _scanner.position; while (_scanner.column == indent && !_scanner.isDone) { // Check for a document indicator. libyaml doesn't do this, but the spec // mandates it. See example 9.5: @@ -1188,6 +1189,7 @@ class Scanner { _scanner.readChar(); } buffer.write(_scanner.substring(startPosition)); + end = _scanner.position; // libyaml always reads a line here, but this breaks on block scalars at // the end of the document that end without newlines. See example 8.1: @@ -1204,7 +1206,7 @@ class Scanner { if (chomping != _Chomping.STRIP) buffer.write(leadingBreak); if (chomping == _Chomping.KEEP) buffer.write(trailingBreaks); - return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), + return new ScalarToken(_scanner.spanFrom(start, end), buffer.toString(), literal ? ScalarStyle.LITERAL : ScalarStyle.FOLDED); } @@ -1430,6 +1432,7 @@ class Scanner { /// Scans a plain scalar. Token _scanPlainScalar() { var start = _scanner.state; + var end = _scanner.state; var buffer = new StringBuffer(); var leadingBreak = ''; var trailingBreaks = ''; @@ -1466,6 +1469,7 @@ class Scanner { _scanner.readChar(); } buffer.write(_scanner.substring(startPosition)); + end = _scanner.state; // Is it the end? if (!_isBlank && !_isBreak) break; @@ -1501,7 +1505,7 @@ class Scanner { // Allow a simple key after a plain scalar with leading blanks. if (leadingBreak.isNotEmpty) _simpleKeyAllowed = true; - return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), + return new ScalarToken(_scanner.spanFrom(start, end), buffer.toString(), ScalarStyle.PLAIN); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index d0d51c5f6..f149b1f6e 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,12 +1,12 @@ name: yaml -version: 2.1.0 +version: 2.1.1 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. dependencies: collection: ">=1.1.0 <2.0.0" path: ">=1.2.0 <2.0.0" - string_scanner: ">=0.1.2 <0.2.0" + string_scanner: ">=0.1.3 <0.2.0" source_span: ">=1.0.0 <2.0.0" dev_dependencies: unittest: ">=0.9.0 <0.12.0" From b7a7e1740649913388355823cbf8b76847e55f6b Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 12 Dec 2014 02:13:32 +0000 Subject: [PATCH 048/179] Fix a crashing yaml bug when parsing block scalars. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//801573003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@42309 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/lib/src/scanner.dart | 4 ++-- pkgs/yaml/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 80548ed2f..b86425023 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.2 + +* Fix a crashing bug when parsing block scalars. + ## 2.1.1 * Properly scope `SourceSpan`s for scalar values surrounded by whitespace. diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 6c702c80e..e1b578ebe 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -1156,7 +1156,7 @@ class Scanner { var leadingBreak = ''; var leadingBlank = false; var trailingBlank = false; - var end = _scanner.position; + var end = _scanner.state; while (_scanner.column == indent && !_scanner.isDone) { // Check for a document indicator. libyaml doesn't do this, but the spec // mandates it. See example 9.5: @@ -1189,7 +1189,7 @@ class Scanner { _scanner.readChar(); } buffer.write(_scanner.substring(startPosition)); - end = _scanner.position; + end = _scanner.state; // libyaml always reads a line here, but this breaks on block scalars at // the end of the document that end without newlines. See example 8.1: diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index f149b1f6e..88650fcef 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.1 +version: 2.1.2 author: "Dart Team " homepage: http://www.dartlang.org description: A parser for YAML. From fcd12ad6292c561c1c711493bd445160803da0a0 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 17:01:39 -0800 Subject: [PATCH 049/179] Add gitignore, status, and codereview files. --- pkgs/yaml/.gitignore | 14 ++++++++++++++ pkgs/yaml/.status | 3 +++ pkgs/yaml/codereview.settings | 3 +++ 3 files changed, 20 insertions(+) create mode 100644 pkgs/yaml/.gitignore create mode 100644 pkgs/yaml/.status create mode 100644 pkgs/yaml/codereview.settings diff --git a/pkgs/yaml/.gitignore b/pkgs/yaml/.gitignore new file mode 100644 index 000000000..388eff0ba --- /dev/null +++ b/pkgs/yaml/.gitignore @@ -0,0 +1,14 @@ +# Don’t commit the following directories created by pub. +.buildlog +.pub/ +build/ +packages + +# Or the files created by dart2js. +*.dart.js +*.js_ +*.js.deps +*.js.map + +# Include when developing application packages. +pubspec.lock \ No newline at end of file diff --git a/pkgs/yaml/.status b/pkgs/yaml/.status new file mode 100644 index 000000000..e9f2b0049 --- /dev/null +++ b/pkgs/yaml/.status @@ -0,0 +1,3 @@ +# Copyright (c) 2014, 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. diff --git a/pkgs/yaml/codereview.settings b/pkgs/yaml/codereview.settings new file mode 100644 index 000000000..0a3d2bb88 --- /dev/null +++ b/pkgs/yaml/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: http://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/yaml/commit/ +CC_LIST: reviews@dartlang.org \ No newline at end of file From 6238a74530c12c3328ce886dc21384d5842e197a Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 17:02:08 -0800 Subject: [PATCH 050/179] Update the pubspec's homepage link. --- pkgs/yaml/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 88650fcef..c094c7b7c 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,7 +1,7 @@ name: yaml version: 2.1.2 author: "Dart Team " -homepage: http://www.dartlang.org +homepage: http://github.com/dart-lang/yaml description: A parser for YAML. dependencies: collection: ">=1.1.0 <2.0.0" From 82251810ab87ad1082e8a647ea5676b44d5b4a64 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 20 Jan 2015 16:20:05 -0800 Subject: [PATCH 051/179] yaml: reformat, fix README and homepage link, bump version R=nweiz@google.com Review URL: https://codereview.chromium.org//852003003 --- pkgs/yaml/README.md | 4 ---- pkgs/yaml/codereview.settings | 2 +- pkgs/yaml/lib/src/parser.dart | 1 - pkgs/yaml/pubspec.yaml | 4 ++-- 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index 531162f41..c78dc97d7 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -24,7 +24,3 @@ main() { print(JSON.encode(doc)); } ``` - -The source code for this package is at . -Please file issues at . Other questions or comments can be -directed to the Dart mailing list at . diff --git a/pkgs/yaml/codereview.settings b/pkgs/yaml/codereview.settings index 0a3d2bb88..03b6c2745 100644 --- a/pkgs/yaml/codereview.settings +++ b/pkgs/yaml/codereview.settings @@ -1,3 +1,3 @@ -CODE_REVIEW_SERVER: http://codereview.chromium.org/ +CODE_REVIEW_SERVER: https://codereview.chromium.org/ VIEW_VC: https://github.com/dart-lang/yaml/commit/ CC_LIST: reviews@dartlang.org \ No newline at end of file diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 72c01dcf0..8bb131f83 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -671,7 +671,6 @@ class Parser { var versionDirective; var tagDirectives = []; - var reservedDirectives = []; while (token.type == TokenType.VERSION_DIRECTIVE || token.type == TokenType.TAG_DIRECTIVE) { if (token is VersionDirectiveToken) { diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index c094c7b7c..e8a62c0c2 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,7 +1,7 @@ name: yaml -version: 2.1.2 +version: 2.1.3-dev author: "Dart Team " -homepage: http://github.com/dart-lang/yaml +homepage: https://github.com/dart-lang/yaml description: A parser for YAML. dependencies: collection: ">=1.1.0 <2.0.0" From f94b78d2f4514247443d80c29230be5d9cbff166 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 9 Jun 2015 15:29:52 -0700 Subject: [PATCH 052/179] Add a "missing colon" hint. Closes dart-lang/yaml#11 R=kathyw@google.com Review URL: https://codereview.chromium.org//1176653003. --- pkgs/yaml/CHANGELOG.md | 5 +++++ pkgs/yaml/lib/src/scanner.dart | 11 ++++++----- pkgs/yaml/pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index b86425023..5dcd74943 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.1.3 + +* Add a hint that a colon might be missing when a mapping value is found in the + wrong context. + ## 2.1.2 * Fix a crashing bug when parsing block scalars. diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index e1b578ebe..512d72e8a 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -653,7 +653,7 @@ class Scanner { if (_inBlockContext) { if (!_simpleKeyAllowed) { throw new YamlException( - "Block sequence entries are not allowed in this context.", + "Block sequence entries are not allowed here.", _scanner.emptySpan); } @@ -676,7 +676,7 @@ class Scanner { void _fetchKey() { if (_inBlockContext) { if (!_simpleKeyAllowed) { - throw new YamlException("Mapping keys are not allowed in this context.", + throw new YamlException("Mapping keys are not allowed here.", _scanner.emptySpan); } @@ -714,14 +714,15 @@ class Scanner { // A simple key cannot follow another simple key. _simpleKeyAllowed = false; } else if (_inBlockContext) { - // If we're here, we've found the ':' indicator following a complex key. - if (!_simpleKeyAllowed) { throw new YamlException( - "Mapping values are not allowed in this context.", + "Mapping values are not allowed here. Did you miss a colon " + "earlier?", _scanner.emptySpan); } + // If we're here, we've found the ':' indicator following a complex key. + _rollIndent( _scanner.column, TokenType.BLOCK_MAPPING_START, diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index e8a62c0c2..d00d31f52 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.3-dev +version: 2.1.3 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. From 721c7be15a73e75c38a6349714f575802f46726d Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 16 Jul 2015 13:46:16 -0700 Subject: [PATCH 053/179] Upgrade to the new test runner. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1236933005 . --- pkgs/yaml/.gitignore | 1 + pkgs/yaml/.status | 3 --- pkgs/yaml/.test_config | 3 +++ pkgs/yaml/pubspec.yaml | 4 ++-- pkgs/yaml/test/utils.dart | 2 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 2 +- pkgs/yaml/test/yaml_test.dart | 2 +- 7 files changed, 9 insertions(+), 8 deletions(-) delete mode 100644 pkgs/yaml/.status create mode 100644 pkgs/yaml/.test_config diff --git a/pkgs/yaml/.gitignore b/pkgs/yaml/.gitignore index 388eff0ba..7dbf0350d 100644 --- a/pkgs/yaml/.gitignore +++ b/pkgs/yaml/.gitignore @@ -3,6 +3,7 @@ .pub/ build/ packages +.packages # Or the files created by dart2js. *.dart.js diff --git a/pkgs/yaml/.status b/pkgs/yaml/.status deleted file mode 100644 index e9f2b0049..000000000 --- a/pkgs/yaml/.status +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright (c) 2014, 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. diff --git a/pkgs/yaml/.test_config b/pkgs/yaml/.test_config new file mode 100644 index 000000000..412fc5c5c --- /dev/null +++ b/pkgs/yaml/.test_config @@ -0,0 +1,3 @@ +{ + "test_package": true +} \ No newline at end of file diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index d00d31f52..a25faa600 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.3 +version: 2.1.4-dev author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. @@ -9,6 +9,6 @@ dependencies: string_scanner: ">=0.1.3 <0.2.0" source_span: ">=1.0.0 <2.0.0" dev_dependencies: - unittest: ">=0.9.0 <0.12.0" + test: ">=0.12.0 <0.13.0" environment: sdk: '>=1.5.0 <2.0.0' diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index 9c96ec103..a2d20196a 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -4,7 +4,7 @@ library yaml.test.utils; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'package:yaml/src/equality.dart' as equality; import 'package:yaml/yaml.dart'; diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index 2c41a6af3..b76a73ba8 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -5,7 +5,7 @@ library yaml.node_wrapper_test; import 'package:source_span/source_span.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; main() { diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 2d9a0e806..8091dc5b2 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -4,7 +4,7 @@ library yaml.test; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; import 'utils.dart'; From ce3bb9a4f4ab8ccfe2b63d93582c50d103b4e9d4 Mon Sep 17 00:00:00 2001 From: Robert Nystrom Date: Tue, 1 Sep 2015 17:08:22 -0700 Subject: [PATCH 054/179] Add a parsing benchmark. R=nweiz@google.com Review URL: https://codereview.chromium.org//1325013002 . --- pkgs/yaml/benchmark/benchmark.dart | 74 ++++++++++++++++++++++++++++++ pkgs/yaml/benchmark/input.yaml | 48 +++++++++++++++++++ pkgs/yaml/benchmark/output.json | 1 + 3 files changed, 123 insertions(+) create mode 100644 pkgs/yaml/benchmark/benchmark.dart create mode 100644 pkgs/yaml/benchmark/input.yaml create mode 100644 pkgs/yaml/benchmark/output.json diff --git a/pkgs/yaml/benchmark/benchmark.dart b/pkgs/yaml/benchmark/benchmark.dart new file mode 100644 index 000000000..aec6d4b0c --- /dev/null +++ b/pkgs/yaml/benchmark/benchmark.dart @@ -0,0 +1,74 @@ +// Copyright (c) 2015, 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 yaml.benchmark.benchmark; + +import 'dart:convert'; +import 'dart:io'; + +import 'package:path/path.dart' as p; + +import 'package:yaml/yaml.dart'; + +const numTrials = 10000000; +const runsPerTrial = 1000; + +final source = loadFile("input.yaml"); +final expected = loadFile("output.json"); + +void main(List args) { + var best = double.INFINITY; + + // Run the benchmark several times. This ensures the VM is warmed up and lets + // us see how much variance there is. + for (var i = 0; i <= numTrials; i++) { + var start = new DateTime.now(); + + // For a single benchmark, convert the source multiple times. + var result; + for (var j = 0; j < runsPerTrial; j++) { + result = loadYaml(source); + } + + var elapsed = + new DateTime.now().difference(start).inMilliseconds / runsPerTrial; + + // Keep track of the best run so far. + if (elapsed >= best) continue; + best = elapsed; + + // Sanity check to make sure the output is what we expect and to make sure + // the VM doesn't optimize "dead" code away. + if (JSON.encode(result) != expected) { + print("Incorrect output:\n${JSON.encode(result)}"); + exit(1); + } + + // Don't print the first run. It's always terrible since the VM hasn't + // warmed up yet. + if (i == 0) continue; + printResult("Run ${padLeft('#$i', 3)}", elapsed); + } + + printResult("Best ", best); +} + +String loadFile(String name) { + var path = p.join(p.dirname(p.fromUri(Platform.script)), name); + return new File(path).readAsStringSync(); +} + +void printResult(String label, double time) { + print("$label: ${padLeft(time.toStringAsFixed(3), 4)}ms " + "${'=' * ((time * 100).toInt())}"); +} + +String padLeft(input, int length) { + var result = input.toString(); + if (result.length < length) { + result = " " * (length - result.length) + result; + } + + return result; +} diff --git a/pkgs/yaml/benchmark/input.yaml b/pkgs/yaml/benchmark/input.yaml new file mode 100644 index 000000000..89bf9dcc2 --- /dev/null +++ b/pkgs/yaml/benchmark/input.yaml @@ -0,0 +1,48 @@ +verb: RecommendCafes +recipe: + - verb: List + outputs: ["Cafe[]"] + - verb: Fetch + inputs: ["Cafe[]"] + outputs: ["CafeWithMenu[]"] + - verb: Flatten + inputs: ["CafeWithMenu[]"] + outputs: ["DishOffering[]"] + - verb: Score + inputs: ["DishOffering[]"] + outputs: ["DishOffering[]/Scored"] + - verb: Display + inputs: ["DishOffering[]/Scored"] +tags: + booleans: [ true, false ] + dates: + - canonical: 2001-12-15T02:59:43.1Z + - iso8601: 2001-12-14t21:59:43.10-05:00 + - spaced: 2001-12-14 21:59:43.10 -5 + - date: 2002-12-14 + numbers: + - int: 12345 + - negative: -345 + - floating-point: 345.678 + - hexidecimal: 0x123abc + - exponential: 12.3015e+02 + - octal: 0o14 + strings: + - unicode: "Sosa did fine.\u263A" + - control: "\b1998\t1999\t2000\n" + - hex esc: "\x0d\x0a is \r\n" + - single: '"Howdy!" he cried.' + - quoted: ' # Not a ''comment''.' + - tie-fighter: '|\-*-/|' + - plain: + This unquoted scalar + spans many lines. + + - quoted: "So does this + quoted scalar.\n" + - accomplishment: > + Mark set a major league + home run record in 1998. + - stats: | + 65 Home Runs + 0.278 Batting Average diff --git a/pkgs/yaml/benchmark/output.json b/pkgs/yaml/benchmark/output.json new file mode 100644 index 000000000..054cef7cf --- /dev/null +++ b/pkgs/yaml/benchmark/output.json @@ -0,0 +1 @@ +{"verb":"RecommendCafes","recipe":[{"outputs":["Cafe[]"],"verb":"List"},{"outputs":["CafeWithMenu[]"],"verb":"Fetch","inputs":["Cafe[]"]},{"outputs":["DishOffering[]"],"verb":"Flatten","inputs":["CafeWithMenu[]"]},{"outputs":["DishOffering[]/Scored"],"verb":"Score","inputs":["DishOffering[]"]},{"verb":"Display","inputs":["DishOffering[]/Scored"]}],"tags":{"numbers":[{"int":12345},{"negative":-345},{"floating-point":345.678},{"hexidecimal":1194684},{"exponential":1230.15},{"octal":12}],"dates":[{"canonical":"2001-12-15T02:59:43.1Z"},{"iso8601":"2001-12-14t21:59:43.10-05:00"},{"spaced":"2001-12-14 21:59:43.10 -5"},{"date":"2002-12-14"}],"strings":[{"unicode":"Sosa did fine.☺"},{"control":"\b1998\t1999\t2000\n"},{"hex esc":"\r\n is \r\n"},{"single":"\"Howdy!\" he cried."},{"quoted":" # Not a 'comment'."},{"tie-fighter":"|\\-*-/|"},{"plain":"This unquoted scalar spans many lines."},{"quoted":"So does this quoted scalar.\n"},{"accomplishment":"Mark set a major league home run record in 1998.\n"},{"stats":"65 Home Runs\n0.278 Batting Average\n"}],"booleans":[true,false]}} \ No newline at end of file From 164e96899731b7bc1aa5e64cd5fac27a58572702 Mon Sep 17 00:00:00 2001 From: Robert Nystrom Date: Tue, 1 Sep 2015 17:13:13 -0700 Subject: [PATCH 055/179] Hoist tokenizing RegExps out. R=nweiz@google.com Review URL: https://codereview.chromium.org//1310423004 . --- pkgs/yaml/lib/src/loader.dart | 45 +++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index d80578fc9..07929579c 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -13,6 +13,31 @@ import 'yaml_document.dart'; import 'yaml_exception.dart'; import 'yaml_node.dart'; +/// Matches YAML null. +final _nullRegExp = new RegExp(r"^(null|Null|NULL|~|)$"); + +/// Matches a YAML bool. +final _boolRegExp = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"); + +/// Matches a YAML decimal integer like `+1234`. +final _decimalIntRegExp = new RegExp(r"^[-+]?[0-9]+$"); + +/// Matches a YAML octal integer like `0o123`. +final _octalIntRegExp = new RegExp(r"^0o([0-7]+)$"); + +/// Matches a YAML hexidecimal integer like `0x123abc`. +final _hexIntRegExp = new RegExp(r"^0x[0-9a-fA-F]+$"); + +/// Matches a YAML floating point number like `12.34+e56`. +final _floatRegExp = new RegExp( + r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"); + +/// Matches YAML infinity. +final _infinityRegExp = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$"); + +/// Matches YAML NaN. +final _nanRegExp = new RegExp(r"^\.(nan|NaN|NAN)$"); + /// A loader that reads [Event]s emitted by a [Parser] and emits /// [YamlDocument]s. /// @@ -183,9 +208,8 @@ class Loader { /// Parses a null scalar. YamlScalar _parseNull(ScalarEvent scalar) { - // TODO(nweiz): stop using regexps. // TODO(nweiz): add ScalarStyle and implicit metadata to the scalars. - if (new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(scalar.value)) { + if (_nullRegExp.hasMatch(scalar.value)) { return new YamlScalar.internal(null, scalar.span, scalar.style); } else { return null; @@ -194,8 +218,7 @@ class Loader { /// Parses a boolean scalar. YamlScalar _parseBool(ScalarEvent scalar) { - var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"). - firstMatch(scalar.value); + var match = _boolRegExp.firstMatch(scalar.value); if (match == null) return null; return new YamlScalar.internal( match.group(1) != null, scalar.span, scalar.style); @@ -203,19 +226,19 @@ class Loader { /// Parses an integer scalar. YamlScalar _parseInt(ScalarEvent scalar) { - var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(scalar.value); + var match = _decimalIntRegExp.firstMatch(scalar.value); if (match != null) { return new YamlScalar.internal( int.parse(match.group(0)), scalar.span, scalar.style); } - match = new RegExp(r"^0o([0-7]+)$").firstMatch(scalar.value); + match = _octalIntRegExp.firstMatch(scalar.value); if (match != null) { var n = int.parse(match.group(1), radix: 8); return new YamlScalar.internal(n, scalar.span, scalar.style); } - match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(scalar.value); + match = _hexIntRegExp.firstMatch(scalar.value); if (match != null) { return new YamlScalar.internal( int.parse(match.group(0)), scalar.span, scalar.style); @@ -226,9 +249,7 @@ class Loader { /// Parses a floating-point scalar. YamlScalar _parseFloat(ScalarEvent scalar) { - var match = new RegExp( - r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"). - firstMatch(scalar.value); + var match = _floatRegExp.firstMatch(scalar.value); if (match != null) { // YAML allows floats of the form "0.", but Dart does not. Fix up those // floats by removing the trailing dot. @@ -237,13 +258,13 @@ class Loader { double.parse(matchStr), scalar.span, scalar.style); } - match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(scalar.value); + match = _infinityRegExp.firstMatch(scalar.value); if (match != null) { var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; return new YamlScalar.internal(value, scalar.span, scalar.style); } - match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(scalar.value); + match = _nanRegExp.firstMatch(scalar.value); if (match != null) { return new YamlScalar.internal(double.NAN, scalar.span, scalar.style); } From e9ed99bae40b7d7c40f415aa5bcaa773e6105325 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 2 Sep 2015 11:41:07 -0700 Subject: [PATCH 056/179] Limit the number of benchmark trials. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1327733002 . --- pkgs/yaml/benchmark/benchmark.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/benchmark/benchmark.dart b/pkgs/yaml/benchmark/benchmark.dart index aec6d4b0c..388fccb5d 100644 --- a/pkgs/yaml/benchmark/benchmark.dart +++ b/pkgs/yaml/benchmark/benchmark.dart @@ -11,7 +11,7 @@ import 'package:path/path.dart' as p; import 'package:yaml/yaml.dart'; -const numTrials = 10000000; +const numTrials = 100; const runsPerTrial = 1000; final source = loadFile("input.yaml"); From 8351c3cd562ea32947565543b730f7a5ec95a5e6 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 2 Sep 2015 13:34:36 -0700 Subject: [PATCH 057/179] Improve performance by not doing binary searches. Normally getting the line and column of a SpanScanner or a SourceLocation needs a binary search through all the line endings in the source file. This CL avoids those searches by using an eager SpanScanner which does extra computation to track its current line and column position, and storing the line and column directly on _SimpleKey objects. See dart-lang/yaml#12 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1325133002 . --- pkgs/yaml/lib/src/scanner.dart | 27 +++++++++++++++++++++------ pkgs/yaml/pubspec.yaml | 5 +++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 512d72e8a..2e02a8f7d 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -292,7 +292,7 @@ class Scanner { /// /// [sourceUrl] can be a String or a [Uri]. Scanner(String source, {sourceUrl}) - : _scanner = new SpanScanner(source, sourceUrl: sourceUrl); + : _scanner = new SpanScanner.eager(source, sourceUrl: sourceUrl); /// Consumes and returns the next token. Token scan() { @@ -485,7 +485,7 @@ class Scanner { // everything but multiline simple keys in a block context. if (!_inBlockContext) continue; - if (key.location.line == _scanner.line) continue; + if (key.line == _scanner.line) continue; if (key.required) { throw new YamlException("Expected ':'.", _scanner.emptySpan); @@ -513,6 +513,8 @@ class Scanner { _removeSimpleKey(); _simpleKeys[_simpleKeys.length - 1] = new _SimpleKey( _tokensParsed + _tokens.length, + _scanner.line, + _scanner.column, _scanner.location, required: required); } @@ -660,7 +662,7 @@ class Scanner { _rollIndent( _scanner.column, TokenType.BLOCK_SEQUENCE_START, - _scanner.emptySpan.start); + _scanner.location); } else { // It is an error for the '-' indicator to occur in the flow context, but // we let the Parser detect and report it because it's able to point to @@ -683,7 +685,7 @@ class Scanner { _rollIndent( _scanner.column, TokenType.BLOCK_MAPPING_START, - _scanner.emptySpan.start); + _scanner.location); } // Simple keys are allowed after `?` in a block context. @@ -703,7 +705,7 @@ class Scanner { // In the block context, we may need to add the // [TokenType.BLOCK_MAPPING_START] token. _rollIndent( - simpleKey.location.column, + simpleKey.column, TokenType.BLOCK_MAPPING_START, simpleKey.location, tokenNumber: simpleKey.tokenNumber); @@ -1639,10 +1641,23 @@ class _SimpleKey { /// no longer on the current line. final SourceLocation location; + /// The line on which the key appears. + /// + /// We could get this from [location], but that requires a binary search + /// whereas this is O(1). + final int line; + + /// The column on which the key appears. + /// + /// We could get this from [location], but that requires a binary search + /// whereas this is O(1). + final int column; + /// Whether this key must exist for the document to be scanned. final bool required; - _SimpleKey(this.tokenNumber, this.location, {bool required}) + _SimpleKey(this.tokenNumber, this.line, this.column, this.location, + {bool required}) : required = required; } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index a25faa600..618f82bef 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -4,11 +4,12 @@ author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. dependencies: + charcode: "^1.1.0" collection: ">=1.1.0 <2.0.0" path: ">=1.2.0 <2.0.0" - string_scanner: ">=0.1.3 <0.2.0" + string_scanner: "^0.1.4" source_span: ">=1.0.0 <2.0.0" dev_dependencies: test: ">=0.12.0 <0.13.0" environment: - sdk: '>=1.5.0 <2.0.0' + sdk: '>=1.8.0 <2.0.0' From 8e9a30ef2a373659b50a7fe1ef2a134bdaeec039 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 2 Sep 2015 18:02:03 -0700 Subject: [PATCH 058/179] Don't use regular expressions in Loader. This is based on https://codereview.chromium.org/1325053002. It also avoids redundant parsing where possible. Closes dart-lang/yaml#12 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1329763002 . --- pkgs/yaml/CHANGELOG.md | 4 + pkgs/yaml/lib/src/loader.dart | 253 +++++++++++++++-------- pkgs/yaml/lib/src/yaml_node.dart | 10 +- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 4 +- pkgs/yaml/lib/yaml.dart | 2 +- pkgs/yaml/pubspec.yaml | 4 +- 6 files changed, 185 insertions(+), 92 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 5dcd74943..6359d97c6 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.4 + +* Substantially improve performance. + ## 2.1.3 * Add a hint that a colon might be missing when a mapping value is found in the diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 07929579c..533631041 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -4,6 +4,7 @@ library yaml.loader; +import 'package:charcode/ascii.dart'; import 'package:source_span/source_span.dart'; import 'equality.dart'; @@ -13,31 +14,6 @@ import 'yaml_document.dart'; import 'yaml_exception.dart'; import 'yaml_node.dart'; -/// Matches YAML null. -final _nullRegExp = new RegExp(r"^(null|Null|NULL|~|)$"); - -/// Matches a YAML bool. -final _boolRegExp = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$"); - -/// Matches a YAML decimal integer like `+1234`. -final _decimalIntRegExp = new RegExp(r"^[-+]?[0-9]+$"); - -/// Matches a YAML octal integer like `0o123`. -final _octalIntRegExp = new RegExp(r"^0o([0-7]+)$"); - -/// Matches a YAML hexidecimal integer like `0x123abc`. -final _hexIntRegExp = new RegExp(r"^0x[0-9a-fA-F]+$"); - -/// Matches a YAML floating point number like `12.34+e56`. -final _floatRegExp = new RegExp( - r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$"); - -/// Matches YAML infinity. -final _infinityRegExp = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$"); - -/// Matches YAML NaN. -final _nanRegExp = new RegExp(r"^\.(nan|NaN|NAN)$"); - /// A loader that reads [Event]s emitted by a [Parser] and emits /// [YamlDocument]s. /// @@ -133,15 +109,11 @@ class Loader { YamlNode _loadScalar(ScalarEvent scalar) { var node; if (scalar.tag == "!") { - node = _parseString(scalar); + node = new YamlScalar.internal(scalar.value, scalar); } else if (scalar.tag != null) { node = _parseByTag(scalar); } else { - node = _parseNull(scalar); - if (node == null) node = _parseBool(scalar); - if (node == null) node = _parseInt(scalar); - if (node == null) node = _parseFloat(scalar); - if (node == null) node = _parseString(scalar); + node = _parseScalar(scalar); } _registerAnchor(scalar.anchor, node); @@ -197,82 +169,191 @@ class Loader { /// Parses a scalar according to its tag name. YamlScalar _parseByTag(ScalarEvent scalar) { switch (scalar.tag) { - case "tag:yaml.org,2002:null": return _parseNull(scalar); - case "tag:yaml.org,2002:bool": return _parseBool(scalar); - case "tag:yaml.org,2002:int": return _parseInt(scalar); - case "tag:yaml.org,2002:float": return _parseFloat(scalar); - case "tag:yaml.org,2002:str": return _parseString(scalar); + case "tag:yaml.org,2002:null": + var result = _parseNull(scalar); + if (result != null) return result; + throw new YamlException("Invalid null scalar.", scalar.span); + case "tag:yaml.org,2002:bool": + var result = _parseBool(scalar); + if (result != null) return result; + throw new YamlException("Invalid bool scalar.", scalar.span); + case "tag:yaml.org,2002:int": + var result = _parseNumber(scalar, allowFloat: false); + if (result != null) return result; + throw new YamlException("Invalid int scalar.", scalar.span); + case "tag:yaml.org,2002:float": + var result = _parseNumber(scalar, allowInt: false); + if (result != null) return result; + throw new YamlException("Invalid float scalar.", scalar.span); + case "tag:yaml.org,2002:str": + return new YamlScalar.internal(scalar.value, scalar); + default: + throw new YamlException('Undefined tag: ${scalar.tag}.', scalar.span); } - throw new YamlException('Undefined tag: ${scalar.tag}.', scalar.span); } - /// Parses a null scalar. + /// Parses [scalar], which may be one of several types. + YamlScalar _parseScalar(ScalarEvent scalar) => + _tryParseScalar(scalar) ?? new YamlScalar.internal(scalar.value, scalar); + + /// Tries to parse [scalar]. + /// + /// If parsing fails, this returns `null`, indicating that the scalar should + /// be parsed as a string. + YamlScalar _tryParseScalar(ScalarEvent scalar) { + // Quickly check for the empty string, which means null. + var length = scalar.value.length; + if (length == 0) return new YamlScalar.internal(null, scalar); + + // Dispatch on the first character. + var firstChar = scalar.value.codeUnitAt(0); + switch (firstChar) { + case $dot: + case $plus: + case $minus: + return _parseNumber(scalar); + case $n: + case $N: + return length == 4 ? _parseNull(scalar) : null; + case $t: + case $T: + return length == 4 ? _parseBool(scalar) : null; + case $f: + case $F: + return length == 5 ? _parseBool(scalar) : null; + case $tilde: + return length == 1 ? new YamlScalar.internal(null, scalar) : null; + default: + if (firstChar >= $0 && firstChar <= $9) return _parseNumber(scalar); + return null; + } + } + + /// Parse a null scalar. + /// + /// Returns a Dart `null` if parsing fails. YamlScalar _parseNull(ScalarEvent scalar) { - // TODO(nweiz): add ScalarStyle and implicit metadata to the scalars. - if (_nullRegExp.hasMatch(scalar.value)) { - return new YamlScalar.internal(null, scalar.span, scalar.style); - } else { - return null; + switch (scalar.value) { + case "": + case "null": + case "Null": + case "NULL": + case "~": + return new YamlScalar.internal(null, scalar); + default: + return null; } } - /// Parses a boolean scalar. + /// Parse a boolean scalar. + /// + /// Returns `null` if parsing fails. YamlScalar _parseBool(ScalarEvent scalar) { - var match = _boolRegExp.firstMatch(scalar.value); - if (match == null) return null; - return new YamlScalar.internal( - match.group(1) != null, scalar.span, scalar.style); + switch (scalar.value) { + case "true": + case "True": + case "TRUE": + return new YamlScalar.internal(true, scalar); + case "false": + case "False": + case "FALSE": + return new YamlScalar.internal(false, scalar); + default: + return null; + } } - /// Parses an integer scalar. - YamlScalar _parseInt(ScalarEvent scalar) { - var match = _decimalIntRegExp.firstMatch(scalar.value); - if (match != null) { - return new YamlScalar.internal( - int.parse(match.group(0)), scalar.span, scalar.style); - } + /// Parses a numeric scalar. + /// + /// Returns `null` if parsing fails. + YamlNode _parseNumber(ScalarEvent scalar, {bool allowInt: true, + bool allowFloat: true}) { + var value = _parseNumberValue(scalar.value, + allowInt: allowInt, allowFloat: allowFloat); + return value == null ? null : new YamlScalar.internal(value, scalar); + } - match = _octalIntRegExp.firstMatch(scalar.value); - if (match != null) { - var n = int.parse(match.group(1), radix: 8); - return new YamlScalar.internal(n, scalar.span, scalar.style); + /// Parses the value of a number. + /// + /// Returns the number if it's parsed successfully, or `null` if it's not. + num _parseNumberValue(String contents, {bool allowInt: true, + bool allowFloat: true}) { + assert(allowInt || allowFloat); + + var firstChar = contents.codeUnitAt(0); + var length = contents.length; + + // Quick check for single digit integers. + if (allowInt && length == 1) { + var value = firstChar - $0; + return value >= 0 && value <= 9 ? value : null; } - match = _hexIntRegExp.firstMatch(scalar.value); - if (match != null) { - return new YamlScalar.internal( - int.parse(match.group(0)), scalar.span, scalar.style); - } + var secondChar = contents.codeUnitAt(1); - return null; - } + // Hexadecimal or octal integers. + if (allowInt && firstChar == $0) { + // int.parse supports 0x natively. + if (secondChar == $x) return int.parse(contents, onError: (_) => null); - /// Parses a floating-point scalar. - YamlScalar _parseFloat(ScalarEvent scalar) { - var match = _floatRegExp.firstMatch(scalar.value); - if (match != null) { - // YAML allows floats of the form "0.", but Dart does not. Fix up those - // floats by removing the trailing dot. - var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), ""); - return new YamlScalar.internal( - double.parse(matchStr), scalar.span, scalar.style); + if (secondChar == $o) { + var afterRadix = contents.substring(2); + return int.parse(afterRadix, radix: 8, onError: (_) => null); + } } - match = _infinityRegExp.firstMatch(scalar.value); - if (match != null) { - var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY; - return new YamlScalar.internal(value, scalar.span, scalar.style); + // Int or float starting with a digit or a +/- sign. + if ((firstChar >= $0 && firstChar <= $9) || + ((firstChar == $plus || firstChar == $minus) && + secondChar >= $0 && secondChar <= $9)) { + // Try to parse an int or, failing that, a double. + var result = null; + if (allowInt) { + // Pass "radix: 10" explicitly to ensure that "-0x10", which is valid + // Dart but invalid YAML, doesn't get parsed. + result = int.parse(contents, radix: 10, onError: (_) => null); + } + + if (allowFloat) result ??= double.parse(contents, (_) => null); + return result; } - match = _nanRegExp.firstMatch(scalar.value); - if (match != null) { - return new YamlScalar.internal(double.NAN, scalar.span, scalar.style); + if (!allowFloat) return null; + + // Now the only possibility is to parse a float starting with a dot or a + // sign and a dot, or the signed/unsigned infinity values and not-a-numbers. + if ((firstChar == $dot && secondChar >= $0 && secondChar <= $9) || + (firstChar == $minus || firstChar == $plus) && secondChar == $dot) { + // Starting with a . and a number or a sign followed by a dot. + if (length == 5) { + switch (contents) { + case "+.inf": + case "+.Inf": + case "+.INF": + return double.INFINITY; + case "-.inf": + case "-.Inf": + case "-.INF": + return -double.INFINITY; + } + } + + return double.parse(contents, (_) => null); + } + + if (length == 4 && firstChar == $dot) { + switch (contents) { + case ".inf": + case ".Inf": + case ".INF": + return double.INFINITY; + case ".nan": + case ".NaN": + case ".NAN": + return double.NAN; + } } return null; } - - /// Parses a string scalar. - YamlScalar _parseString(ScalarEvent scalar) => - new YamlScalar.internal(scalar.value, scalar.span, scalar.style); } diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 027bc1b32..d4961bb91 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -9,6 +9,7 @@ import 'dart:collection' as collection; import 'package:collection/collection.dart'; import 'package:source_span/source_span.dart'; +import 'event.dart'; import 'null_span.dart'; import 'style.dart'; import 'yaml_node_wrapper.dart'; @@ -163,7 +164,14 @@ class YamlScalar extends YamlNode { } /// Users of the library should not use this constructor. - YamlScalar.internal(this.value, SourceSpan span, this.style) { + YamlScalar.internal(this.value, ScalarEvent scalar) + : style = scalar.style { + _span = span; + } + + /// Users of the library should not use this constructor. + YamlScalar.internalWithSpan(this.value, SourceSpan span) + : style = ScalarStyle.ANY { _span = span; } diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index be96ba4d5..d7146c450 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -59,7 +59,7 @@ class _YamlMapNodes extends MapBase final SourceSpan _span; Iterable get keys => _dartMap.keys.map((key) => - new YamlScalar.internal(key, _span, ScalarStyle.ANY)); + new YamlScalar.internalWithSpan(key, _span)); _YamlMapNodes(this._dartMap, this._span); @@ -151,5 +151,5 @@ class _YamlListNodes extends ListBase { YamlNode _nodeForValue(value, SourceSpan span) { if (value is Map) return new YamlMapWrapper._(value, span); if (value is List) return new YamlListWrapper._(value, span); - return new YamlScalar.internal(value, span, ScalarStyle.ANY); + return new YamlScalar.internalWithSpan(value, span); } diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 9af329a20..aa120ef97 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -53,7 +53,7 @@ YamlDocument loadYamlDocument(String yaml, {sourceUrl}) { var document = loader.load(); if (document == null) { return new YamlDocument.internal( - new YamlScalar.internal(null, loader.span, ScalarStyle.ANY), + new YamlScalar.internalWithSpan(null, loader.span), loader.span, null, const []); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 618f82bef..f6a5b1e62 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.4-dev +version: 2.1.4 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. @@ -12,4 +12,4 @@ dependencies: dev_dependencies: test: ">=0.12.0 <0.13.0" environment: - sdk: '>=1.8.0 <2.0.0' + sdk: '>=1.12.0 <2.0.0' From 765946c89efdd87c32b62e3e8f97d1d688eb1c50 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 8 Sep 2015 17:38:05 -0700 Subject: [PATCH 059/179] Fix source spans for scalars. Closes dart-lang/yaml#13 R=pquitslund@google.com, rnystrom@google.com Review URL: https://codereview.chromium.org//1329183002 . --- pkgs/yaml/CHANGELOG.md | 5 +++++ pkgs/yaml/lib/src/yaml_node.dart | 2 +- pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/yaml_test.dart | 37 ++++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 6359d97c6..2dfac867f 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.1.5 + +* Fix a bug with 2.1.4 where source span information was being discarded for + scalar values. + ## 2.1.4 * Substantially improve performance. diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index d4961bb91..99f751510 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -166,7 +166,7 @@ class YamlScalar extends YamlNode { /// Users of the library should not use this constructor. YamlScalar.internal(this.value, ScalarEvent scalar) : style = scalar.style { - _span = span; + _span = scalar.span; } /// Users of the library should not use this constructor. diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index f6a5b1e62..f91d9cffc 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.4 +version: 2.1.5 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 8091dc5b2..c4601d50d 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -54,6 +54,43 @@ main() { }); }); + test("includes source span information", () { + var yaml = loadYamlNode(r""" +- foo: + bar +- 123 +"""); + + expect(yaml.span.start.line, equals(0)); + expect(yaml.span.start.column, equals(0)); + expect(yaml.span.end.line, equals(3)); + expect(yaml.span.end.column, equals(0)); + + var map = yaml.nodes.first; + expect(map.span.start.line, equals(0)); + expect(map.span.start.column, equals(2)); + expect(map.span.end.line, equals(2)); + expect(map.span.end.column, equals(0)); + + var key = map.nodes.keys.first; + expect(key.span.start.line, equals(0)); + expect(key.span.start.column, equals(2)); + expect(key.span.end.line, equals(0)); + expect(key.span.end.column, equals(5)); + + var value = map.nodes.values.first; + expect(value.span.start.line, equals(1)); + expect(value.span.start.column, equals(4)); + expect(value.span.end.line, equals(1)); + expect(value.span.end.column, equals(7)); + + var scalar = yaml.nodes.last; + expect(scalar.span.start.line, equals(2)); + expect(scalar.span.start.column, equals(2)); + expect(scalar.span.end.line, equals(2)); + expect(scalar.span.end.column, equals(5)); + }); + // The following tests are all taken directly from the YAML spec // (http://www.yaml.org/spec/1.2/spec.html). Most of them are code examples // that are directly included in the spec, but additional tests are derived From 0dc36e4998b7532e52e029d66a9b7ff60fe452f4 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 24 Sep 2015 15:07:18 -0700 Subject: [PATCH 060/179] add a cast add a paramater type --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/lib/src/loader.dart | 2 +- pkgs/yaml/lib/src/parser.dart | 12 ++++++------ pkgs/yaml/pubspec.yaml | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 2dfac867f..f84570707 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.6 + +* Fix two analysis issues with DDC's strong mode. + ## 2.1.5 * Fix a bug with 2.1.4 where source span information was being discarded for diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 533631041..82ae4558e 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -63,7 +63,7 @@ class Loader { YamlDocument _loadDocument(DocumentStartEvent firstEvent) { var contents = _loadNode(_parser.parse()); - var lastEvent = _parser.parse(); + var lastEvent = _parser.parse() as DocumentEndEvent; assert(lastEvent.type == EventType.DOCUMENT_END); return new YamlDocument.internal( diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 8bb131f83..136247b74 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -115,7 +115,7 @@ class Parser { /// /// stream ::= /// STREAM-START implicit_document? explicit_document* STREAM-END - /// ************ + /// ************ Event _parseStreamStart() { var token = _scanner.scan(); assert(token.type == TokenType.STREAM_START); @@ -183,7 +183,7 @@ class Parser { /// /// explicit_document ::= /// DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* - /// *********** + /// *********** Event _parseDocumentContent() { var token = _scanner.peek(); @@ -462,7 +462,7 @@ class Parser { /// /// (VALUE block_node_or_indentless_sequence?)?)* /// ***** * - /// BLOCK-END + /// BLOCK-END /// Event _parseBlockMappingValue() { var token = _scanner.peek(); @@ -527,7 +527,7 @@ class Parser { _scanner.scan(); _state = _states.removeLast(); return new Event(EventType.SEQUENCE_END, token.span); - } + } /// Parses the productions: /// @@ -670,7 +670,7 @@ class Parser { var token = _scanner.peek(); var versionDirective; - var tagDirectives = []; + var tagDirectives = []; while (token.type == TokenType.VERSION_DIRECTIVE || token.type == TokenType.TAG_DIRECTIVE) { if (token is VersionDirectiveToken) { @@ -699,7 +699,7 @@ class Parser { token = _scanner.advance(); } - + _appendTagDirective( new TagDirective("!", "!"), token.span.start.pointSpan(), diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index f91d9cffc..9d92334c8 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.5 +version: 2.1.6 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. From 1786f59abca4c26b1862b36023da252d720983cd Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 1 Oct 2015 14:09:12 -0700 Subject: [PATCH 061/179] Fix some strong mode warnings in the parser. R=jmesserly@google.com Review URL: https://codereview.chromium.org//1375713005 . --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/lib/src/parser.dart | 16 ++++++++-------- pkgs/yaml/pubspec.yaml | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index f84570707..21fbf36a8 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.7 + +* Fix more strong mode warnings. + ## 2.1.6 * Fix two analysis issues with DDC's strong mode. diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 136247b74..b44043a1e 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -260,24 +260,24 @@ class Parser { var anchor; var tagToken; var span = token.span.start.pointSpan(); - parseAnchor() { + parseAnchor(token) { anchor = token.name; span = span.expand(token.span); - token = _scanner.advance(); + return _scanner.advance(); } - parseTag() { + parseTag(token) { tagToken = token; span = span.expand(token.span); - token = _scanner.advance(); + return _scanner.advance(); } if (token is AnchorToken) { - parseAnchor(); - if (token is TagToken) parseTag(); + token = parseAnchor(token); + if (token is TagToken) token = parseTag(token); } else if (token is TagToken) { - parseTag(); - if (token is AnchorToken) parseAnchor(); + token = parseTag(token); + if (token is AnchorToken) token = parseAnchor(token); } var tag; diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 9d92334c8..98f2e29ae 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.6 +version: 2.1.7-dev author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. From f36e14a098c650f9a582ee0386c37e0cd54167cd Mon Sep 17 00:00:00 2001 From: John Messerly Date: Thu, 1 Oct 2015 14:17:02 -0700 Subject: [PATCH 062/179] fixes dart-lang/yaml#15, strong mode errors and warnings --- pkgs/yaml/lib/src/loader.dart | 2 +- pkgs/yaml/lib/src/scanner.dart | 3 ++- pkgs/yaml/lib/yaml.dart | 8 +++++--- pkgs/yaml/pubspec.yaml | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 82ae4558e..07ae43051 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -127,7 +127,7 @@ class Loader { throw new YamlException("Invalid tag for sequence.", firstEvent.span); } - var children = []; + var children = []; var node = new YamlList.internal( children, firstEvent.span, firstEvent.style); _registerAnchor(firstEvent.anchor, node); diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 2e02a8f7d..0ac86dce8 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -443,7 +443,8 @@ class Scanner { var token = _tokens.last; if (token.type == TokenType.FLOW_SEQUENCE_END || token.type == TokenType.FLOW_MAPPING_END || - (token.type == TokenType.SCALAR && token.style.isQuoted)) { + (token.type == TokenType.SCALAR && + (token as ScalarToken).style.isQuoted)) { _fetchValue(); return; } diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index aa120ef97..0d48deae9 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -81,15 +81,17 @@ YamlDocument loadYamlDocument(String yaml, {sourceUrl}) { YamlList loadYamlStream(String yaml, {sourceUrl}) { var loader = new Loader(yaml, sourceUrl: sourceUrl); - var documents = []; + var documents = []; var document = loader.load(); while (document != null) { documents.add(document); document = loader.load(); } + // TODO(jmesserly): the type on the `document` parameter is a workaround for: + // https://github.com/dart-lang/dev_compiler/issues/203 return new YamlList.internal( - documents.map((document) => document.contents).toList(), + documents.map((YamlDocument document) => document.contents).toList(), loader.span, CollectionStyle.ANY); } @@ -101,7 +103,7 @@ YamlList loadYamlStream(String yaml, {sourceUrl}) { List loadYamlDocuments(String yaml, {sourceUrl}) { var loader = new Loader(yaml, sourceUrl: sourceUrl); - var documents = []; + var documents = []; var document = loader.load(); while (document != null) { documents.add(document); diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 98f2e29ae..46b74758d 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.7-dev +version: 2.1.7 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. From aee6282f864b29f8fa75e281553a6406c8eb3959 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 19 Jan 2016 15:39:51 -0800 Subject: [PATCH 063/179] Get rid of all the library tags. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1608993004 . --- pkgs/yaml/lib/src/equality.dart | 2 -- pkgs/yaml/lib/src/event.dart | 2 -- pkgs/yaml/lib/src/loader.dart | 2 -- pkgs/yaml/lib/src/null_span.dart | 2 -- pkgs/yaml/lib/src/parser.dart | 2 -- pkgs/yaml/lib/src/scanner.dart | 2 -- pkgs/yaml/lib/src/style.dart | 2 -- pkgs/yaml/lib/src/token.dart | 2 -- pkgs/yaml/lib/src/utils.dart | 2 -- pkgs/yaml/lib/src/yaml_document.dart | 2 -- pkgs/yaml/lib/src/yaml_exception.dart | 2 -- pkgs/yaml/lib/src/yaml_node.dart | 2 -- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 2 -- pkgs/yaml/lib/yaml.dart | 2 -- pkgs/yaml/test/utils.dart | 2 -- pkgs/yaml/test/yaml_node_wrapper_test.dart | 2 -- pkgs/yaml/test/yaml_test.dart | 2 -- 17 files changed, 34 deletions(-) diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index 540813599..a6874cb41 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -2,8 +2,6 @@ // 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 yaml.equality; - import 'dart:collection'; import 'package:collection/collection.dart'; diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart index 96e2f1666..a78c6ea1f 100644 --- a/pkgs/yaml/lib/src/event.dart +++ b/pkgs/yaml/lib/src/event.dart @@ -2,8 +2,6 @@ // 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 yaml.event; - import 'package:source_span/source_span.dart'; import 'style.dart'; diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 07ae43051..fee7769e2 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -2,8 +2,6 @@ // 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 yaml.loader; - import 'package:charcode/ascii.dart'; import 'package:source_span/source_span.dart'; diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index 06b42f020..43ac685bd 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -2,8 +2,6 @@ // 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 yaml.null_span; - import 'package:source_span/source_span.dart'; /// A [SourceSpan] with no location information. diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index b44043a1e..d5ed87aad 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -2,8 +2,6 @@ // 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 yaml.parser; - import 'package:source_span/source_span.dart'; import 'package:string_scanner/string_scanner.dart'; diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 0ac86dce8..15b021994 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -2,8 +2,6 @@ // 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 yaml.scanner; - import 'package:collection/collection.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:source_span/source_span.dart'; diff --git a/pkgs/yaml/lib/src/style.dart b/pkgs/yaml/lib/src/style.dart index 6305fce79..d23540402 100644 --- a/pkgs/yaml/lib/src/style.dart +++ b/pkgs/yaml/lib/src/style.dart @@ -2,8 +2,6 @@ // 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 yaml.style; - /// An enum of source scalar styles. class ScalarStyle { /// No source style was specified. diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 20ae547c6..5f91ce9b8 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -2,8 +2,6 @@ // 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 yaml.token; - import 'package:source_span/source_span.dart'; import 'style.dart'; diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 445221fe4..c1a58e4da 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -2,8 +2,6 @@ // 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 yaml.utils; - import 'package:source_span/source_span.dart'; /// A pair of values. diff --git a/pkgs/yaml/lib/src/yaml_document.dart b/pkgs/yaml/lib/src/yaml_document.dart index 4c249a0c1..61a82e737 100644 --- a/pkgs/yaml/lib/src/yaml_document.dart +++ b/pkgs/yaml/lib/src/yaml_document.dart @@ -2,8 +2,6 @@ // 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 yaml.yaml_document; - import 'dart:collection'; import 'package:source_span/source_span.dart'; diff --git a/pkgs/yaml/lib/src/yaml_exception.dart b/pkgs/yaml/lib/src/yaml_exception.dart index 86899531e..04067eea3 100644 --- a/pkgs/yaml/lib/src/yaml_exception.dart +++ b/pkgs/yaml/lib/src/yaml_exception.dart @@ -2,8 +2,6 @@ // 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 yaml.exception; - import 'package:source_span/source_span.dart'; /// An error thrown by the YAML processor. diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 99f751510..2b615d3b1 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -2,8 +2,6 @@ // 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 yaml.yaml_node; - import 'dart:collection' as collection; import 'package:collection/collection.dart'; diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index d7146c450..a0922ed98 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -2,8 +2,6 @@ // 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 yaml.yaml_node_wrapper; - import 'dart:collection'; import 'package:collection/collection.dart' as pkg_collection; diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 0d48deae9..9772464bb 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -2,8 +2,6 @@ // 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 yaml; - import 'src/loader.dart'; import 'src/style.dart'; import 'src/yaml_document.dart'; diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index a2d20196a..e1d4b6472 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -2,8 +2,6 @@ // 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 yaml.test.utils; - import 'package:test/test.dart'; import 'package:yaml/src/equality.dart' as equality; import 'package:yaml/yaml.dart'; diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index b76a73ba8..8cb8cfafc 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -2,8 +2,6 @@ // 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 yaml.node_wrapper_test; - import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index c4601d50d..d2f5d19ba 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -2,8 +2,6 @@ // 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 yaml.test; - import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; From c7a1b062a88f20ea07eab3ddf3679406db7e19e4 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 19 Jan 2016 15:40:19 -0800 Subject: [PATCH 064/179] Make "path" a dev dependency. Closes dart-lang/yaml#18 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1605933003 . --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 21fbf36a8..bb4d88e85 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.8 + +* Remove the dependency on `path`, since we don't actually import it. + ## 2.1.7 * Fix more strong mode warnings. diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 46b74758d..ad893095e 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,15 +1,15 @@ name: yaml -version: 2.1.7 +version: 2.1.8 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. dependencies: charcode: "^1.1.0" collection: ">=1.1.0 <2.0.0" - path: ">=1.2.0 <2.0.0" string_scanner: "^0.1.4" source_span: ">=1.0.0 <2.0.0" dev_dependencies: + path: ">=1.2.0 <2.0.0" test: ">=0.12.0 <0.13.0" environment: sdk: '>=1.12.0 <2.0.0' From c2c45f0ac15f9f5b0f491c403dc397f23c70d8ac Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 4 May 2016 16:52:43 -0700 Subject: [PATCH 065/179] Fix all strong-mode warnings. R=jmesserly@google.com Review URL: https://codereview.chromium.org//1948223002 . --- pkgs/yaml/.analysis_options | 2 ++ pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/lib/src/equality.dart | 3 ++- pkgs/yaml/lib/src/loader.dart | 2 +- pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/yaml_test.dart | 4 ++-- 6 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 pkgs/yaml/.analysis_options diff --git a/pkgs/yaml/.analysis_options b/pkgs/yaml/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/yaml/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index bb4d88e85..e1a43b2b5 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.9 + +* Fix all strong-mode warnings. + ## 2.1.8 * Remove the dependency on `path`, since we don't actually import it. diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index a6874cb41..846f7168a 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -9,7 +9,8 @@ import 'package:collection/collection.dart'; import 'yaml_node.dart'; /// Returns a [Map] that compares its keys based on [deepEquals]. -Map deepEqualsMap() => new HashMap(equals: deepEquals, hashCode: deepHashCode); +Map/**/ deepEqualsMap/**/() => + new HashMap(equals: deepEquals, hashCode: deepHashCode); /// Returns whether two objects are structurally equivalent. /// diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index fee7769e2..ea6eb9967 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -147,7 +147,7 @@ class Loader { throw new YamlException("Invalid tag for mapping.", firstEvent.span); } - var children = deepEqualsMap(); + var children = deepEqualsMap/**/(); var node = new YamlMap.internal( children, firstEvent.span, firstEvent.style); _registerAnchor(firstEvent.anchor, node); diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index ad893095e..87ddd5b69 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.8 +version: 2.1.9 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index d2f5d19ba..153af5e97 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -57,14 +57,14 @@ main() { - foo: bar - 123 -"""); +""") as YamlList; expect(yaml.span.start.line, equals(0)); expect(yaml.span.start.column, equals(0)); expect(yaml.span.end.line, equals(3)); expect(yaml.span.end.column, equals(0)); - var map = yaml.nodes.first; + var map = yaml.nodes.first as YamlMap; expect(map.span.start.line, equals(0)); expect(map.span.start.column, equals(2)); expect(map.span.end.line, equals(2)); From 047fb67ab8fdc72a5ba67e56d32bdf3bef7bf0f5 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 23 Jun 2016 14:40:51 -0700 Subject: [PATCH 066/179] Support string_scanner 1.0.0. R=kevmoo@google.com, cbracken@google.com Review URL: https://codereview.chromium.org//2085783002 . --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index e1a43b2b5..da7f6bd8b 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.10 + +* Support `string_scanner` 1.0.0. + ## 2.1.9 * Fix all strong-mode warnings. diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 87ddd5b69..990054f29 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,12 +1,12 @@ name: yaml -version: 2.1.9 +version: 2.1.10 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. dependencies: charcode: "^1.1.0" collection: ">=1.1.0 <2.0.0" - string_scanner: "^0.1.4" + string_scanner: ">=0.1.4 <2.0.0" source_span: ">=1.0.0 <2.0.0" dev_dependencies: path: ">=1.2.0 <2.0.0" From 089d3269749c3c6247f986a026de882503a8f5b0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 6 Oct 2016 08:31:20 -0700 Subject: [PATCH 067/179] fix a couple of analyzer errors --- pkgs/yaml/lib/src/parser.dart | 2 +- pkgs/yaml/lib/src/scanner.dart | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index d5ed87aad..df6ed75f5 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -667,7 +667,7 @@ class Parser { Pair> _processDirectives() { var token = _scanner.peek(); - var versionDirective; + VersionDirective versionDirective; var tagDirectives = []; while (token.type == TokenType.VERSION_DIRECTIVE || token.type == TokenType.TAG_DIRECTIVE) { diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 15b021994..b1ae1e34e 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -460,8 +460,6 @@ class Scanner { _fetchPlainScalar(); return; } - - throw 'Inaccessible'; } /// Throws an error about a disallowed character. From 58225d0915e1e717ffb1d9ec6117289a873a2380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9nes=20Alm=C3=A1si?= Date: Wed, 5 Oct 2016 17:56:39 +0100 Subject: [PATCH 068/179] Do not try to fetch more tokens if the stream end is encountered. --- pkgs/yaml/lib/src/scanner.dart | 3 +++ pkgs/yaml/test/yaml_test.dart | 37 ++++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 15b021994..47efd385e 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -324,6 +324,9 @@ class Scanner { if (_tokens.isNotEmpty) { _staleSimpleKeys(); + // If there are no more tokens to fetch, break. + if (_tokens.last.type == TokenType.STREAM_END) break; + // If the current token could be a simple key, we need to scan more // tokens until we determine whether it is or not. Otherwise we might // not emit the `KEY` token before we emit the value of the key. diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 153af5e97..053f6be29 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -29,26 +29,33 @@ main() { }); }); - group("refuses documents that declare version", () { - test("1.0", () { - expectYamlFails(""" - %YAML 1.0 - --- text - """); + group("refuses", () { + test("invalid contents", () { + // This caused the scanner to hang in an infinite loop. + expectYamlFails("{"); }); - test("1.3", () { - expectYamlFails(""" - %YAML 1.3 + group("documents that declare version", () { + test("1.0", () { + expectYamlFails(""" + %YAML 1.0 --- text """); - }); + }); - test("2.0", () { - expectYamlFails(""" - %YAML 2.0 - --- text - """); + test("1.3", () { + expectYamlFails(""" + %YAML 1.3 + --- text + """); + }); + + test("2.0", () { + expectYamlFails(""" + %YAML 2.0 + --- text + """); + }); }); }); From 7743b109ef9dd210f116db93552cd4c064a27f06 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 6 Oct 2016 13:17:18 -0700 Subject: [PATCH 069/179] Include a pull request reference. --- pkgs/yaml/test/yaml_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 053f6be29..8da4b8a6d 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -30,8 +30,8 @@ main() { }); group("refuses", () { + // Regression test for #19. test("invalid contents", () { - // This caused the scanner to hang in an infinite loop. expectYamlFails("{"); }); From 647a497ce0af8de9630aeba274ef8be3862dcc41 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 6 Oct 2016 13:19:46 -0700 Subject: [PATCH 070/179] Add pubspec and changelog entries. --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index da7f6bd8b..a60773b52 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.11 + +* Fix an infinite loop when parsing some invalid documents. + ## 2.1.10 * Support `string_scanner` 1.0.0. diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 990054f29..cc622c437 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.10 +version: 2.1.11 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. From 5831316e31cddbb052523a92159331e8d2c13142 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 13 Oct 2016 10:57:30 -0700 Subject: [PATCH 071/179] Reject duplicate keys. (dart-lang/yaml#22) --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/lib/src/loader.dart | 4 ++++ pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/yaml_test.dart | 4 ++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index a60773b52..eece5fe88 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.12 + +* Properly refuse mappings with duplicate keys. + ## 2.1.11 * Fix an infinite loop when parsing some invalid documents. diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index ea6eb9967..a2d681b92 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -156,6 +156,10 @@ class Loader { while (event.type != EventType.MAPPING_END) { var key = _loadNode(event); var value = _loadNode(_parser.parse()); + if (children.containsKey(key)) { + throw new YamlException("Duplicate mapping key.", key.span); + } + children[key] = value; event = _parser.parse(); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index cc622c437..d4445d9b2 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.11 +version: 2.1.12 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 8da4b8a6d..8dee6c6fc 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -35,6 +35,10 @@ main() { expectYamlFails("{"); }); + test("duplicate mapping keys", () { + expectYamlFails("{a: 1, a: 2}"); + }); + group("documents that declare version", () { test("1.0", () { expectYamlFails(""" From b6aae808c78d18f7cd20c397c106e7ffc4bde501 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 6 Apr 2017 17:02:04 -0700 Subject: [PATCH 072/179] enable Travis-CI --- pkgs/yaml/.travis.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 pkgs/yaml/.travis.yml diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml new file mode 100644 index 000000000..2173f35d5 --- /dev/null +++ b/pkgs/yaml/.travis.yml @@ -0,0 +1,20 @@ +language: dart +sudo: false +dart: + - stable + - dev + - 1.22.1 + - 1.21.1 + - 1.20.1 + - 1.19.1 +dart_task: + - test: -p vm + xvfb: false + - test: -p firefox + - test: -p dartium + install_dartium: true + - dartfmt + - dartanalyzer +cache: + directories: + - $HOME/.pub-cache From feff3e268ea9b5ee7982e189e5745bf801a6c08d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 6 Apr 2017 17:06:04 -0700 Subject: [PATCH 073/179] dartfmt --- pkgs/yaml/lib/src/equality.dart | 4 +- pkgs/yaml/lib/src/event.dart | 6 +- pkgs/yaml/lib/src/loader.dart | 40 +- pkgs/yaml/lib/src/null_span.dart | 3 +- pkgs/yaml/lib/src/parser.dart | 28 +- pkgs/yaml/lib/src/scanner.dart | 123 +-- pkgs/yaml/lib/src/style.dart | 1 - pkgs/yaml/lib/src/utils.dart | 2 - pkgs/yaml/lib/src/yaml_document.dart | 4 +- pkgs/yaml/lib/src/yaml_exception.dart | 4 +- pkgs/yaml/lib/src/yaml_node.dart | 14 +- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 4 +- pkgs/yaml/lib/yaml.dart | 3 +- pkgs/yaml/test/utils.dart | 4 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 56 +- pkgs/yaml/test/yaml_test.dart | 1035 +++++++++++--------- 16 files changed, 733 insertions(+), 598 deletions(-) diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index 846f7168a..886725918 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -58,7 +58,7 @@ class _DeepEquals { } } - /// Returns whether [list1] and [list2] are structurally equal. + /// Returns whether [list1] and [list2] are structurally equal. bool _listEquals(List list1, List list2) { if (list1.length != list2.length) return false; @@ -69,7 +69,7 @@ class _DeepEquals { return true; } - /// Returns whether [map1] and [map2] are structurally equal. + /// Returns whether [map1] and [map2] are structurally equal. bool _mapEquals(Map map1, Map map2) { if (map1.length != map2.length) return false; diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart index a78c6ea1f..296df22d6 100644 --- a/pkgs/yaml/lib/src/event.dart +++ b/pkgs/yaml/lib/src/event.dart @@ -35,8 +35,10 @@ class DocumentStartEvent implements Event { /// `===` sequence). final bool isImplicit; - DocumentStartEvent(this.span, {this.versionDirective, - List tagDirectives, this.isImplicit: true}) + DocumentStartEvent(this.span, + {this.versionDirective, + List tagDirectives, + this.isImplicit: true}) : tagDirectives = tagDirectives == null ? [] : tagDirectives; String toString() => "DOCUMENT_START"; diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index a2d681b92..a7568707d 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -76,11 +76,16 @@ class Loader { /// Composes a node. YamlNode _loadNode(Event firstEvent) { switch (firstEvent.type) { - case EventType.ALIAS: return _loadAlias(firstEvent); - case EventType.SCALAR: return _loadScalar(firstEvent); - case EventType.SEQUENCE_START: return _loadSequence(firstEvent); - case EventType.MAPPING_START: return _loadMapping(firstEvent); - default: throw "Unreachable"; + case EventType.ALIAS: + return _loadAlias(firstEvent); + case EventType.SCALAR: + return _loadScalar(firstEvent); + case EventType.SEQUENCE_START: + return _loadSequence(firstEvent); + case EventType.MAPPING_START: + return _loadMapping(firstEvent); + default: + throw "Unreachable"; } } @@ -120,14 +125,15 @@ class Loader { /// Composes a sequence node. YamlNode _loadSequence(SequenceStartEvent firstEvent) { - if (firstEvent.tag != "!" && firstEvent.tag != null && + if (firstEvent.tag != "!" && + firstEvent.tag != null && firstEvent.tag != "tag:yaml.org,2002:seq") { throw new YamlException("Invalid tag for sequence.", firstEvent.span); } var children = []; - var node = new YamlList.internal( - children, firstEvent.span, firstEvent.style); + var node = + new YamlList.internal(children, firstEvent.span, firstEvent.style); _registerAnchor(firstEvent.anchor, node); var event = _parser.parse(); @@ -142,14 +148,15 @@ class Loader { /// Composes a mapping node. YamlNode _loadMapping(MappingStartEvent firstEvent) { - if (firstEvent.tag != "!" && firstEvent.tag != null && + if (firstEvent.tag != "!" && + firstEvent.tag != null && firstEvent.tag != "tag:yaml.org,2002:map") { throw new YamlException("Invalid tag for mapping.", firstEvent.span); } var children = deepEqualsMap/**/(); - var node = new YamlMap.internal( - children, firstEvent.span, firstEvent.style); + var node = + new YamlMap.internal(children, firstEvent.span, firstEvent.style); _registerAnchor(firstEvent.anchor, node); var event = _parser.parse(); @@ -268,8 +275,8 @@ class Loader { /// Parses a numeric scalar. /// /// Returns `null` if parsing fails. - YamlNode _parseNumber(ScalarEvent scalar, {bool allowInt: true, - bool allowFloat: true}) { + YamlNode _parseNumber(ScalarEvent scalar, + {bool allowInt: true, bool allowFloat: true}) { var value = _parseNumberValue(scalar.value, allowInt: allowInt, allowFloat: allowFloat); return value == null ? null : new YamlScalar.internal(value, scalar); @@ -278,8 +285,8 @@ class Loader { /// Parses the value of a number. /// /// Returns the number if it's parsed successfully, or `null` if it's not. - num _parseNumberValue(String contents, {bool allowInt: true, - bool allowFloat: true}) { + num _parseNumberValue(String contents, + {bool allowInt: true, bool allowFloat: true}) { assert(allowInt || allowFloat); var firstChar = contents.codeUnitAt(0); @@ -307,7 +314,8 @@ class Loader { // Int or float starting with a digit or a +/- sign. if ((firstChar >= $0 && firstChar <= $9) || ((firstChar == $plus || firstChar == $minus) && - secondChar >= $0 && secondChar <= $9)) { + secondChar >= $0 && + secondChar <= $9)) { // Try to parse an int or, failing that, a double. var result = null; if (allowInt) { diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index 43ac685bd..eab4ec06d 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -14,6 +14,5 @@ class NullSpan extends SourceSpanMixin { SourceLocation get end => start; final text = ""; - NullSpan(sourceUrl) - : start = new SourceLocation(0, sourceUrl: sourceUrl); + NullSpan(sourceUrl) : start = new SourceLocation(0, sourceUrl: sourceUrl); } diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index df6ed75f5..24e9e029a 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -214,8 +214,8 @@ class Parser { _scanner.scan(); return new DocumentEndEvent(token.span, isImplicit: false); } else { - return new DocumentEndEvent( - token.span.start.pointSpan(), isImplicit: true); + return new DocumentEndEvent(token.span.start.pointSpan(), + isImplicit: true); } } @@ -305,8 +305,7 @@ class Parser { _state = _states.removeLast(); _scanner.scan(); - return new ScalarEvent( - span.expand(token.span), token.value, token.style, + return new ScalarEvent(span.expand(token.span), token.value, token.style, anchor: anchor, tag: tag); } @@ -331,7 +330,6 @@ class Parser { anchor: anchor, tag: tag); } - if (block && token.type == TokenType.BLOCK_MAPPING_START) { _state = _State.BLOCK_MAPPING_FIRST_KEY; return new MappingStartEvent( @@ -341,8 +339,7 @@ class Parser { if (anchor != null || tag != null) { _state = _states.removeLast(); - return new ScalarEvent( - span, '', ScalarStyle.PLAIN, + return new ScalarEvent(span, '', ScalarStyle.PLAIN, anchor: anchor, tag: tag); } @@ -514,8 +511,7 @@ class Parser { if (token.type == TokenType.KEY) { _state = _State.FLOW_SEQUENCE_ENTRY_MAPPING_KEY; _scanner.scan(); - return new MappingStartEvent( - token.span, CollectionStyle.FLOW); + return new MappingStartEvent(token.span, CollectionStyle.FLOW); } else if (token.type != TokenType.FLOW_SEQUENCE_END) { _states.add(_State.FLOW_SEQUENCE_ENTRY); return _parseNode(); @@ -579,8 +575,8 @@ class Parser { /// * Event _parseFlowSequenceEntryMappingEnd() { _state = _State.FLOW_SEQUENCE_ENTRY; - return new Event(EventType.MAPPING_END, - _scanner.peek().span.start.pointSpan()); + return new Event( + EventType.MAPPING_END, _scanner.peek().span.start.pointSpan()); } /// Parses the productions: @@ -670,7 +666,7 @@ class Parser { VersionDirective versionDirective; var tagDirectives = []; while (token.type == TokenType.VERSION_DIRECTIVE || - token.type == TokenType.TAG_DIRECTIVE) { + token.type == TokenType.TAG_DIRECTIVE) { if (token is VersionDirectiveToken) { if (versionDirective != null) { throw new YamlException("Duplicate %YAML directive.", token.span); @@ -679,7 +675,7 @@ class Parser { if (token.major != 1 || token.minor == 0) { throw new YamlException( "Incompatible YAML document. This parser only supports YAML 1.1 " - "and 1.2.", + "and 1.2.", token.span); } else if (token.minor > 2) { // TODO(nweiz): Print to stderr when issue 6943 is fixed and dart:io @@ -699,11 +695,9 @@ class Parser { } _appendTagDirective( - new TagDirective("!", "!"), - token.span.start.pointSpan(), + new TagDirective("!", "!"), token.span.start.pointSpan(), allowDuplicates: true); - _appendTagDirective( - new TagDirective("!!", "tag:yaml.org,2002:"), + _appendTagDirective(new TagDirective("!!", "tag:yaml.org,2002:"), token.span.start.pointSpan(), allowDuplicates: true); diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 9bf81143e..91556af4e 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -135,7 +135,7 @@ class Scanner { /// /// Entries in this list may be `null`, indicating that there is no valid /// simple key for the associated level of nesting. - /// + /// /// When a ":" is parsed and there's a simple key available, a [TokenType.KEY] /// token is inserted in [_tokens] before that key's token. This allows the /// parser to tell that the key is intended to be a mapping key. @@ -187,8 +187,8 @@ class Scanner { return true; default: return (char >= NUMBER_0 && char <= NUMBER_9) || - (char >= LETTER_A && char <= LETTER_Z) || - (char >= LETTER_CAP_A && char <= LETTER_CAP_Z); + (char >= LETTER_A && char <= LETTER_Z) || + (char >= LETTER_CAP_A && char <= LETTER_CAP_Z); } } @@ -222,8 +222,8 @@ class Scanner { var char = _scanner.peekChar(); if (char == null) return false; return (char >= NUMBER_0 && char <= NUMBER_9) || - (char >= LETTER_A && char <= LETTER_F) || - (char >= LETTER_CAP_A && char <= LETTER_CAP_F); + (char >= LETTER_A && char <= LETTER_F) || + (char >= LETTER_CAP_A && char <= LETTER_CAP_F); } /// Whether the character at the current position is a plain character. @@ -248,9 +248,9 @@ class Scanner { return true; default: return (char >= 0x00020 && char <= 0x00007E) || - (char >= 0x000A0 && char <= 0x00D7FF) || - (char >= 0x0E000 && char <= 0x00FFFD) || - (char >= 0x10000 && char <= 0x10FFFF); + (char >= 0x000A0 && char <= 0x00D7FF) || + (char >= 0x0E000 && char <= 0x00FFFD) || + (char >= 0x10000 && char <= 0x10FFFF); } } @@ -271,9 +271,9 @@ class Scanner { return true; default: return (char >= 0x00020 && char <= 0x00007E) || - (char >= 0x000A0 && char <= 0x00D7FF) || - (char >= 0x0E000 && char <= 0x00FFFD) || - (char >= 0x10000 && char <= 0x10FFFF); + (char >= 0x000A0 && char <= 0x00D7FF) || + (char >= 0x0E000 && char <= 0x00FFFD) || + (char >= 0x10000 && char <= 0x10FFFF); } } @@ -282,7 +282,8 @@ class Scanner { /// /// If so, this sets the scanner's last match to that indicator. bool get _isDocumentIndicator { - return _scanner.column == 0 && _isBlankOrEndAt(3) && + return _scanner.column == 0 && + _isBlankOrEndAt(3) && (_scanner.matches('---') || _scanner.matches('...')); } @@ -300,8 +301,7 @@ class Scanner { var token = _tokens.removeFirst(); _tokenAvailable = false; _tokensParsed++; - _streamEndProduced = token is Token && - token.type == TokenType.STREAM_END; + _streamEndProduced = token is Token && token.type == TokenType.STREAM_END; return token; } @@ -330,8 +330,8 @@ class Scanner { // If the current token could be a simple key, we need to scan more // tokens until we determine whether it is or not. Otherwise we might // not emit the `KEY` token before we emit the value of the key. - if (!_simpleKeys.any((key) => - key != null && key.tokenNumber == _tokensParsed)) { + if (!_simpleKeys + .any((key) => key != null && key.tokenNumber == _tokensParsed)) { break; } } @@ -655,14 +655,11 @@ class Scanner { if (_inBlockContext) { if (!_simpleKeyAllowed) { throw new YamlException( - "Block sequence entries are not allowed here.", - _scanner.emptySpan); + "Block sequence entries are not allowed here.", _scanner.emptySpan); } _rollIndent( - _scanner.column, - TokenType.BLOCK_SEQUENCE_START, - _scanner.location); + _scanner.column, TokenType.BLOCK_SEQUENCE_START, _scanner.location); } else { // It is an error for the '-' indicator to occur in the flow context, but // we let the Parser detect and report it because it's able to point to @@ -678,14 +675,12 @@ class Scanner { void _fetchKey() { if (_inBlockContext) { if (!_simpleKeyAllowed) { - throw new YamlException("Mapping keys are not allowed here.", - _scanner.emptySpan); + throw new YamlException( + "Mapping keys are not allowed here.", _scanner.emptySpan); } _rollIndent( - _scanner.column, - TokenType.BLOCK_MAPPING_START, - _scanner.location); + _scanner.column, TokenType.BLOCK_MAPPING_START, _scanner.location); } // Simple keys are allowed after `?` in a block context. @@ -705,9 +700,7 @@ class Scanner { // In the block context, we may need to add the // [TokenType.BLOCK_MAPPING_START] token. _rollIndent( - simpleKey.column, - TokenType.BLOCK_MAPPING_START, - simpleKey.location, + simpleKey.column, TokenType.BLOCK_MAPPING_START, simpleKey.location, tokenNumber: simpleKey.tokenNumber); // Remove the simple key. @@ -719,16 +712,14 @@ class Scanner { if (!_simpleKeyAllowed) { throw new YamlException( "Mapping values are not allowed here. Did you miss a colon " - "earlier?", + "earlier?", _scanner.emptySpan); } // If we're here, we've found the ':' indicator following a complex key. _rollIndent( - _scanner.column, - TokenType.BLOCK_MAPPING_START, - _scanner.location); + _scanner.column, TokenType.BLOCK_MAPPING_START, _scanner.location); _simpleKeyAllowed = true; } else if (_simpleKeyAllowed) { // If we're here, we've found the ':' indicator with an empty key. This @@ -798,7 +789,7 @@ class Scanner { // libyaml disallows tabs after "-", "?", or ":", but the spec allows // them. See section 6.2: http://yaml.org/spec/1.2/spec.html#id2778241. while (_scanner.peekChar() == SP || - ((!_inBlockContext || !afterLineBreak) && + ((!_inBlockContext || !afterLineBreak) && _scanner.peekChar() == TAB)) { _scanner.readChar(); } @@ -830,7 +821,7 @@ class Scanner { /// %YAML 1.2 # a comment \n /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /// %TAG !yaml! tag:yaml.org,2002: \n - /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Token _scanDirective() { var start = _scanner.state; @@ -860,8 +851,7 @@ class Scanner { _skipComment(); if (!_isBreakOrEnd) { - throw new YamlException( - "Expected comment or line break after directive.", + throw new YamlException("Expected comment or line break after directive.", _scanner.spanFrom(start)); } @@ -967,11 +957,17 @@ class Scanner { var next = _scanner.peekChar(); if (name.isEmpty || - (!_isBlankOrEnd && next != QUESTION && next != COLON && - next != COMMA && next != RIGHT_SQUARE && next != RIGHT_CURLY && - next != PERCENT && next != AT && next != GRAVE_ACCENT)) { - throw new YamlException("Expected alphanumeric character.", - _scanner.emptySpan); + (!_isBlankOrEnd && + next != QUESTION && + next != COLON && + next != COMMA && + next != RIGHT_SQUARE && + next != RIGHT_CURLY && + next != PERCENT && + next != AT && + next != GRAVE_ACCENT)) { + throw new YamlException( + "Expected alphanumeric character.", _scanner.emptySpan); } if (anchor) { @@ -1075,7 +1071,8 @@ class Scanner { // disallowed. var start = _scanner.position; var char = _scanner.peekChar(); - while (_isTagChar || (flowSeparators && + while (_isTagChar || + (flowSeparators && (char == COMMA || char == LEFT_SQUARE || char == RIGHT_SQUARE))) { _scanner.readChar(); char = _scanner.peekChar(); @@ -1134,8 +1131,8 @@ class Scanner { // Check if we're at the end of the line. if (!_isBreakOrEnd) { - throw new YamlException("Expected comment or line break.", - _scanner.emptySpan); + throw new YamlException( + "Expected comment or line break.", _scanner.emptySpan); } _skipLine(); @@ -1172,7 +1169,9 @@ class Scanner { trailingBlank = _isBlank; // Check if we need to fold the leading line break. - if (!literal && leadingBreak.isNotEmpty && !leadingBlank && + if (!literal && + leadingBreak.isNotEmpty && + !leadingBlank && !trailingBlank) { // Do we need to join the lines with a space? if (trailingBreaks.isEmpty) buffer.writeCharCode(SP); @@ -1270,7 +1269,8 @@ class Scanner { var leadingBlanks = false; while (!_isBlankOrEnd) { var char = _scanner.peekChar(); - if (singleQuote && char == SINGLE_QUOTE && + if (singleQuote && + char == SINGLE_QUOTE && _scanner.peekChar(1) == SINGLE_QUOTE) { // An escaped single quote. _scanner.readChar(); @@ -1350,8 +1350,8 @@ class Scanner { codeLength = 8; break; default: - throw new YamlException("Unknown escape character.", - _scanner.spanFrom(escapeStart)); + throw new YamlException( + "Unknown escape character.", _scanner.spanFrom(escapeStart)); } _scanner.readChar(); @@ -1372,8 +1372,7 @@ class Scanner { // Check the value and write the character. if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) { - throw new YamlException( - "Invalid Unicode character escape code.", + throw new YamlException("Invalid Unicode character escape code.", _scanner.spanFrom(escapeStart)); } @@ -1480,7 +1479,8 @@ class Scanner { while (_isBlank || _isBreak) { if (_isBlank) { // Check for a tab character messing up the intendation. - if (leadingBreak.isNotEmpty && _scanner.column < indent && + if (leadingBreak.isNotEmpty && + _scanner.column < indent && _scanner.peekChar() == TAB) { _scanner.error("Expected a space but found a tab.", length: 1); } @@ -1508,8 +1508,8 @@ class Scanner { // Allow a simple key after a plain scalar with leading blanks. if (leadingBreak.isNotEmpty) _simpleKeyAllowed = true; - return new ScalarToken(_scanner.spanFrom(start, end), buffer.toString(), - ScalarStyle.PLAIN); + return new ScalarToken( + _scanner.spanFrom(start, end), buffer.toString(), ScalarStyle.PLAIN); } /// Moves past the current line break, if there is one. @@ -1554,7 +1554,10 @@ class Scanner { // the source. bool _isBlankOrEndAt(int offset) { var char = _scanner.peekChar(offset); - return char == null || char == SP || char == TAB || char == CR || + return char == null || + char == SP || + char == TAB || + char == CR || char == LF; } @@ -1597,10 +1600,10 @@ class Scanner { return true; default: return char != null && - ((char >= 0x00020 && char <= 0x00007E) || - (char >= 0x000A0 && char <= 0x00D7FF) || - (char >= 0x0E000 && char <= 0x00FFFD) || - (char >= 0x10000 && char <= 0x10FFFF)); + ((char >= 0x00020 && char <= 0x00007E) || + (char >= 0x000A0 && char <= 0x00D7FF) || + (char >= 0x0E000 && char <= 0x00FFFD) || + (char >= 0x10000 && char <= 0x10FFFF)); } } @@ -1657,7 +1660,7 @@ class _SimpleKey { final bool required; _SimpleKey(this.tokenNumber, this.line, this.column, this.location, - {bool required}) + {bool required}) : required = required; } diff --git a/pkgs/yaml/lib/src/style.dart b/pkgs/yaml/lib/src/style.dart index d23540402..30082cfa6 100644 --- a/pkgs/yaml/lib/src/style.dart +++ b/pkgs/yaml/lib/src/style.dart @@ -19,7 +19,6 @@ class ScalarStyle { /// See http://yaml.org/spec/1.2/spec.html#id2795688. static const LITERAL = const ScalarStyle._("LITERAL"); - /// The folded scalar style, with a `>` prefix. /// /// See http://yaml.org/spec/1.2/spec.html#id2796251. diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index c1a58e4da..36e4e938c 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -38,5 +38,3 @@ YamlWarningCallback yamlWarningCallback = (message, [span]) { if (span != null) message = span.message(message); print(message); }; - - diff --git a/pkgs/yaml/lib/src/yaml_document.dart b/pkgs/yaml/lib/src/yaml_document.dart index 61a82e737..b3732238a 100644 --- a/pkgs/yaml/lib/src/yaml_document.dart +++ b/pkgs/yaml/lib/src/yaml_document.dart @@ -31,8 +31,8 @@ class YamlDocument { /// Users of the library should not use this constructor. YamlDocument.internal(this.contents, this.span, this.versionDirective, - List tagDirectives, {this.startImplicit: false, - this.endImplicit: false}) + List tagDirectives, + {this.startImplicit: false, this.endImplicit: false}) : tagDirectives = new UnmodifiableListView(tagDirectives); String toString() => contents.toString(); diff --git a/pkgs/yaml/lib/src/yaml_exception.dart b/pkgs/yaml/lib/src/yaml_exception.dart index 04067eea3..c4b7f28b8 100644 --- a/pkgs/yaml/lib/src/yaml_exception.dart +++ b/pkgs/yaml/lib/src/yaml_exception.dart @@ -6,7 +6,5 @@ import 'package:source_span/source_span.dart'; /// An error thrown by the YAML processor. class YamlException extends SourceSpanFormatException { - YamlException(String message, SourceSpan span) - : super(message, span); + YamlException(String message, SourceSpan span) : super(message, span); } - diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 2b615d3b1..7190c8180 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -39,7 +39,7 @@ abstract class YamlNode { } /// A read-only [Map] parsed from YAML. -class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { +class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// A view of [this] where the keys and values are guaranteed to be /// [YamlNode]s. /// @@ -64,8 +64,7 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - factory YamlMap({sourceUrl}) => - new YamlMapWrapper(const {}, sourceUrl); + factory YamlMap({sourceUrl}) => new YamlMapWrapper(const {}, sourceUrl); /// Wraps a Dart map so that it can be accessed (recursively) like a /// [YamlMap]. @@ -114,8 +113,7 @@ class YamlList extends YamlNode with collection.ListMixin { /// [sourceUrl] is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - factory YamlList({sourceUrl}) => - new YamlListWrapper(const [], sourceUrl); + factory YamlList({sourceUrl}) => new YamlListWrapper(const [], sourceUrl); /// Wraps a Dart list so that it can be accessed (recursively) like a /// [YamlList]. @@ -156,14 +154,12 @@ class YamlScalar extends YamlNode { /// [sourceUrl] is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - YamlScalar.wrap(this.value, {sourceUrl}) - : style = ScalarStyle.ANY { + YamlScalar.wrap(this.value, {sourceUrl}) : style = ScalarStyle.ANY { _span = new NullSpan(sourceUrl); } /// Users of the library should not use this constructor. - YamlScalar.internal(this.value, ScalarEvent scalar) - : style = scalar.style { + YamlScalar.internal(this.value, ScalarEvent scalar) : style = scalar.style { _span = scalar.span; } diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index a0922ed98..bcb0faac0 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -56,8 +56,8 @@ class _YamlMapNodes extends MapBase final SourceSpan _span; - Iterable get keys => _dartMap.keys.map((key) => - new YamlScalar.internalWithSpan(key, _span)); + Iterable get keys => + _dartMap.keys.map((key) => new YamlScalar.internalWithSpan(key, _span)); _YamlMapNodes(this._dartMap, this._span); diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 9772464bb..13d6dc271 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -52,7 +52,8 @@ YamlDocument loadYamlDocument(String yaml, {sourceUrl}) { if (document == null) { return new YamlDocument.internal( new YamlScalar.internalWithSpan(null, loader.span), - loader.span, null, const []); + loader.span, + null, const []); } var nextDocument = loader.load(); diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index e1d4b6472..f7203870e 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -12,8 +12,8 @@ final Matcher throwsYamlException = throwsA(new isInstanceOf()); /// Returns a matcher that asserts that the value equals [expected]. /// /// This handles recursive loops and considers `NaN` to equal itself. -Matcher deepEquals(expected) => predicate((actual) => - equality.deepEquals(actual, expected), "equals $expected"); +Matcher deepEquals(expected) => predicate( + (actual) => equality.deepEquals(actual, expected), "equals $expected"); /// Constructs a new yaml.YamlMap, optionally from a normal Map. Map deepEqualsMap([Map from]) { diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index 8cb8cfafc..5d9a102bd 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -41,14 +41,16 @@ main() { "scalar": "value" }); - expect(map, equals({ - "list": [1, 2, 3], - "map": { - "foo": "bar", - "nested": [4, 5, 6] - }, - "scalar": "value" - })); + expect( + map, + equals({ + "list": [1, 2, 3], + "map": { + "foo": "bar", + "nested": [4, 5, 6] + }, + "scalar": "value" + })); expect(map.span, isNullSpan(isNull)); expect(map["list"], new isInstanceOf()); @@ -94,14 +96,16 @@ main() { "value" ]); - expect(list, equals([ - [1, 2, 3], - { - "foo": "bar", - "nested": [4, 5, 6] - }, - "value" - ])); + expect( + list, + equals([ + [1, 2, 3], + { + "foo": "bar", + "nested": [4, 5, 6] + }, + "value" + ])); expect(list.span, isNullSpan(isNull)); expect(list[0], new isInstanceOf()); @@ -149,13 +153,13 @@ main() { } Matcher isNullSpan(sourceUrl) => predicate((span) { - expect(span, new isInstanceOf()); - expect(span.length, equals(0)); - expect(span.text, isEmpty); - expect(span.start, equals(span.end)); - expect(span.start.offset, equals(0)); - expect(span.start.line, equals(0)); - expect(span.start.column, equals(0)); - expect(span.sourceUrl, sourceUrl); - return true; -}); + expect(span, new isInstanceOf()); + expect(span.length, equals(0)); + expect(span.text, isEmpty); + expect(span.start, equals(span.end)); + expect(span.start.offset, equals(0)); + expect(span.start.line, equals(0)); + expect(span.start.column, equals(0)); + expect(span.sourceUrl, sourceUrl); + return true; + }); diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 8dee6c6fc..acddf5f9b 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -16,16 +16,14 @@ main() { e.toString().contains('Tab characters are not allowed as indentation')); test('using a tab as indentation', () { - expect(() => loadYaml('foo:\n\tbar'), - throwsA(tabError)); + expect(() => loadYaml('foo:\n\tbar'), throwsA(tabError)); }); test('using a tab not as indentation', () { expect(() => loadYaml(''' "foo \tbar" - error'''), - throwsA(isNot(tabError))); + error'''), throwsA(isNot(tabError))); }); }); @@ -115,27 +113,34 @@ main() { // the spec. group('2.1: Collections', () { test('[Example 2.1]', () { - expectYamlLoads(["Mark McGwire", "Sammy Sosa", "Ken Griffey"], - """ + expectYamlLoads( + ["Mark McGwire", "Sammy Sosa", "Ken Griffey"], + """ - Mark McGwire - Sammy Sosa - Ken Griffey"""); }); test('[Example 2.2]', () { - expectYamlLoads({"hr": 65, "avg": 0.278, "rbi": 147}, - """ + expectYamlLoads( + {"hr": 65, "avg": 0.278, "rbi": 147}, + """ hr: 65 # Home runs avg: 0.278 # Batting average rbi: 147 # Runs Batted In"""); }); test('[Example 2.3]', () { - expectYamlLoads({ - "american": ["Boston Red Sox", "Detroit Tigers", "New York Yankees"], - "national": ["New York Mets", "Chicago Cubs", "Atlanta Braves"], - }, - """ + expectYamlLoads( + { + "american": [ + "Boston Red Sox", + "Detroit Tigers", + "New York Yankees" + ], + "national": ["New York Mets", "Chicago Cubs", "Atlanta Braves"], + }, + """ american: - Boston Red Sox - Detroit Tigers @@ -147,11 +152,12 @@ main() { }); test('[Example 2.4]', () { - expectYamlLoads([ - {"name": "Mark McGwire", "hr": 65, "avg": 0.278}, - {"name": "Sammy Sosa", "hr": 63, "avg": 0.288}, - ], - """ + expectYamlLoads( + [ + {"name": "Mark McGwire", "hr": 65, "avg": 0.278}, + {"name": "Sammy Sosa", "hr": 63, "avg": 0.288}, + ], + """ - name: Mark McGwire hr: 65 @@ -163,23 +169,25 @@ main() { }); test('[Example 2.5]', () { - expectYamlLoads([ - ["name", "hr", "avg"], - ["Mark McGwire", 65, 0.278], - ["Sammy Sosa", 63, 0.288] - ], - """ + expectYamlLoads( + [ + ["name", "hr", "avg"], + ["Mark McGwire", 65, 0.278], + ["Sammy Sosa", 63, 0.288] + ], + """ - [name , hr, avg ] - [Mark McGwire, 65, 0.278] - [Sammy Sosa , 63, 0.288]"""); }); test('[Example 2.6]', () { - expectYamlLoads({ - "Mark McGwire": {"hr": 65, "avg": 0.278}, - "Sammy Sosa": {"hr": 63, "avg": 0.288} - }, - """ + expectYamlLoads( + { + "Mark McGwire": {"hr": 65, "avg": 0.278}, + "Sammy Sosa": {"hr": 63, "avg": 0.288} + }, + """ Mark McGwire: {hr: 65, avg: 0.278} Sammy Sosa: { hr: 63, @@ -190,11 +198,12 @@ main() { group('2.2: Structures', () { test('[Example 2.7]', () { - expectYamlStreamLoads([ - ["Mark McGwire", "Sammy Sosa", "Ken Griffey"], - ["Chicago Cubs", "St Louis Cardinals"] - ], - """ + expectYamlStreamLoads( + [ + ["Mark McGwire", "Sammy Sosa", "Ken Griffey"], + ["Chicago Cubs", "St Louis Cardinals"] + ], + """ # Ranking of 1998 home runs --- - Mark McGwire @@ -208,11 +217,20 @@ main() { }); test('[Example 2.8]', () { - expectYamlStreamLoads([ - {"time": "20:03:20", "player": "Sammy Sosa", "action": "strike (miss)"}, - {"time": "20:03:47", "player": "Sammy Sosa", "action": "grand slam"}, - ], - """ + expectYamlStreamLoads( + [ + { + "time": "20:03:20", + "player": "Sammy Sosa", + "action": "strike (miss)" + }, + { + "time": "20:03:47", + "player": "Sammy Sosa", + "action": "grand slam" + }, + ], + """ --- time: 20:03:20 player: Sammy Sosa @@ -226,11 +244,12 @@ main() { }); test('[Example 2.9]', () { - expectYamlLoads({ - "hr": ["Mark McGwire", "Sammy Sosa"], - "rbi": ["Sammy Sosa", "Ken Griffey"] - }, - """ + expectYamlLoads( + { + "hr": ["Mark McGwire", "Sammy Sosa"], + "rbi": ["Sammy Sosa", "Ken Griffey"] + }, + """ --- hr: # 1998 hr ranking - Mark McGwire @@ -242,11 +261,12 @@ main() { }); test('[Example 2.10]', () { - expectYamlLoads({ - "hr": ["Mark McGwire", "Sammy Sosa"], - "rbi": ["Sammy Sosa", "Ken Griffey"] - }, - """ + expectYamlLoads( + { + "hr": ["Mark McGwire", "Sammy Sosa"], + "rbi": ["Sammy Sosa", "Ken Griffey"] + }, + """ --- hr: - Mark McGwire @@ -260,10 +280,14 @@ main() { test('[Example 2.11]', () { var doc = deepEqualsMap(); doc[["Detroit Tigers", "Chicago cubs"]] = ["2001-07-23"]; - doc[["New York Yankees", "Atlanta Braves"]] = - ["2001-07-02", "2001-08-12", "2001-08-14"]; - expectYamlLoads(doc, - """ + doc[["New York Yankees", "Atlanta Braves"]] = [ + "2001-07-02", + "2001-08-12", + "2001-08-14" + ]; + expectYamlLoads( + doc, + """ ? - Detroit Tigers - Chicago cubs : @@ -276,12 +300,13 @@ main() { }); test('[Example 2.12]', () { - expectYamlLoads([ - {"item": "Super Hoop", "quantity": 1}, - {"item": "Basketball", "quantity": 4}, - {"item": "Big Shoes", "quantity": 1}, - ], - """ + expectYamlLoads( + [ + {"item": "Super Hoop", "quantity": 1}, + {"item": "Basketball", "quantity": 4}, + {"item": "Big Shoes", "quantity": 1}, + ], + """ --- # Products purchased - item : Super Hoop @@ -296,11 +321,10 @@ main() { group('2.3: Scalars', () { test('[Example 2.13]', () { expectYamlLoads( - cleanUpLiteral( - """ + cleanUpLiteral(""" \\//||\\/|| // || ||__"""), - """ + """ # ASCII Art --- | \\//||\\/|| @@ -308,8 +332,9 @@ main() { }); test('[Example 2.14]', () { - expectYamlLoads("Mark McGwire's year was crippled by a knee injury.", - """ + expectYamlLoads( + "Mark McGwire's year was crippled by a knee injury.", + """ --- > Mark McGwire's year was crippled @@ -318,15 +343,14 @@ main() { test('[Example 2.15]', () { expectYamlLoads( - cleanUpLiteral( - """ + cleanUpLiteral(""" Sammy Sosa completed another fine season with great stats. 63 Home Runs 0.288 Batting Average What a year!"""), - """ + """ > Sammy Sosa completed another fine season with great stats. @@ -338,12 +362,14 @@ main() { }); test('[Example 2.16]', () { - expectYamlLoads({ - "name": "Mark McGwire", - "accomplishment": "Mark set a major league home run record in 1998.\n", - "stats": "65 Home Runs\n0.278 Batting Average" - }, - """ + expectYamlLoads( + { + "name": "Mark McGwire", + "accomplishment": + "Mark set a major league home run record in 1998.\n", + "stats": "65 Home Runs\n0.278 Batting Average" + }, + """ name: Mark McGwire accomplishment: > Mark set a major league @@ -354,15 +380,16 @@ main() { }); test('[Example 2.17]', () { - expectYamlLoads({ - "unicode": "Sosa did fine.\u263A", - "control": "\b1998\t1999\t2000\n", - "hex esc": "\r\n is \r\n", - "single": '"Howdy!" he cried.', - "quoted": " # Not a 'comment'.", - "tie-fighter": "|\\-*-/|" - }, - """ + expectYamlLoads( + { + "unicode": "Sosa did fine.\u263A", + "control": "\b1998\t1999\t2000\n", + "hex esc": "\r\n is \r\n", + "single": '"Howdy!" he cried.', + "quoted": " # Not a 'comment'.", + "tie-fighter": "|\\-*-/|" + }, + """ unicode: "Sosa did fine.\\u263A" control: "\\b1998\\t1999\\t2000\\n" hex esc: "\\x0d\\x0a is \\r\\n" @@ -373,11 +400,12 @@ main() { }); test('[Example 2.18]', () { - expectYamlLoads({ - "plain": "This unquoted scalar spans many lines.", - "quoted": "So does this quoted scalar.\n" - }, - ''' + expectYamlLoads( + { + "plain": "This unquoted scalar spans many lines.", + "quoted": "So does this quoted scalar.\n" + }, + ''' plain: This unquoted scalar spans many lines. @@ -389,13 +417,14 @@ main() { group('2.4: Tags', () { test('[Example 2.19]', () { - expectYamlLoads({ - "canonical": 12345, - "decimal": 12345, - "octal": 12, - "hexadecimal": 12 - }, - """ + expectYamlLoads( + { + "canonical": 12345, + "decimal": 12345, + "octal": 12, + "hexadecimal": 12 + }, + """ canonical: 12345 decimal: +12345 octal: 0o14 @@ -403,14 +432,15 @@ main() { }); test('[Example 2.20]', () { - expectYamlLoads({ - "canonical": 1230.15, - "exponential": 1230.15, - "fixed": 1230.15, - "negative infinity": -infinity, - "not a number": nan - }, - """ + expectYamlLoads( + { + "canonical": 1230.15, + "exponential": 1230.15, + "fixed": 1230.15, + "negative infinity": -infinity, + "not a number": nan + }, + """ canonical: 1.23015e+3 exponential: 12.3015e+02 fixed: 1230.15 @@ -424,8 +454,9 @@ main() { "string": "012345" }); doc[null] = null; - expectYamlLoads(doc, - """ + expectYamlLoads( + doc, + """ null: booleans: [ true, false ] string: '012345'"""); @@ -440,32 +471,33 @@ main() { // doesn't plan to support. test('[Example 2.28]', () { - expectYamlStreamLoads([ - { - "Time": "2001-11-23 15:01:42 -5", - "User": "ed", - "Warning": "This is an error message for the log file" - }, - { - "Time": "2001-11-23 15:02:31 -5", - "User": "ed", - "Warning": "A slightly different error message." - }, - { - "DateTime": "2001-11-23 15:03:17 -5", - "User": "ed", - "Fatal": 'Unknown variable "bar"', - "Stack": [ + expectYamlStreamLoads( + [ { - "file": "TopClass.py", - "line": 23, - "code": 'x = MoreObject("345\\n")\n' + "Time": "2001-11-23 15:01:42 -5", + "User": "ed", + "Warning": "This is an error message for the log file" }, - {"file": "MoreClass.py", "line": 58, "code": "foo = bar"} - ] - } - ], - """ + { + "Time": "2001-11-23 15:02:31 -5", + "User": "ed", + "Warning": "A slightly different error message." + }, + { + "DateTime": "2001-11-23 15:03:17 -5", + "User": "ed", + "Fatal": 'Unknown variable "bar"', + "Stack": [ + { + "file": "TopClass.py", + "line": 23, + "code": 'x = MoreObject("345\\n")\n' + }, + {"file": "MoreClass.py", "line": 58, "code": "foo = bar"} + ] + } + ], + """ --- Time: 2001-11-23 15:01:42 -5 User: ed @@ -550,11 +582,12 @@ main() { group('5.3: Indicator Characters', () { test('[Example 5.3]', () { - expectYamlLoads({ - 'sequence': ['one', 'two'], - 'mapping': {'sky': 'blue', 'sea': 'green'} - }, - """ + expectYamlLoads( + { + 'sequence': ['one', 'two'], + 'mapping': {'sky': 'blue', 'sea': 'green'} + }, + """ sequence: - one - two @@ -565,11 +598,12 @@ main() { }); test('[Example 5.4]', () { - expectYamlLoads({ - 'sequence': ['one', 'two'], - 'mapping': {'sky': 'blue', 'sea': 'green'} - }, - """ + expectYamlLoads( + { + 'sequence': ['one', 'two'], + 'mapping': {'sky': 'blue', 'sea': 'green'} + }, + """ sequence: [ one, two, ] mapping: { sky: blue, sea: green }"""); }); @@ -579,11 +613,9 @@ main() { // Skipping 5.6 because it uses an undefined tag. test('[Example 5.7]', () { - expectYamlLoads({ - 'literal': "some\ntext\n", - 'folded': "some text\n" - }, - """ + expectYamlLoads( + {'literal': "some\ntext\n", 'folded': "some text\n"}, + """ literal: | some text @@ -594,19 +626,18 @@ main() { }); test('[Example 5.8]', () { - expectYamlLoads({ - 'single': "text", - 'double': "text" - }, - """ + expectYamlLoads( + {'single': "text", 'double': "text"}, + """ single: 'text' double: "text" """); }); test('[Example 5.9]', () { - expectYamlLoads("text", - """ + expectYamlLoads( + "text", + """ %YAML 1.2 --- text"""); }); @@ -631,18 +662,22 @@ main() { }); group('in a scalar context must be normalized', () { - test("from \\r to \\n", () => - expectYamlLoads(["foo\nbar"], indentLiteral('- |\n foo\r bar'))); - test("from \\r\\n to \\n", () => - expectYamlLoads(["foo\nbar"], indentLiteral('- |\n foo\r\n bar'))); + test( + "from \\r to \\n", + () => expectYamlLoads( + ["foo\nbar"], indentLiteral('- |\n foo\r bar'))); + test( + "from \\r\\n to \\n", + () => expectYamlLoads( + ["foo\nbar"], indentLiteral('- |\n foo\r\n bar'))); }); test('[Example 5.11]', () { expectYamlLoads( - cleanUpLiteral(""" + cleanUpLiteral(""" Line break (no glyph) Line break (glyphed)"""), - """ + """ | Line break (no glyph) Line break (glyphed)"""); @@ -651,11 +686,12 @@ main() { group('5.5: White Space Characters', () { test('[Example 5.12]', () { - expectYamlLoads({ - "quoted": "Quoted \t", - "block": 'void main() {\n\tprintf("Hello, world!\\n");\n}\n' - }, - """ + expectYamlLoads( + { + "quoted": "Quoted \t", + "block": 'void main() {\n\tprintf("Hello, world!\\n");\n}\n' + }, + """ # Tabs and spaces quoted: "Quoted \t" block:\t| @@ -669,12 +705,12 @@ main() { group('5.7: Escaped Characters', () { test('[Example 5.13]', () { expectYamlLoads( - "Fun with \x5C " - "\x22 \x07 \x08 \x1B \x0C " - "\x0A \x0D \x09 \x0B \x00 " - "\x20 \xA0 \x85 \u2028 \u2029 " - "A A A", - ''' + "Fun with \x5C " + "\x22 \x07 \x08 \x1B \x0C " + "\x0A \x0D \x09 \x0B \x00 " + "\x20 \xA0 \x85 \u2028 \u2029 " + "A A A", + ''' "Fun with \\\\ \\" \\a \\b \\e \\f \\ \\n \\r \\t \\v \\0 \\ @@ -691,24 +727,26 @@ main() { // Chapter 6: Basic Structures group('6.1: Indentation Spaces', () { test('may not include TAB characters', () { - expectYamlFails( - """ + expectYamlFails(""" - \t- foo \t- bar"""); }); test('must be the same for all sibling nodes', () { - expectYamlFails( - """ + expectYamlFails(""" - - foo - bar"""); }); test('may be different for the children of sibling nodes', () { - expectYamlLoads([["foo"], ["bar"]], - """ + expectYamlLoads( + [ + ["foo"], + ["bar"] + ], + """ - - foo - @@ -716,17 +754,14 @@ main() { }); test('[Example 6.1]', () { - expectYamlLoads({ - "Not indented": { - "By one space": "By four\n spaces\n", - "Flow style": [ - "By two", - "Also by two", - "Still by two" - ] - } - }, - """ + expectYamlLoads( + { + "Not indented": { + "By one space": "By four\n spaces\n", + "Flow style": ["By two", "Also by two", "Still by two"] + } + }, + """ # Leading comment line spaces are # neither content nor indentation. @@ -742,8 +777,14 @@ main() { }); test('[Example 6.2]', () { - expectYamlLoads({'a': ['b', ['c', 'd']]}, - """ + expectYamlLoads( + { + 'a': [ + 'b', + ['c', 'd'] + ] + }, + """ ? a : -\tb - -\tc @@ -753,8 +794,12 @@ main() { group('6.2: Separation Spaces', () { test('[Example 6.3]', () { - expectYamlLoads([{'foo': 'bar'}, ['baz', 'baz']], - """ + expectYamlLoads( + [ + {'foo': 'bar'}, + ['baz', 'baz'] + ], + """ - foo:\t bar - - baz -\tbaz"""); @@ -763,12 +808,13 @@ main() { group('6.3: Line Prefixes', () { test('[Example 6.4]', () { - expectYamlLoads({ - "plain": "text lines", - "quoted": "text lines", - "block": "text\n \tlines\n" - }, - """ + expectYamlLoads( + { + "plain": "text lines", + "quoted": "text lines", + "block": "text\n \tlines\n" + }, + """ plain: text lines quoted: "text @@ -782,11 +828,12 @@ main() { group('6.4: Empty Lines', () { test('[Example 6.5]', () { - expectYamlLoads({ - "Folding": "Empty line\nas a line feed", - "Chomping": "Clipped empty lines\n", - }, - """ + expectYamlLoads( + { + "Folding": "Empty line\nas a line feed", + "Chomping": "Clipped empty lines\n", + }, + """ Folding: "Empty line \t @@ -799,8 +846,9 @@ main() { group('6.5: Line Folding', () { test('[Example 6.6]', () { - expectYamlLoads("trimmed\n\n\nas space", - """ + expectYamlLoads( + "trimmed\n\n\nas space", + """ >- trimmed @@ -812,8 +860,9 @@ main() { }); test('[Example 6.7]', () { - expectYamlLoads("foo \n\n\t bar\n\nbaz\n", - """ + expectYamlLoads( + "foo \n\n\t bar\n\nbaz\n", + """ > foo @@ -824,8 +873,9 @@ main() { }); test('[Example 6.8]', () { - expectYamlLoads(" foo\nbar\nbaz ", - ''' + expectYamlLoads( + " foo\nbar\nbaz ", + ''' " foo @@ -844,24 +894,29 @@ main() { }); test('[Example 6.9]', () { - expectYamlLoads({'key': 'value'}, - """ + expectYamlLoads( + {'key': 'value'}, + """ key: # Comment value"""); }); group('outside of scalar content', () { test('may appear on a line of their own', () { - expectYamlLoads([1, 2], - """ + expectYamlLoads( + [1, 2], + """ - 1 # Comment - 2"""); }); test('are independent of indentation level', () { - expectYamlLoads([[1, 2]], - """ + expectYamlLoads( + [ + [1, 2] + ], + """ - - 1 # Comment @@ -869,8 +924,9 @@ main() { }); test('include lines containing only white space characters', () { - expectYamlLoads([1, 2], - """ + expectYamlLoads( + [1, 2], + """ - 1 \t - 2"""); @@ -879,8 +935,9 @@ main() { group('within scalar content', () { test('may not appear on a line of their own', () { - expectYamlLoads(["foo\n# not comment\nbar\n"], - """ + expectYamlLoads( + ["foo\n# not comment\nbar\n"], + """ - | foo # not comment @@ -889,8 +946,9 @@ main() { }); test("don't include lines containing only white space characters", () { - expectYamlLoads(["foo\n \t \nbar\n"], - """ + expectYamlLoads( + ["foo\n \t \nbar\n"], + """ - | foo \t @@ -900,16 +958,18 @@ main() { }); test('[Example 6.10]', () { - expectYamlLoads(null, - """ + expectYamlLoads( + null, + """ # Comment """); }); test('[Example 6.11]', () { - expectYamlLoads({'key': 'value'}, - """ + expectYamlLoads( + {'key': 'value'}, + """ key: # Comment # lines value @@ -918,8 +978,9 @@ main() { group('ending a block scalar header', () { test('may not be followed by additional comment lines', () { - expectYamlLoads(["# not comment\nfoo\n"], - """ + expectYamlLoads( + ["# not comment\nfoo\n"], + """ - | # comment # not comment foo @@ -930,20 +991,17 @@ main() { group('6.7: Separation Lines', () { test('may not be used within implicit keys', () { - expectYamlFails( - """ + expectYamlFails(""" [1, 2]: 3"""); }); test('[Example 6.12]', () { var doc = deepEqualsMap(); - doc[{'first': 'Sammy', 'last': 'Sosa'}] = { - 'hr': 65, - 'avg': 0.278 - }; - expectYamlLoads(doc, - """ + doc[{'first': 'Sammy', 'last': 'Sosa'}] = {'hr': 65, 'avg': 0.278}; + expectYamlLoads( + doc, + """ { first: Sammy, last: Sosa }: # Statistics: hr: # Home runs @@ -956,8 +1014,9 @@ main() { group('6.8: Directives', () { // TODO(nweiz): assert that this produces a warning test('[Example 6.13]', () { - expectYamlLoads("foo", - ''' + expectYamlLoads( + "foo", + ''' %FOO bar baz # Should be ignored # with a warning. --- "foo"'''); @@ -965,8 +1024,9 @@ main() { // TODO(nweiz): assert that this produces a warning. test('[Example 6.14]', () { - expectYamlLoads("foo", - ''' + expectYamlLoads( + "foo", + ''' %YAML 1.3 # Attempt parsing # with a warning --- @@ -974,24 +1034,23 @@ main() { }); test('[Example 6.15]', () { - expectYamlFails( - """ + expectYamlFails(""" %YAML 1.2 %YAML 1.1 foo"""); }); test('[Example 6.16]', () { - expectYamlLoads("foo", - ''' + expectYamlLoads( + "foo", + ''' %TAG !yaml! tag:yaml.org,2002: --- !yaml!str "foo"'''); }); test('[Example 6.17]', () { - expectYamlFails( - """ + expectYamlFails(""" %TAG ! !foo %TAG ! !foo bar"""); @@ -1003,18 +1062,17 @@ main() { group('6.9: Node Properties', () { test('may be specified in any order', () { - expectYamlLoads(["foo", "bar"], - """ + expectYamlLoads( + ["foo", "bar"], + """ - !!str &a1 foo - &a2 !!str bar"""); }); test('[Example 6.23]', () { - expectYamlLoads({ - "foo": "bar", - "baz": "foo" - }, - ''' + expectYamlLoads( + {"foo": "bar", "baz": "foo"}, + ''' !!str &a1 "foo": !!str bar &a2 baz : *a1'''); @@ -1032,8 +1090,9 @@ main() { // currently doesn't plan to support. test('[Example 6.28]', () { - expectYamlLoads(["12", 12, "12"], - ''' + expectYamlLoads( + ["12", 12, "12"], + ''' # Assuming conventional resolution: - "12" - 12 @@ -1041,11 +1100,9 @@ main() { }); test('[Example 6.29]', () { - expectYamlLoads({ - "First occurrence": "Value", - "Second occurrence": "Value" - }, - """ + expectYamlLoads( + {"First occurrence": "Value", "Second occurrence": "Value"}, + """ First occurrence: &anchor Value Second occurrence: *anchor"""); }); @@ -1054,8 +1111,7 @@ main() { // Chapter 7: Flow Styles group('7.1: Alias Nodes', () { test("must not use an anchor that doesn't previously occur", () { - expectYamlFails( - """ + expectYamlFails(""" - *anchor - &anchor foo"""); }); @@ -1065,33 +1121,28 @@ main() { }); group('must not specify', () { - test('tag properties', () => expectYamlFails( - """ + test('tag properties', () => expectYamlFails(""" - &anchor foo - !str *anchor""")); - test('anchor properties', () => expectYamlFails( - """ + test('anchor properties', () => expectYamlFails(""" - &anchor foo - &anchor2 *anchor""")); - test('content', () => expectYamlFails( - """ + test('content', () => expectYamlFails(""" - &anchor foo - *anchor bar""")); }); test('must preserve structural equality', () { - var doc = loadYaml(cleanUpLiteral( - """ + var doc = loadYaml(cleanUpLiteral(""" anchor: &anchor [a, b, c] alias: *anchor""")); var anchorList = doc['anchor']; var aliasList = doc['alias']; expect(anchorList, same(aliasList)); - doc = loadYaml(cleanUpLiteral( - """ + doc = loadYaml(cleanUpLiteral(""" ? &anchor [a, b, c] : ? *anchor : bar""")); @@ -1101,13 +1152,14 @@ main() { }); test('[Example 7.1]', () { - expectYamlLoads({ - "First occurrence": "Foo", - "Second occurrence": "Foo", - "Override anchor": "Bar", - "Reuse anchor": "Bar", - }, - """ + expectYamlLoads( + { + "First occurrence": "Foo", + "Second occurrence": "Foo", + "Override anchor": "Bar", + "Reuse anchor": "Bar", + }, + """ First occurrence: &anchor Foo Second occurrence: *anchor Override anchor: &anchor Bar @@ -1117,11 +1169,9 @@ main() { group('7.2: Empty Nodes', () { test('[Example 7.2]', () { - expectYamlLoads({ - "foo": "", - "": "bar" - }, - """ + expectYamlLoads( + {"foo": "", "": "bar"}, + """ { foo : !!str, !!str : bar, @@ -1131,8 +1181,9 @@ main() { test('[Example 7.3]', () { var doc = deepEqualsMap({"foo": null}); doc[null] = "bar"; - expectYamlLoads(doc, - """ + expectYamlLoads( + doc, + """ { ? foo :, : bar, @@ -1142,10 +1193,13 @@ main() { group('7.3: Flow Scalar Styles', () { test('[Example 7.4]', () { - expectYamlLoads({ - "implicit block key": [{"implicit flow key": "value"}] - }, - ''' + expectYamlLoads( + { + "implicit block key": [ + {"implicit flow key": "value"} + ] + }, + ''' "implicit block key" : [ "implicit flow key" : value, ]'''); @@ -1153,8 +1207,8 @@ main() { test('[Example 7.5]', () { expectYamlLoads( - "folded to a space,\nto a line feed, or \t \tnon-content", - ''' + "folded to a space,\nto a line feed, or \t \tnon-content", + ''' "folded to a space,\t @@ -1163,8 +1217,9 @@ main() { }); test('[Example 7.6]', () { - expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", - ''' + expectYamlLoads( + " 1st non-empty\n2nd non-empty 3rd non-empty ", + ''' " 1st non-empty 2nd non-empty @@ -1176,18 +1231,22 @@ main() { }); test('[Example 7.8]', () { - expectYamlLoads({ - "implicit block key": [{"implicit flow key": "value"}] - }, - """ + expectYamlLoads( + { + "implicit block key": [ + {"implicit flow key": "value"} + ] + }, + """ 'implicit block key' : [ 'implicit flow key' : value, ]"""); }); test('[Example 7.9]', () { - expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", - """ + expectYamlLoads( + " 1st non-empty\n2nd non-empty 3rd non-empty ", + """ ' 1st non-empty 2nd non-empty @@ -1195,15 +1254,22 @@ main() { }); test('[Example 7.10]', () { - expectYamlLoads([ - "::vector", ": - ()", "Up, up, and away!", -123, - "http://example.com/foo#bar", - [ - "::vector", ": - ()", "Up, up, and away!", -123, - "http://example.com/foo#bar" - ] - ], - ''' + expectYamlLoads( + [ + "::vector", + ": - ()", + "Up, up, and away!", + -123, + "http://example.com/foo#bar", + [ + "::vector", + ": - ()", + "Up, up, and away!", + -123, + "http://example.com/foo#bar" + ] + ], + ''' # Outside flow collection: - ::vector - ": - ()" @@ -1219,18 +1285,22 @@ main() { }); test('[Example 7.11]', () { - expectYamlLoads({ - "implicit block key": [{"implicit flow key": "value"}] - }, - """ + expectYamlLoads( + { + "implicit block key": [ + {"implicit flow key": "value"} + ] + }, + """ implicit block key : [ implicit flow key : value, ]"""); }); test('[Example 7.12]', () { - expectYamlLoads("1st non-empty\n2nd non-empty 3rd non-empty", - """ + expectYamlLoads( + "1st non-empty\n2nd non-empty 3rd non-empty", + """ 1st non-empty 2nd non-empty @@ -1240,21 +1310,26 @@ main() { group('7.4: Flow Collection Styles', () { test('[Example 7.13]', () { - expectYamlLoads([ - ['one', 'two'], - ['three', 'four'] - ], - """ + expectYamlLoads( + [ + ['one', 'two'], + ['three', 'four'] + ], + """ - [ one, two, ] - [three ,four]"""); }); test('[Example 7.14]', () { - expectYamlLoads([ - "double quoted", "single quoted", "plain text", ["nested"], - {"single": "pair"} - ], - """ + expectYamlLoads( + [ + "double quoted", + "single quoted", + "plain text", + ["nested"], + {"single": "pair"} + ], + """ [ "double quoted", 'single @@ -1266,23 +1341,22 @@ main() { }); test('[Example 7.15]', () { - expectYamlLoads([ - {"one": "two", "three": "four"}, - {"five": "six", "seven": "eight"}, - ], - """ + expectYamlLoads( + [ + {"one": "two", "three": "four"}, + {"five": "six", "seven": "eight"}, + ], + """ - { one : two , three: four , } - {five: six,seven : eight}"""); }); test('[Example 7.16]', () { - var doc = deepEqualsMap({ - "explicit": "entry", - "implicit": "entry" - }); + var doc = deepEqualsMap({"explicit": "entry", "implicit": "entry"}); doc[null] = null; - expectYamlLoads(doc, - """ + expectYamlLoads( + doc, + """ { ? explicit: entry, implicit: entry, @@ -1297,8 +1371,9 @@ main() { "omitted value": null }); doc[null] = "omitted key"; - expectYamlLoads(doc, - ''' + expectYamlLoads( + doc, + ''' { unquoted : "separate", http://foo.com, @@ -1308,12 +1383,9 @@ main() { }); test('[Example 7.18]', () { - expectYamlLoads({ - "adjacent": "value", - "readable": "value", - "empty": null - }, - ''' + expectYamlLoads( + {"adjacent": "value", "readable": "value", "empty": null}, + ''' { "adjacent":value, "readable": value, @@ -1322,16 +1394,22 @@ main() { }); test('[Example 7.19]', () { - expectYamlLoads([{"foo": "bar"}], - """ + expectYamlLoads( + [ + {"foo": "bar"} + ], + """ [ foo: bar ]"""); }); test('[Example 7.20]', () { - expectYamlLoads([{"foo bar": "baz"}], - """ + expectYamlLoads( + [ + {"foo bar": "baz"} + ], + """ [ ? foo bar : baz @@ -1345,8 +1423,15 @@ main() { var el2 = deepEqualsMap(); el2[{"JSON": "like"}] = "adjacent"; - expectYamlLoads([[{"YAML": "separate"}], [el1], [el2]], - """ + expectYamlLoads( + [ + [ + {"YAML": "separate"} + ], + [el1], + [el2] + ], + """ - [ YAML : separate ] - [ : empty key entry ] - [ {JSON: like}:adjacent ]"""); @@ -1368,8 +1453,15 @@ main() { group('7.5: Flow Nodes', () { test('[Example 7.23]', () { - expectYamlLoads([["a", "b"], {"a": "b"}, "a", "b", "c"], - """ + expectYamlLoads( + [ + ["a", "b"], + {"a": "b"}, + "a", + "b", + "c" + ], + """ - [ a, b ] - { a: b } - "a" @@ -1378,8 +1470,9 @@ main() { }); test('[Example 7.24]', () { - expectYamlLoads(["a", "b", "c", "c", ""], - """ + expectYamlLoads( + ["a", "b", "c", "c", ""], + """ - !!str "a" - 'b' - &anchor "c" @@ -1391,8 +1484,9 @@ main() { // Chapter 8: Block Styles group('8.1: Block Scalar Styles', () { test('[Example 8.1]', () { - expectYamlLoads(["literal\n", " folded\n", "keep\n\n", " strip"], - """ + expectYamlLoads( + ["literal\n", " folded\n", "keep\n\n", " strip"], + """ - | # Empty header literal - >1 # Indentation indicator @@ -1409,13 +1503,9 @@ main() { // "\t detected\n", not "\t\ndetected\n". However, I'm reasonably // confident that "\t\ndetected\n" is correct when parsed according to the // rest of the spec. - expectYamlLoads([ - "detected\n", - "\n\n# detected\n", - " explicit\n", - "\t\ndetected\n" - ], - """ + expectYamlLoads( + ["detected\n", "\n\n# detected\n", " explicit\n", "\t\ndetected\n"], + """ - | detected - > @@ -1431,27 +1521,25 @@ main() { }); test('[Example 8.3]', () { - expectYamlFails( - """ + expectYamlFails(""" - | text"""); - expectYamlFails( - """ + expectYamlFails(""" - > text text"""); - expectYamlFails( - """ + expectYamlFails(""" - |2 text"""); }); test('[Example 8.4]', () { - expectYamlLoads({"strip": "text", "clip": "text\n", "keep": "text\n"}, - """ + expectYamlLoads( + {"strip": "text", "clip": "text\n", "keep": "text\n"}, + """ strip: |- text clip: | @@ -1465,12 +1553,9 @@ main() { // This example in the spec only includes a single newline in the "keep" // value, but as far as I can tell that's not how it's supposed to be // parsed according to the rest of the spec. - expectYamlLoads({ - "strip": "# text", - "clip": "# text\n", - "keep": "# text\n\n" - }, - """ + expectYamlLoads( + {"strip": "# text", "clip": "# text\n", "keep": "# text\n\n"}, + """ # Strip # Comments: strip: |- @@ -1494,8 +1579,9 @@ main() { }); test('[Example 8.6]', () { - expectYamlLoads({"strip": "", "clip": "", "keep": "\n"}, - """ + expectYamlLoads( + {"strip": "", "clip": "", "keep": "\n"}, + """ strip: >- clip: > @@ -1506,8 +1592,9 @@ main() { }); test('[Example 8.7]', () { - expectYamlLoads("literal\n\ttext\n", - """ + expectYamlLoads( + "literal\n\ttext\n", + """ | literal \ttext @@ -1515,8 +1602,9 @@ main() { }); test('[Example 8.8]', () { - expectYamlLoads("\n\nliteral\n \n\ntext\n", - """ + expectYamlLoads( + "\n\nliteral\n \n\ntext\n", + """ | @@ -1529,8 +1617,9 @@ main() { }); test('[Example 8.9]', () { - expectYamlLoads("folded text\n", - """ + expectYamlLoads( + "folded text\n", + """ > folded text @@ -1539,7 +1628,7 @@ main() { test('[Example 8.10]', () { expectYamlLoads( - cleanUpLiteral(""" + cleanUpLiteral(""" folded line next line @@ -1550,7 +1639,7 @@ main() { last line """), - """ + """ > folded @@ -1574,18 +1663,28 @@ main() { group('8.2: Block Collection Styles', () { test('[Example 8.14]', () { - expectYamlLoads({"block sequence": ["one", {"two": "three"}]}, - """ + expectYamlLoads( + { + "block sequence": [ + "one", + {"two": "three"} + ] + }, + """ block sequence: - one - two : three"""); }); test('[Example 8.15]', () { - expectYamlLoads([ - null, "block node\n", ["one", "two"], {"one": "two"} - ], - """ + expectYamlLoads( + [ + null, + "block node\n", + ["one", "two"], + {"one": "two"} + ], + """ - # Empty - | block node @@ -1595,18 +1694,22 @@ main() { }); test('[Example 8.16]', () { - expectYamlLoads({"block mapping": {"key": "value"}}, - """ + expectYamlLoads( + { + "block mapping": {"key": "value"} + }, + """ block mapping: key: value"""); }); test('[Example 8.17]', () { - expectYamlLoads({ - "explicit key": null, - "block key\n": ["one", "two"] - }, - """ + expectYamlLoads( + { + "explicit key": null, + "block key\n": ["one", "two"] + }, + """ ? explicit key # Empty value ? | block key @@ -1620,8 +1723,9 @@ main() { "quoted key": ["entry"] }); doc[null] = null; - expectYamlLoads(doc, - ''' + expectYamlLoads( + doc, + ''' plain key: in-line value : # Both empty "quoted key": @@ -1631,16 +1735,25 @@ main() { test('[Example 8.19]', () { var el = deepEqualsMap(); el[{'earth': 'blue'}] = {'moon': 'white'}; - expectYamlLoads([{'sun': 'yellow'}, el], - """ + expectYamlLoads( + [ + {'sun': 'yellow'}, + el + ], + """ - sun: yellow - ? earth: blue : moon: white"""); }); test('[Example 8.20]', () { - expectYamlLoads(["flow in block", "Block scalar\n", {"foo": "bar"}], - ''' + expectYamlLoads( + [ + "flow in block", + "Block scalar\n", + {"foo": "bar"} + ], + ''' - "flow in block" - > @@ -1652,8 +1765,9 @@ main() { test('[Example 8.21]', () { // The spec doesn't include a newline after "value" in the parsed map, but // the block scalar is clipped so it should be retained. - expectYamlLoads({"literal": "value\n", "folded": "value"}, - """ + expectYamlLoads( + {"literal": "value\n", "folded": "value"}, + """ literal: |2 value folded: @@ -1663,11 +1777,15 @@ main() { }); test('[Example 8.22]', () { - expectYamlLoads({ - "sequence": ["entry", ["nested"]], - "mapping": {"foo": "bar"} - }, - """ + expectYamlLoads( + { + "sequence": [ + "entry", + ["nested"] + ], + "mapping": {"foo": "bar"} + }, + """ sequence: !!seq - entry - !!seq @@ -1683,8 +1801,9 @@ main() { // doesn't plan to support. test('[Example 9.2]', () { - expectYamlLoads("Document", - """ + expectYamlLoads( + "Document", + """ %YAML 1.2 --- Document @@ -1700,8 +1819,8 @@ main() { // indented the same amount, the text would be part of the literal, which // implies that the spec's parse of this document is incorrect. expectYamlStreamLoads( - ["Bare document", "%!PS-Adobe-2.0 # Not the first line\n"], - """ + ["Bare document", "%!PS-Adobe-2.0 # Not the first line\n"], + """ Bare document ... @@ -1713,8 +1832,12 @@ main() { }); test('[Example 9.4]', () { - expectYamlStreamLoads([{"matches %": 20}, null], - """ + expectYamlStreamLoads( + [ + {"matches %": 20}, + null + ], + """ --- { matches % : 20 } @@ -1727,8 +1850,9 @@ main() { test('[Example 9.5]', () { // The spec doesn't have a space between the second // "YAML" and "1.2", but this seems to be a typo. - expectYamlStreamLoads(["%!PS-Adobe-2.0\n", null], - """ + expectYamlStreamLoads( + ["%!PS-Adobe-2.0\n", null], + """ %YAML 1.2 --- | %!PS-Adobe-2.0 @@ -1740,8 +1864,13 @@ main() { }); test('[Example 9.6]', () { - expectYamlStreamLoads(["Document", null, {"matches %": 20}], - """ + expectYamlStreamLoads( + [ + "Document", + null, + {"matches %": 20} + ], + """ Document --- # Empty @@ -1755,19 +1884,20 @@ main() { // Chapter 10: Recommended Schemas group('10.1: Failsafe Schema', () { test('[Example 10.1]', () { - expectYamlLoads({ - "Block style": { - "Clark": "Evans", - "Ingy": "döt Net", - "Oren": "Ben-Kiki" - }, - "Flow style": { - "Clark": "Evans", - "Ingy": "döt Net", - "Oren": "Ben-Kiki" - } - }, - """ + expectYamlLoads( + { + "Block style": { + "Clark": "Evans", + "Ingy": "döt Net", + "Oren": "Ben-Kiki" + }, + "Flow style": { + "Clark": "Evans", + "Ingy": "döt Net", + "Oren": "Ben-Kiki" + } + }, + """ Block style: !!map Clark : Evans Ingy : döt Net @@ -1777,11 +1907,12 @@ main() { }); test('[Example 10.2]', () { - expectYamlLoads({ - "Block style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"], - "Flow style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"] - }, - """ + expectYamlLoads( + { + "Block style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"], + "Flow style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"] + }, + """ Block style: !!seq - Clark Evans - Ingy döt Net @@ -1791,11 +1922,12 @@ main() { }); test('[Example 10.3]', () { - expectYamlLoads({ - "Block style": "String: just a theory.", - "Flow style": "String: just a theory." - }, - ''' + expectYamlLoads( + { + "Block style": "String: just a theory.", + "Flow style": "String: just a theory." + }, + ''' Block style: !!str |- String: just a theory. @@ -1872,16 +2004,17 @@ main() { group('10.3: Core Schema', () { test('[Example 10.9]', () { - expectYamlLoads({ - "A null": null, - "Also a null": null, - "Not a null": "", - "Booleans": [true, true, false, false], - "Integers": [0, 7, 0x3A, -19], - "Floats": [0, 0, 0.5, 12000, -200000], - "Also floats": [infinity, -infinity, infinity, nan] - }, - ''' + expectYamlLoads( + { + "A null": null, + "Also a null": null, + "Not a null": "", + "Booleans": [true, true, false, false], + "Integers": [0, 7, 0x3A, -19], + "Floats": [0, 0, 0.5, 12000, -200000], + "Also floats": [infinity, -infinity, infinity, nan] + }, + ''' A null: null Also a null: # Empty Not a null: "" From dd792d4c98a2a5893949883c6327800e06afe21f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Jul 2017 08:05:05 -0700 Subject: [PATCH 074/179] Fix travis (dart-lang/yaml#28) --- pkgs/yaml/.travis.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml index 2173f35d5..15f2fd229 100644 --- a/pkgs/yaml/.travis.yml +++ b/pkgs/yaml/.travis.yml @@ -13,8 +13,17 @@ dart_task: - test: -p firefox - test: -p dartium install_dartium: true - - dartfmt - dartanalyzer + +matrix: + include: + - dart: stable + dart_task: dartfmt + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + cache: directories: - $HOME/.pub-cache From 0173460b161afbe945edd799b3d46c2d08bd1f86 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 18 Jul 2017 13:40:57 -0700 Subject: [PATCH 075/179] Update pubspec.yaml --- pkgs/yaml/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index d4445d9b2..2b6503068 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -12,4 +12,4 @@ dev_dependencies: path: ">=1.2.0 <2.0.0" test: ">=0.12.0 <0.13.0" environment: - sdk: '>=1.12.0 <2.0.0' + sdk: '>=1.12.0 <2.0.0-dev.infinity' From 572c076256338b3d4e082ebd8b2b2bdc4ae49e3c Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 18 Jul 2017 13:41:31 -0700 Subject: [PATCH 076/179] Rename .analysis_options to analysis_options.yaml --- pkgs/yaml/{.analysis_options => analysis_options.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkgs/yaml/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/yaml/.analysis_options b/pkgs/yaml/analysis_options.yaml similarity index 100% rename from pkgs/yaml/.analysis_options rename to pkgs/yaml/analysis_options.yaml From a0a95783b7477747845cae9516deaa79972fcfea Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 11 Sep 2017 15:32:06 -0700 Subject: [PATCH 077/179] Update README.md (dart-lang/yaml#32) --- pkgs/yaml/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index c78dc97d7..6f77bcdc6 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -1,5 +1,7 @@ A parser for [YAML](http://www.yaml.org/). +[![Build Status](https://travis-ci.org/dart-lang/yaml.svg?branch=master)](https://travis-ci.org/dart-lang/yaml) + Use `loadYaml` to load a single document, or `loadYamlStream` to load a stream of documents. For example: From dfeed38d4d65fad98789f63f5529390d413491fe Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 12 Sep 2017 16:14:53 -0700 Subject: [PATCH 078/179] Travis testing: dev, stable, and oldest supported (dart-lang/yaml#33) * Travis testing: dev, stable, and oldest supported * Require SDK >= 1.23.0 - range we can correctly test on travis --- pkgs/yaml/.travis.yml | 7 ++----- pkgs/yaml/pubspec.yaml | 6 +++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml index 15f2fd229..d0fdea5da 100644 --- a/pkgs/yaml/.travis.yml +++ b/pkgs/yaml/.travis.yml @@ -1,12 +1,9 @@ language: dart sudo: false dart: - - stable - dev - - 1.22.1 - - 1.21.1 - - 1.20.1 - - 1.19.1 + - stable + - 1.23.0 dart_task: - test: -p vm xvfb: false diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 2b6503068..8dd003496 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,8 +1,10 @@ name: yaml -version: 2.1.12 +version: 2.1.13-dev author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. +environment: + sdk: '>=1.23.0 <2.0.0-dev.infinity' dependencies: charcode: "^1.1.0" collection: ">=1.1.0 <2.0.0" @@ -11,5 +13,3 @@ dependencies: dev_dependencies: path: ">=1.2.0 <2.0.0" test: ">=0.12.0 <0.13.0" -environment: - sdk: '>=1.12.0 <2.0.0-dev.infinity' From 65d2acd0688201c54f244436259537c41d29dbd5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 18 Sep 2017 18:11:22 -0700 Subject: [PATCH 079/179] Remove -dev.infinity in SDK upper constraint --- pkgs/yaml/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 8dd003496..2d29bda88 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -4,7 +4,7 @@ author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. environment: - sdk: '>=1.23.0 <2.0.0-dev.infinity' + sdk: '>=1.23.0 <2.0.0' dependencies: charcode: "^1.1.0" collection: ">=1.1.0 <2.0.0" From 49455d1eea2fb42c514c3a68a02f7c164458eb56 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 27 Sep 2017 13:35:43 -0700 Subject: [PATCH 080/179] Stop using comment-based generic syntax (dart-lang/yaml#35) Closes dart-lang/yaml#34 --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/lib/src/equality.dart | 2 +- pkgs/yaml/lib/src/loader.dart | 2 +- pkgs/yaml/pubspec.yaml | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index eece5fe88..ce32d71a7 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.13 + +* Stop using comment-based generic syntax. + ## 2.1.12 * Properly refuse mappings with duplicate keys. diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index 886725918..3c947a9c1 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -9,7 +9,7 @@ import 'package:collection/collection.dart'; import 'yaml_node.dart'; /// Returns a [Map] that compares its keys based on [deepEquals]. -Map/**/ deepEqualsMap/**/() => +Map deepEqualsMap() => new HashMap(equals: deepEquals, hashCode: deepHashCode); /// Returns whether two objects are structurally equivalent. diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index a7568707d..94859a7fe 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -154,7 +154,7 @@ class Loader { throw new YamlException("Invalid tag for mapping.", firstEvent.span); } - var children = deepEqualsMap/**/(); + var children = deepEqualsMap(); var node = new YamlMap.internal(children, firstEvent.span, firstEvent.style); _registerAnchor(firstEvent.anchor, node); diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 2d29bda88..c255dc77a 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.13-dev +version: 2.1.13 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. From f224837bd30b4934bba18577bf7b2488f8c8ca2c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 20 Feb 2018 15:33:17 -0800 Subject: [PATCH 081/179] Don't test Dartium on Travis (dart-lang/yaml#37) --- pkgs/yaml/.travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml index d0fdea5da..0f85ddf65 100644 --- a/pkgs/yaml/.travis.yml +++ b/pkgs/yaml/.travis.yml @@ -1,15 +1,13 @@ language: dart -sudo: false + dart: - dev - stable - - 1.23.0 + dart_task: - test: -p vm xvfb: false - test: -p firefox - - test: -p dartium - install_dartium: true - dartanalyzer matrix: From 73004e8fda35270a68a9c0feccd504799dd0f9a7 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Tue, 15 May 2018 22:34:10 +0200 Subject: [PATCH 082/179] Remove upper case constants (dart-lang/yaml#39) --- pkgs/yaml/.travis.yml | 4 +- pkgs/yaml/CHANGELOG.md | 4 + pkgs/yaml/benchmark/benchmark.dart | 6 +- pkgs/yaml/lib/src/loader.dart | 8 +- pkgs/yaml/pubspec.yaml | 4 +- pkgs/yaml/test/yaml_test.dart | 880 +++++++++++------------------ 6 files changed, 345 insertions(+), 561 deletions(-) diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml index 0f85ddf65..6105af8bc 100644 --- a/pkgs/yaml/.travis.yml +++ b/pkgs/yaml/.travis.yml @@ -2,8 +2,6 @@ language: dart dart: - dev - - stable - dart_task: - test: -p vm xvfb: false @@ -12,7 +10,7 @@ dart_task: matrix: include: - - dart: stable + - dart: dev dart_task: dartfmt # Only building master means that we don't run two builds for each pull request. diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index ce32d71a7..fd41fdb8b 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.14 + +* Updated SDK version to 2.0.0-dev.17.0 + ## 2.1.13 * Stop using comment-based generic syntax. diff --git a/pkgs/yaml/benchmark/benchmark.dart b/pkgs/yaml/benchmark/benchmark.dart index 388fccb5d..e3521b1ff 100644 --- a/pkgs/yaml/benchmark/benchmark.dart +++ b/pkgs/yaml/benchmark/benchmark.dart @@ -18,7 +18,7 @@ final source = loadFile("input.yaml"); final expected = loadFile("output.json"); void main(List args) { - var best = double.INFINITY; + var best = double.infinity; // Run the benchmark several times. This ensures the VM is warmed up and lets // us see how much variance there is. @@ -40,8 +40,8 @@ void main(List args) { // Sanity check to make sure the output is what we expect and to make sure // the VM doesn't optimize "dead" code away. - if (JSON.encode(result) != expected) { - print("Incorrect output:\n${JSON.encode(result)}"); + if (jsonEncode(result) != expected) { + print("Incorrect output:\n${jsonEncode(result)}"); exit(1); } diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 94859a7fe..d00fc2c86 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -340,11 +340,11 @@ class Loader { case "+.inf": case "+.Inf": case "+.INF": - return double.INFINITY; + return double.infinity; case "-.inf": case "-.Inf": case "-.INF": - return -double.INFINITY; + return -double.infinity; } } @@ -356,11 +356,11 @@ class Loader { case ".inf": case ".Inf": case ".INF": - return double.INFINITY; + return double.infinity; case ".nan": case ".NaN": case ".NAN": - return double.NAN; + return double.nan; } } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index c255dc77a..b60d7cc1f 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,10 +1,10 @@ name: yaml -version: 2.1.13 +version: 2.1.14 author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. environment: - sdk: '>=1.23.0 <2.0.0' + sdk: '>=2.0.0-dev.17.0 <2.0.0' dependencies: charcode: "^1.1.0" collection: ">=1.1.0 <2.0.0" diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index acddf5f9b..727ee8e1c 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -113,34 +113,24 @@ main() { // the spec. group('2.1: Collections', () { test('[Example 2.1]', () { - expectYamlLoads( - ["Mark McGwire", "Sammy Sosa", "Ken Griffey"], - """ + expectYamlLoads(["Mark McGwire", "Sammy Sosa", "Ken Griffey"], """ - Mark McGwire - Sammy Sosa - Ken Griffey"""); }); test('[Example 2.2]', () { - expectYamlLoads( - {"hr": 65, "avg": 0.278, "rbi": 147}, - """ + expectYamlLoads({"hr": 65, "avg": 0.278, "rbi": 147}, """ hr: 65 # Home runs avg: 0.278 # Batting average rbi: 147 # Runs Batted In"""); }); test('[Example 2.3]', () { - expectYamlLoads( - { - "american": [ - "Boston Red Sox", - "Detroit Tigers", - "New York Yankees" - ], - "national": ["New York Mets", "Chicago Cubs", "Atlanta Braves"], - }, - """ + expectYamlLoads({ + "american": ["Boston Red Sox", "Detroit Tigers", "New York Yankees"], + "national": ["New York Mets", "Chicago Cubs", "Atlanta Braves"], + }, """ american: - Boston Red Sox - Detroit Tigers @@ -152,12 +142,10 @@ main() { }); test('[Example 2.4]', () { - expectYamlLoads( - [ - {"name": "Mark McGwire", "hr": 65, "avg": 0.278}, - {"name": "Sammy Sosa", "hr": 63, "avg": 0.288}, - ], - """ + expectYamlLoads([ + {"name": "Mark McGwire", "hr": 65, "avg": 0.278}, + {"name": "Sammy Sosa", "hr": 63, "avg": 0.288}, + ], """ - name: Mark McGwire hr: 65 @@ -169,25 +157,21 @@ main() { }); test('[Example 2.5]', () { - expectYamlLoads( - [ - ["name", "hr", "avg"], - ["Mark McGwire", 65, 0.278], - ["Sammy Sosa", 63, 0.288] - ], - """ + expectYamlLoads([ + ["name", "hr", "avg"], + ["Mark McGwire", 65, 0.278], + ["Sammy Sosa", 63, 0.288] + ], """ - [name , hr, avg ] - [Mark McGwire, 65, 0.278] - [Sammy Sosa , 63, 0.288]"""); }); test('[Example 2.6]', () { - expectYamlLoads( - { - "Mark McGwire": {"hr": 65, "avg": 0.278}, - "Sammy Sosa": {"hr": 63, "avg": 0.288} - }, - """ + expectYamlLoads({ + "Mark McGwire": {"hr": 65, "avg": 0.278}, + "Sammy Sosa": {"hr": 63, "avg": 0.288} + }, """ Mark McGwire: {hr: 65, avg: 0.278} Sammy Sosa: { hr: 63, @@ -198,12 +182,10 @@ main() { group('2.2: Structures', () { test('[Example 2.7]', () { - expectYamlStreamLoads( - [ - ["Mark McGwire", "Sammy Sosa", "Ken Griffey"], - ["Chicago Cubs", "St Louis Cardinals"] - ], - """ + expectYamlStreamLoads([ + ["Mark McGwire", "Sammy Sosa", "Ken Griffey"], + ["Chicago Cubs", "St Louis Cardinals"] + ], """ # Ranking of 1998 home runs --- - Mark McGwire @@ -217,20 +199,10 @@ main() { }); test('[Example 2.8]', () { - expectYamlStreamLoads( - [ - { - "time": "20:03:20", - "player": "Sammy Sosa", - "action": "strike (miss)" - }, - { - "time": "20:03:47", - "player": "Sammy Sosa", - "action": "grand slam" - }, - ], - """ + expectYamlStreamLoads([ + {"time": "20:03:20", "player": "Sammy Sosa", "action": "strike (miss)"}, + {"time": "20:03:47", "player": "Sammy Sosa", "action": "grand slam"}, + ], """ --- time: 20:03:20 player: Sammy Sosa @@ -244,12 +216,10 @@ main() { }); test('[Example 2.9]', () { - expectYamlLoads( - { - "hr": ["Mark McGwire", "Sammy Sosa"], - "rbi": ["Sammy Sosa", "Ken Griffey"] - }, - """ + expectYamlLoads({ + "hr": ["Mark McGwire", "Sammy Sosa"], + "rbi": ["Sammy Sosa", "Ken Griffey"] + }, """ --- hr: # 1998 hr ranking - Mark McGwire @@ -261,12 +231,10 @@ main() { }); test('[Example 2.10]', () { - expectYamlLoads( - { - "hr": ["Mark McGwire", "Sammy Sosa"], - "rbi": ["Sammy Sosa", "Ken Griffey"] - }, - """ + expectYamlLoads({ + "hr": ["Mark McGwire", "Sammy Sosa"], + "rbi": ["Sammy Sosa", "Ken Griffey"] + }, """ --- hr: - Mark McGwire @@ -285,9 +253,7 @@ main() { "2001-08-12", "2001-08-14" ]; - expectYamlLoads( - doc, - """ + expectYamlLoads(doc, """ ? - Detroit Tigers - Chicago cubs : @@ -300,13 +266,11 @@ main() { }); test('[Example 2.12]', () { - expectYamlLoads( - [ - {"item": "Super Hoop", "quantity": 1}, - {"item": "Basketball", "quantity": 4}, - {"item": "Big Shoes", "quantity": 1}, - ], - """ + expectYamlLoads([ + {"item": "Super Hoop", "quantity": 1}, + {"item": "Basketball", "quantity": 4}, + {"item": "Big Shoes", "quantity": 1}, + ], """ --- # Products purchased - item : Super Hoop @@ -320,11 +284,9 @@ main() { group('2.3: Scalars', () { test('[Example 2.13]', () { - expectYamlLoads( - cleanUpLiteral(""" + expectYamlLoads(cleanUpLiteral(""" \\//||\\/|| - // || ||__"""), - """ + // || ||__"""), """ # ASCII Art --- | \\//||\\/|| @@ -332,9 +294,7 @@ main() { }); test('[Example 2.14]', () { - expectYamlLoads( - "Mark McGwire's year was crippled by a knee injury.", - """ + expectYamlLoads("Mark McGwire's year was crippled by a knee injury.", """ --- > Mark McGwire's year was crippled @@ -342,15 +302,13 @@ main() { }); test('[Example 2.15]', () { - expectYamlLoads( - cleanUpLiteral(""" + expectYamlLoads(cleanUpLiteral(""" Sammy Sosa completed another fine season with great stats. 63 Home Runs 0.288 Batting Average - What a year!"""), - """ + What a year!"""), """ > Sammy Sosa completed another fine season with great stats. @@ -362,14 +320,11 @@ main() { }); test('[Example 2.16]', () { - expectYamlLoads( - { - "name": "Mark McGwire", - "accomplishment": - "Mark set a major league home run record in 1998.\n", - "stats": "65 Home Runs\n0.278 Batting Average" - }, - """ + expectYamlLoads({ + "name": "Mark McGwire", + "accomplishment": "Mark set a major league home run record in 1998.\n", + "stats": "65 Home Runs\n0.278 Batting Average" + }, """ name: Mark McGwire accomplishment: > Mark set a major league @@ -380,16 +335,14 @@ main() { }); test('[Example 2.17]', () { - expectYamlLoads( - { - "unicode": "Sosa did fine.\u263A", - "control": "\b1998\t1999\t2000\n", - "hex esc": "\r\n is \r\n", - "single": '"Howdy!" he cried.', - "quoted": " # Not a 'comment'.", - "tie-fighter": "|\\-*-/|" - }, - """ + expectYamlLoads({ + "unicode": "Sosa did fine.\u263A", + "control": "\b1998\t1999\t2000\n", + "hex esc": "\r\n is \r\n", + "single": '"Howdy!" he cried.', + "quoted": " # Not a 'comment'.", + "tie-fighter": "|\\-*-/|" + }, """ unicode: "Sosa did fine.\\u263A" control: "\\b1998\\t1999\\t2000\\n" hex esc: "\\x0d\\x0a is \\r\\n" @@ -400,12 +353,10 @@ main() { }); test('[Example 2.18]', () { - expectYamlLoads( - { - "plain": "This unquoted scalar spans many lines.", - "quoted": "So does this quoted scalar.\n" - }, - ''' + expectYamlLoads({ + "plain": "This unquoted scalar spans many lines.", + "quoted": "So does this quoted scalar.\n" + }, ''' plain: This unquoted scalar spans many lines. @@ -417,14 +368,12 @@ main() { group('2.4: Tags', () { test('[Example 2.19]', () { - expectYamlLoads( - { - "canonical": 12345, - "decimal": 12345, - "octal": 12, - "hexadecimal": 12 - }, - """ + expectYamlLoads({ + "canonical": 12345, + "decimal": 12345, + "octal": 12, + "hexadecimal": 12 + }, """ canonical: 12345 decimal: +12345 octal: 0o14 @@ -432,15 +381,13 @@ main() { }); test('[Example 2.20]', () { - expectYamlLoads( - { - "canonical": 1230.15, - "exponential": 1230.15, - "fixed": 1230.15, - "negative infinity": -infinity, - "not a number": nan - }, - """ + expectYamlLoads({ + "canonical": 1230.15, + "exponential": 1230.15, + "fixed": 1230.15, + "negative infinity": -infinity, + "not a number": nan + }, """ canonical: 1.23015e+3 exponential: 12.3015e+02 fixed: 1230.15 @@ -454,9 +401,7 @@ main() { "string": "012345" }); doc[null] = null; - expectYamlLoads( - doc, - """ + expectYamlLoads(doc, """ null: booleans: [ true, false ] string: '012345'"""); @@ -471,33 +416,31 @@ main() { // doesn't plan to support. test('[Example 2.28]', () { - expectYamlStreamLoads( - [ - { - "Time": "2001-11-23 15:01:42 -5", - "User": "ed", - "Warning": "This is an error message for the log file" - }, + expectYamlStreamLoads([ + { + "Time": "2001-11-23 15:01:42 -5", + "User": "ed", + "Warning": "This is an error message for the log file" + }, + { + "Time": "2001-11-23 15:02:31 -5", + "User": "ed", + "Warning": "A slightly different error message." + }, + { + "DateTime": "2001-11-23 15:03:17 -5", + "User": "ed", + "Fatal": 'Unknown variable "bar"', + "Stack": [ { - "Time": "2001-11-23 15:02:31 -5", - "User": "ed", - "Warning": "A slightly different error message." + "file": "TopClass.py", + "line": 23, + "code": 'x = MoreObject("345\\n")\n' }, - { - "DateTime": "2001-11-23 15:03:17 -5", - "User": "ed", - "Fatal": 'Unknown variable "bar"', - "Stack": [ - { - "file": "TopClass.py", - "line": 23, - "code": 'x = MoreObject("345\\n")\n' - }, - {"file": "MoreClass.py", "line": 58, "code": "foo = bar"} - ] - } - ], - """ + {"file": "MoreClass.py", "line": 58, "code": "foo = bar"} + ] + } + ], """ --- Time: 2001-11-23 15:01:42 -5 User: ed @@ -582,12 +525,10 @@ main() { group('5.3: Indicator Characters', () { test('[Example 5.3]', () { - expectYamlLoads( - { - 'sequence': ['one', 'two'], - 'mapping': {'sky': 'blue', 'sea': 'green'} - }, - """ + expectYamlLoads({ + 'sequence': ['one', 'two'], + 'mapping': {'sky': 'blue', 'sea': 'green'} + }, """ sequence: - one - two @@ -598,12 +539,10 @@ main() { }); test('[Example 5.4]', () { - expectYamlLoads( - { - 'sequence': ['one', 'two'], - 'mapping': {'sky': 'blue', 'sea': 'green'} - }, - """ + expectYamlLoads({ + 'sequence': ['one', 'two'], + 'mapping': {'sky': 'blue', 'sea': 'green'} + }, """ sequence: [ one, two, ] mapping: { sky: blue, sea: green }"""); }); @@ -613,9 +552,7 @@ main() { // Skipping 5.6 because it uses an undefined tag. test('[Example 5.7]', () { - expectYamlLoads( - {'literal': "some\ntext\n", 'folded': "some text\n"}, - """ + expectYamlLoads({'literal': "some\ntext\n", 'folded': "some text\n"}, """ literal: | some text @@ -626,18 +563,14 @@ main() { }); test('[Example 5.8]', () { - expectYamlLoads( - {'single': "text", 'double': "text"}, - """ + expectYamlLoads({'single': "text", 'double': "text"}, """ single: 'text' double: "text" """); }); test('[Example 5.9]', () { - expectYamlLoads( - "text", - """ + expectYamlLoads("text", """ %YAML 1.2 --- text"""); }); @@ -673,11 +606,9 @@ main() { }); test('[Example 5.11]', () { - expectYamlLoads( - cleanUpLiteral(""" + expectYamlLoads(cleanUpLiteral(""" Line break (no glyph) - Line break (glyphed)"""), - """ + Line break (glyphed)"""), """ | Line break (no glyph) Line break (glyphed)"""); @@ -686,12 +617,10 @@ main() { group('5.5: White Space Characters', () { test('[Example 5.12]', () { - expectYamlLoads( - { - "quoted": "Quoted \t", - "block": 'void main() {\n\tprintf("Hello, world!\\n");\n}\n' - }, - """ + expectYamlLoads({ + "quoted": "Quoted \t", + "block": 'void main() {\n\tprintf("Hello, world!\\n");\n}\n' + }, """ # Tabs and spaces quoted: "Quoted \t" block:\t| @@ -741,12 +670,10 @@ main() { }); test('may be different for the children of sibling nodes', () { - expectYamlLoads( - [ - ["foo"], - ["bar"] - ], - """ + expectYamlLoads([ + ["foo"], + ["bar"] + ], """ - - foo - @@ -754,14 +681,12 @@ main() { }); test('[Example 6.1]', () { - expectYamlLoads( - { - "Not indented": { - "By one space": "By four\n spaces\n", - "Flow style": ["By two", "Also by two", "Still by two"] - } - }, - """ + expectYamlLoads({ + "Not indented": { + "By one space": "By four\n spaces\n", + "Flow style": ["By two", "Also by two", "Still by two"] + } + }, """ # Leading comment line spaces are # neither content nor indentation. @@ -777,14 +702,12 @@ main() { }); test('[Example 6.2]', () { - expectYamlLoads( - { - 'a': [ - 'b', - ['c', 'd'] - ] - }, - """ + expectYamlLoads({ + 'a': [ + 'b', + ['c', 'd'] + ] + }, """ ? a : -\tb - -\tc @@ -794,12 +717,10 @@ main() { group('6.2: Separation Spaces', () { test('[Example 6.3]', () { - expectYamlLoads( - [ - {'foo': 'bar'}, - ['baz', 'baz'] - ], - """ + expectYamlLoads([ + {'foo': 'bar'}, + ['baz', 'baz'] + ], """ - foo:\t bar - - baz -\tbaz"""); @@ -808,13 +729,11 @@ main() { group('6.3: Line Prefixes', () { test('[Example 6.4]', () { - expectYamlLoads( - { - "plain": "text lines", - "quoted": "text lines", - "block": "text\n \tlines\n" - }, - """ + expectYamlLoads({ + "plain": "text lines", + "quoted": "text lines", + "block": "text\n \tlines\n" + }, """ plain: text lines quoted: "text @@ -828,12 +747,10 @@ main() { group('6.4: Empty Lines', () { test('[Example 6.5]', () { - expectYamlLoads( - { - "Folding": "Empty line\nas a line feed", - "Chomping": "Clipped empty lines\n", - }, - """ + expectYamlLoads({ + "Folding": "Empty line\nas a line feed", + "Chomping": "Clipped empty lines\n", + }, """ Folding: "Empty line \t @@ -846,9 +763,7 @@ main() { group('6.5: Line Folding', () { test('[Example 6.6]', () { - expectYamlLoads( - "trimmed\n\n\nas space", - """ + expectYamlLoads("trimmed\n\n\nas space", """ >- trimmed @@ -860,9 +775,7 @@ main() { }); test('[Example 6.7]', () { - expectYamlLoads( - "foo \n\n\t bar\n\nbaz\n", - """ + expectYamlLoads("foo \n\n\t bar\n\nbaz\n", """ > foo @@ -873,9 +786,7 @@ main() { }); test('[Example 6.8]', () { - expectYamlLoads( - " foo\nbar\nbaz ", - ''' + expectYamlLoads(" foo\nbar\nbaz ", ''' " foo @@ -894,29 +805,23 @@ main() { }); test('[Example 6.9]', () { - expectYamlLoads( - {'key': 'value'}, - """ + expectYamlLoads({'key': 'value'}, """ key: # Comment value"""); }); group('outside of scalar content', () { test('may appear on a line of their own', () { - expectYamlLoads( - [1, 2], - """ + expectYamlLoads([1, 2], """ - 1 # Comment - 2"""); }); test('are independent of indentation level', () { - expectYamlLoads( - [ - [1, 2] - ], - """ + expectYamlLoads([ + [1, 2] + ], """ - - 1 # Comment @@ -924,9 +829,7 @@ main() { }); test('include lines containing only white space characters', () { - expectYamlLoads( - [1, 2], - """ + expectYamlLoads([1, 2], """ - 1 \t - 2"""); @@ -935,9 +838,7 @@ main() { group('within scalar content', () { test('may not appear on a line of their own', () { - expectYamlLoads( - ["foo\n# not comment\nbar\n"], - """ + expectYamlLoads(["foo\n# not comment\nbar\n"], """ - | foo # not comment @@ -946,9 +847,7 @@ main() { }); test("don't include lines containing only white space characters", () { - expectYamlLoads( - ["foo\n \t \nbar\n"], - """ + expectYamlLoads(["foo\n \t \nbar\n"], """ - | foo \t @@ -958,18 +857,14 @@ main() { }); test('[Example 6.10]', () { - expectYamlLoads( - null, - """ + expectYamlLoads(null, """ # Comment """); }); test('[Example 6.11]', () { - expectYamlLoads( - {'key': 'value'}, - """ + expectYamlLoads({'key': 'value'}, """ key: # Comment # lines value @@ -978,9 +873,7 @@ main() { group('ending a block scalar header', () { test('may not be followed by additional comment lines', () { - expectYamlLoads( - ["# not comment\nfoo\n"], - """ + expectYamlLoads(["# not comment\nfoo\n"], """ - | # comment # not comment foo @@ -999,9 +892,7 @@ main() { test('[Example 6.12]', () { var doc = deepEqualsMap(); doc[{'first': 'Sammy', 'last': 'Sosa'}] = {'hr': 65, 'avg': 0.278}; - expectYamlLoads( - doc, - """ + expectYamlLoads(doc, """ { first: Sammy, last: Sosa }: # Statistics: hr: # Home runs @@ -1014,9 +905,7 @@ main() { group('6.8: Directives', () { // TODO(nweiz): assert that this produces a warning test('[Example 6.13]', () { - expectYamlLoads( - "foo", - ''' + expectYamlLoads("foo", ''' %FOO bar baz # Should be ignored # with a warning. --- "foo"'''); @@ -1024,9 +913,7 @@ main() { // TODO(nweiz): assert that this produces a warning. test('[Example 6.14]', () { - expectYamlLoads( - "foo", - ''' + expectYamlLoads("foo", ''' %YAML 1.3 # Attempt parsing # with a warning --- @@ -1041,9 +928,7 @@ main() { }); test('[Example 6.16]', () { - expectYamlLoads( - "foo", - ''' + expectYamlLoads("foo", ''' %TAG !yaml! tag:yaml.org,2002: --- !yaml!str "foo"'''); @@ -1062,17 +947,13 @@ main() { group('6.9: Node Properties', () { test('may be specified in any order', () { - expectYamlLoads( - ["foo", "bar"], - """ + expectYamlLoads(["foo", "bar"], """ - !!str &a1 foo - &a2 !!str bar"""); }); test('[Example 6.23]', () { - expectYamlLoads( - {"foo": "bar", "baz": "foo"}, - ''' + expectYamlLoads({"foo": "bar", "baz": "foo"}, ''' !!str &a1 "foo": !!str bar &a2 baz : *a1'''); @@ -1090,9 +971,7 @@ main() { // currently doesn't plan to support. test('[Example 6.28]', () { - expectYamlLoads( - ["12", 12, "12"], - ''' + expectYamlLoads(["12", 12, "12"], ''' # Assuming conventional resolution: - "12" - 12 @@ -1101,8 +980,7 @@ main() { test('[Example 6.29]', () { expectYamlLoads( - {"First occurrence": "Value", "Second occurrence": "Value"}, - """ + {"First occurrence": "Value", "Second occurrence": "Value"}, """ First occurrence: &anchor Value Second occurrence: *anchor"""); }); @@ -1152,14 +1030,12 @@ main() { }); test('[Example 7.1]', () { - expectYamlLoads( - { - "First occurrence": "Foo", - "Second occurrence": "Foo", - "Override anchor": "Bar", - "Reuse anchor": "Bar", - }, - """ + expectYamlLoads({ + "First occurrence": "Foo", + "Second occurrence": "Foo", + "Override anchor": "Bar", + "Reuse anchor": "Bar", + }, """ First occurrence: &anchor Foo Second occurrence: *anchor Override anchor: &anchor Bar @@ -1169,9 +1045,7 @@ main() { group('7.2: Empty Nodes', () { test('[Example 7.2]', () { - expectYamlLoads( - {"foo": "", "": "bar"}, - """ + expectYamlLoads({"foo": "", "": "bar"}, """ { foo : !!str, !!str : bar, @@ -1181,9 +1055,7 @@ main() { test('[Example 7.3]', () { var doc = deepEqualsMap({"foo": null}); doc[null] = "bar"; - expectYamlLoads( - doc, - """ + expectYamlLoads(doc, """ { ? foo :, : bar, @@ -1193,13 +1065,11 @@ main() { group('7.3: Flow Scalar Styles', () { test('[Example 7.4]', () { - expectYamlLoads( - { - "implicit block key": [ - {"implicit flow key": "value"} - ] - }, - ''' + expectYamlLoads({ + "implicit block key": [ + {"implicit flow key": "value"} + ] + }, ''' "implicit block key" : [ "implicit flow key" : value, ]'''); @@ -1207,8 +1077,7 @@ main() { test('[Example 7.5]', () { expectYamlLoads( - "folded to a space,\nto a line feed, or \t \tnon-content", - ''' + "folded to a space,\nto a line feed, or \t \tnon-content", ''' "folded to a space,\t @@ -1217,9 +1086,7 @@ main() { }); test('[Example 7.6]', () { - expectYamlLoads( - " 1st non-empty\n2nd non-empty 3rd non-empty ", - ''' + expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", ''' " 1st non-empty 2nd non-empty @@ -1231,22 +1098,18 @@ main() { }); test('[Example 7.8]', () { - expectYamlLoads( - { - "implicit block key": [ - {"implicit flow key": "value"} - ] - }, - """ + expectYamlLoads({ + "implicit block key": [ + {"implicit flow key": "value"} + ] + }, """ 'implicit block key' : [ 'implicit flow key' : value, ]"""); }); test('[Example 7.9]', () { - expectYamlLoads( - " 1st non-empty\n2nd non-empty 3rd non-empty ", - """ + expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", """ ' 1st non-empty 2nd non-empty @@ -1254,22 +1117,20 @@ main() { }); test('[Example 7.10]', () { - expectYamlLoads( - [ - "::vector", - ": - ()", - "Up, up, and away!", - -123, - "http://example.com/foo#bar", - [ - "::vector", - ": - ()", - "Up, up, and away!", - -123, - "http://example.com/foo#bar" - ] - ], - ''' + expectYamlLoads([ + "::vector", + ": - ()", + "Up, up, and away!", + -123, + "http://example.com/foo#bar", + [ + "::vector", + ": - ()", + "Up, up, and away!", + -123, + "http://example.com/foo#bar" + ] + ], ''' # Outside flow collection: - ::vector - ": - ()" @@ -1285,22 +1146,18 @@ main() { }); test('[Example 7.11]', () { - expectYamlLoads( - { - "implicit block key": [ - {"implicit flow key": "value"} - ] - }, - """ + expectYamlLoads({ + "implicit block key": [ + {"implicit flow key": "value"} + ] + }, """ implicit block key : [ implicit flow key : value, ]"""); }); test('[Example 7.12]', () { - expectYamlLoads( - "1st non-empty\n2nd non-empty 3rd non-empty", - """ + expectYamlLoads("1st non-empty\n2nd non-empty 3rd non-empty", """ 1st non-empty 2nd non-empty @@ -1310,26 +1167,22 @@ main() { group('7.4: Flow Collection Styles', () { test('[Example 7.13]', () { - expectYamlLoads( - [ - ['one', 'two'], - ['three', 'four'] - ], - """ + expectYamlLoads([ + ['one', 'two'], + ['three', 'four'] + ], """ - [ one, two, ] - [three ,four]"""); }); test('[Example 7.14]', () { - expectYamlLoads( - [ - "double quoted", - "single quoted", - "plain text", - ["nested"], - {"single": "pair"} - ], - """ + expectYamlLoads([ + "double quoted", + "single quoted", + "plain text", + ["nested"], + {"single": "pair"} + ], """ [ "double quoted", 'single @@ -1341,12 +1194,10 @@ main() { }); test('[Example 7.15]', () { - expectYamlLoads( - [ - {"one": "two", "three": "four"}, - {"five": "six", "seven": "eight"}, - ], - """ + expectYamlLoads([ + {"one": "two", "three": "four"}, + {"five": "six", "seven": "eight"}, + ], """ - { one : two , three: four , } - {five: six,seven : eight}"""); }); @@ -1354,9 +1205,7 @@ main() { test('[Example 7.16]', () { var doc = deepEqualsMap({"explicit": "entry", "implicit": "entry"}); doc[null] = null; - expectYamlLoads( - doc, - """ + expectYamlLoads(doc, """ { ? explicit: entry, implicit: entry, @@ -1371,9 +1220,7 @@ main() { "omitted value": null }); doc[null] = "omitted key"; - expectYamlLoads( - doc, - ''' + expectYamlLoads(doc, ''' { unquoted : "separate", http://foo.com, @@ -1384,8 +1231,7 @@ main() { test('[Example 7.18]', () { expectYamlLoads( - {"adjacent": "value", "readable": "value", "empty": null}, - ''' + {"adjacent": "value", "readable": "value", "empty": null}, ''' { "adjacent":value, "readable": value, @@ -1394,22 +1240,18 @@ main() { }); test('[Example 7.19]', () { - expectYamlLoads( - [ - {"foo": "bar"} - ], - """ + expectYamlLoads([ + {"foo": "bar"} + ], """ [ foo: bar ]"""); }); test('[Example 7.20]', () { - expectYamlLoads( - [ - {"foo bar": "baz"} - ], - """ + expectYamlLoads([ + {"foo bar": "baz"} + ], """ [ ? foo bar : baz @@ -1423,15 +1265,13 @@ main() { var el2 = deepEqualsMap(); el2[{"JSON": "like"}] = "adjacent"; - expectYamlLoads( - [ - [ - {"YAML": "separate"} - ], - [el1], - [el2] - ], - """ + expectYamlLoads([ + [ + {"YAML": "separate"} + ], + [el1], + [el2] + ], """ - [ YAML : separate ] - [ : empty key entry ] - [ {JSON: like}:adjacent ]"""); @@ -1453,15 +1293,13 @@ main() { group('7.5: Flow Nodes', () { test('[Example 7.23]', () { - expectYamlLoads( - [ - ["a", "b"], - {"a": "b"}, - "a", - "b", - "c" - ], - """ + expectYamlLoads([ + ["a", "b"], + {"a": "b"}, + "a", + "b", + "c" + ], """ - [ a, b ] - { a: b } - "a" @@ -1470,9 +1308,7 @@ main() { }); test('[Example 7.24]', () { - expectYamlLoads( - ["a", "b", "c", "c", ""], - """ + expectYamlLoads(["a", "b", "c", "c", ""], """ - !!str "a" - 'b' - &anchor "c" @@ -1484,9 +1320,7 @@ main() { // Chapter 8: Block Styles group('8.1: Block Scalar Styles', () { test('[Example 8.1]', () { - expectYamlLoads( - ["literal\n", " folded\n", "keep\n\n", " strip"], - """ + expectYamlLoads(["literal\n", " folded\n", "keep\n\n", " strip"], """ - | # Empty header literal - >1 # Indentation indicator @@ -1537,9 +1371,7 @@ main() { }); test('[Example 8.4]', () { - expectYamlLoads( - {"strip": "text", "clip": "text\n", "keep": "text\n"}, - """ + expectYamlLoads({"strip": "text", "clip": "text\n", "keep": "text\n"}, """ strip: |- text clip: | @@ -1554,8 +1386,7 @@ main() { // value, but as far as I can tell that's not how it's supposed to be // parsed according to the rest of the spec. expectYamlLoads( - {"strip": "# text", "clip": "# text\n", "keep": "# text\n\n"}, - """ + {"strip": "# text", "clip": "# text\n", "keep": "# text\n\n"}, """ # Strip # Comments: strip: |- @@ -1579,9 +1410,7 @@ main() { }); test('[Example 8.6]', () { - expectYamlLoads( - {"strip": "", "clip": "", "keep": "\n"}, - """ + expectYamlLoads({"strip": "", "clip": "", "keep": "\n"}, """ strip: >- clip: > @@ -1592,9 +1421,7 @@ main() { }); test('[Example 8.7]', () { - expectYamlLoads( - "literal\n\ttext\n", - """ + expectYamlLoads("literal\n\ttext\n", """ | literal \ttext @@ -1602,9 +1429,7 @@ main() { }); test('[Example 8.8]', () { - expectYamlLoads( - "\n\nliteral\n \n\ntext\n", - """ + expectYamlLoads("\n\nliteral\n \n\ntext\n", """ | @@ -1617,9 +1442,7 @@ main() { }); test('[Example 8.9]', () { - expectYamlLoads( - "folded text\n", - """ + expectYamlLoads("folded text\n", """ > folded text @@ -1627,8 +1450,7 @@ main() { }); test('[Example 8.10]', () { - expectYamlLoads( - cleanUpLiteral(""" + expectYamlLoads(cleanUpLiteral(""" folded line next line @@ -1638,8 +1460,7 @@ main() { * lines last line - """), - """ + """), """ > folded @@ -1663,28 +1484,24 @@ main() { group('8.2: Block Collection Styles', () { test('[Example 8.14]', () { - expectYamlLoads( - { - "block sequence": [ - "one", - {"two": "three"} - ] - }, - """ + expectYamlLoads({ + "block sequence": [ + "one", + {"two": "three"} + ] + }, """ block sequence: - one - two : three"""); }); test('[Example 8.15]', () { - expectYamlLoads( - [ - null, - "block node\n", - ["one", "two"], - {"one": "two"} - ], - """ + expectYamlLoads([ + null, + "block node\n", + ["one", "two"], + {"one": "two"} + ], """ - # Empty - | block node @@ -1694,22 +1511,18 @@ main() { }); test('[Example 8.16]', () { - expectYamlLoads( - { - "block mapping": {"key": "value"} - }, - """ + expectYamlLoads({ + "block mapping": {"key": "value"} + }, """ block mapping: key: value"""); }); test('[Example 8.17]', () { - expectYamlLoads( - { - "explicit key": null, - "block key\n": ["one", "two"] - }, - """ + expectYamlLoads({ + "explicit key": null, + "block key\n": ["one", "two"] + }, """ ? explicit key # Empty value ? | block key @@ -1723,9 +1536,7 @@ main() { "quoted key": ["entry"] }); doc[null] = null; - expectYamlLoads( - doc, - ''' + expectYamlLoads(doc, ''' plain key: in-line value : # Both empty "quoted key": @@ -1735,25 +1546,21 @@ main() { test('[Example 8.19]', () { var el = deepEqualsMap(); el[{'earth': 'blue'}] = {'moon': 'white'}; - expectYamlLoads( - [ - {'sun': 'yellow'}, - el - ], - """ + expectYamlLoads([ + {'sun': 'yellow'}, + el + ], """ - sun: yellow - ? earth: blue : moon: white"""); }); test('[Example 8.20]', () { - expectYamlLoads( - [ - "flow in block", - "Block scalar\n", - {"foo": "bar"} - ], - ''' + expectYamlLoads([ + "flow in block", + "Block scalar\n", + {"foo": "bar"} + ], ''' - "flow in block" - > @@ -1765,9 +1572,7 @@ main() { test('[Example 8.21]', () { // The spec doesn't include a newline after "value" in the parsed map, but // the block scalar is clipped so it should be retained. - expectYamlLoads( - {"literal": "value\n", "folded": "value"}, - """ + expectYamlLoads({"literal": "value\n", "folded": "value"}, """ literal: |2 value folded: @@ -1777,15 +1582,13 @@ main() { }); test('[Example 8.22]', () { - expectYamlLoads( - { - "sequence": [ - "entry", - ["nested"] - ], - "mapping": {"foo": "bar"} - }, - """ + expectYamlLoads({ + "sequence": [ + "entry", + ["nested"] + ], + "mapping": {"foo": "bar"} + }, """ sequence: !!seq - entry - !!seq @@ -1801,9 +1604,7 @@ main() { // doesn't plan to support. test('[Example 9.2]', () { - expectYamlLoads( - "Document", - """ + expectYamlLoads("Document", """ %YAML 1.2 --- Document @@ -1819,8 +1620,7 @@ main() { // indented the same amount, the text would be part of the literal, which // implies that the spec's parse of this document is incorrect. expectYamlStreamLoads( - ["Bare document", "%!PS-Adobe-2.0 # Not the first line\n"], - """ + ["Bare document", "%!PS-Adobe-2.0 # Not the first line\n"], """ Bare document ... @@ -1832,12 +1632,10 @@ main() { }); test('[Example 9.4]', () { - expectYamlStreamLoads( - [ - {"matches %": 20}, - null - ], - """ + expectYamlStreamLoads([ + {"matches %": 20}, + null + ], """ --- { matches % : 20 } @@ -1850,9 +1648,7 @@ main() { test('[Example 9.5]', () { // The spec doesn't have a space between the second // "YAML" and "1.2", but this seems to be a typo. - expectYamlStreamLoads( - ["%!PS-Adobe-2.0\n", null], - """ + expectYamlStreamLoads(["%!PS-Adobe-2.0\n", null], """ %YAML 1.2 --- | %!PS-Adobe-2.0 @@ -1864,13 +1660,11 @@ main() { }); test('[Example 9.6]', () { - expectYamlStreamLoads( - [ - "Document", - null, - {"matches %": 20} - ], - """ + expectYamlStreamLoads([ + "Document", + null, + {"matches %": 20} + ], """ Document --- # Empty @@ -1884,20 +1678,14 @@ main() { // Chapter 10: Recommended Schemas group('10.1: Failsafe Schema', () { test('[Example 10.1]', () { - expectYamlLoads( - { - "Block style": { - "Clark": "Evans", - "Ingy": "döt Net", - "Oren": "Ben-Kiki" - }, - "Flow style": { - "Clark": "Evans", - "Ingy": "döt Net", - "Oren": "Ben-Kiki" - } - }, - """ + expectYamlLoads({ + "Block style": { + "Clark": "Evans", + "Ingy": "döt Net", + "Oren": "Ben-Kiki" + }, + "Flow style": {"Clark": "Evans", "Ingy": "döt Net", "Oren": "Ben-Kiki"} + }, """ Block style: !!map Clark : Evans Ingy : döt Net @@ -1907,12 +1695,10 @@ main() { }); test('[Example 10.2]', () { - expectYamlLoads( - { - "Block style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"], - "Flow style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"] - }, - """ + expectYamlLoads({ + "Block style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"], + "Flow style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"] + }, """ Block style: !!seq - Clark Evans - Ingy döt Net @@ -1922,12 +1708,10 @@ main() { }); test('[Example 10.3]', () { - expectYamlLoads( - { - "Block style": "String: just a theory.", - "Flow style": "String: just a theory." - }, - ''' + expectYamlLoads({ + "Block style": "String: just a theory.", + "Flow style": "String: just a theory." + }, ''' Block style: !!str |- String: just a theory. @@ -2004,17 +1788,15 @@ main() { group('10.3: Core Schema', () { test('[Example 10.9]', () { - expectYamlLoads( - { - "A null": null, - "Also a null": null, - "Not a null": "", - "Booleans": [true, true, false, false], - "Integers": [0, 7, 0x3A, -19], - "Floats": [0, 0, 0.5, 12000, -200000], - "Also floats": [infinity, -infinity, infinity, nan] - }, - ''' + expectYamlLoads({ + "A null": null, + "Also a null": null, + "Not a null": "", + "Booleans": [true, true, false, false], + "Integers": [0, 7, 0x3A, -19], + "Floats": [0, 0, 0.5, 12000, -200000], + "Also floats": [infinity, -infinity, infinity, nan] + }, ''' A null: null Also a null: # Empty Not a null: "" From ee1ba96fc34356f4c0337d802f9a5b6dfe747330 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Tue, 22 May 2018 17:44:26 +0200 Subject: [PATCH 083/179] Remove usage of deprecated `onError` argument to `int.parse` and `double.parse`. (dart-lang/yaml#43) --- pkgs/yaml/CHANGELOG.md | 1 + pkgs/yaml/lib/src/loader.dart | 12 ++++++------ pkgs/yaml/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index fd41fdb8b..ce4246948 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,5 +1,6 @@ ## 2.1.14 +* Remove use of deprecated features. * Updated SDK version to 2.0.0-dev.17.0 ## 2.1.13 diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index d00fc2c86..956b17ce7 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -302,12 +302,12 @@ class Loader { // Hexadecimal or octal integers. if (allowInt && firstChar == $0) { - // int.parse supports 0x natively. - if (secondChar == $x) return int.parse(contents, onError: (_) => null); + // int.tryParse supports 0x natively. + if (secondChar == $x) return int.tryParse(contents); if (secondChar == $o) { var afterRadix = contents.substring(2); - return int.parse(afterRadix, radix: 8, onError: (_) => null); + return int.tryParse(afterRadix, radix: 8); } } @@ -321,10 +321,10 @@ class Loader { if (allowInt) { // Pass "radix: 10" explicitly to ensure that "-0x10", which is valid // Dart but invalid YAML, doesn't get parsed. - result = int.parse(contents, radix: 10, onError: (_) => null); + result = int.tryParse(contents, radix: 10); } - if (allowFloat) result ??= double.parse(contents, (_) => null); + if (allowFloat) result ??= double.tryParse(contents); return result; } @@ -348,7 +348,7 @@ class Loader { } } - return double.parse(contents, (_) => null); + return double.tryParse(contents); } if (length == 4 && firstChar == $dot) { diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index b60d7cc1f..8f520c5c9 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -4,7 +4,7 @@ author: "Dart Team " homepage: https://github.com/dart-lang/yaml description: A parser for YAML. environment: - sdk: '>=2.0.0-dev.17.0 <2.0.0' + sdk: '>=2.0.0-dev.49.0 <2.0.0' dependencies: charcode: "^1.1.0" collection: ">=1.1.0 <2.0.0" From 1a58205c3dadec44ab5c46d848d3ccdd451f39ab Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Tue, 17 Jul 2018 16:21:57 -0400 Subject: [PATCH 084/179] chore: set max SDK version to <3.0.0 (dart-lang/yaml#46) --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/analysis_options.yaml | 2 -- pkgs/yaml/pubspec.yaml | 24 +++++++++++-------- pkgs/yaml/test/utils.dart | 2 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 28 +++++++++++----------- 5 files changed, 33 insertions(+), 27 deletions(-) delete mode 100644 pkgs/yaml/analysis_options.yaml diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index ce4246948..143e1c2d0 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.15 + +* Set max SDK version to `<3.0.0`, and adjust other dependencies. + ## 2.1.14 * Remove use of deprecated features. diff --git a/pkgs/yaml/analysis_options.yaml b/pkgs/yaml/analysis_options.yaml deleted file mode 100644 index a10d4c5a0..000000000 --- a/pkgs/yaml/analysis_options.yaml +++ /dev/null @@ -1,2 +0,0 @@ -analyzer: - strong-mode: true diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 8f520c5c9..9f0897c82 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,15 +1,19 @@ name: yaml -version: 2.1.14 -author: "Dart Team " -homepage: https://github.com/dart-lang/yaml +version: 2.1.15 + description: A parser for YAML. +author: Dart Team +homepage: https://github.com/dart-lang/yaml + environment: - sdk: '>=2.0.0-dev.49.0 <2.0.0' + sdk: '>=2.0.0-dev.49.0 <3.0.0' + dependencies: - charcode: "^1.1.0" - collection: ">=1.1.0 <2.0.0" - string_scanner: ">=0.1.4 <2.0.0" - source_span: ">=1.0.0 <2.0.0" + charcode: ^1.1.0 + collection: '>=1.1.0 <2.0.0' + string_scanner: '>=0.1.4 <2.0.0' + source_span: '>=1.0.0 <2.0.0' + dev_dependencies: - path: ">=1.2.0 <2.0.0" - test: ">=0.12.0 <0.13.0" + path: '>=1.2.0 <2.0.0' + test: '>=0.12.0 <0.13.0' diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index f7203870e..39fe203de 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -7,7 +7,7 @@ import 'package:yaml/src/equality.dart' as equality; import 'package:yaml/yaml.dart'; /// A matcher that validates that a closure or Future throws a [YamlException]. -final Matcher throwsYamlException = throwsA(new isInstanceOf()); +final Matcher throwsYamlException = throwsA(new TypeMatcher()); /// Returns a matcher that asserts that the value equals [expected]. /// diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index 5d9a102bd..d9b501050 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -53,19 +53,19 @@ main() { })); expect(map.span, isNullSpan(isNull)); - expect(map["list"], new isInstanceOf()); - expect(map["list"].nodes[0], new isInstanceOf()); + expect(map["list"], new TypeMatcher()); + expect(map["list"].nodes[0], new TypeMatcher()); expect(map["list"].span, isNullSpan(isNull)); - expect(map["map"], new isInstanceOf()); - expect(map["map"].nodes["foo"], new isInstanceOf()); - expect(map["map"]["nested"], new isInstanceOf()); + expect(map["map"], new TypeMatcher()); + expect(map["map"].nodes["foo"], new TypeMatcher()); + expect(map["map"]["nested"], new TypeMatcher()); expect(map["map"].span, isNullSpan(isNull)); - expect(map.nodes["scalar"], new isInstanceOf()); + expect(map.nodes["scalar"], new TypeMatcher()); expect(map.nodes["scalar"].value, "value"); expect(map.nodes["scalar"].span, isNullSpan(isNull)); expect(map["scalar"], "value"); expect(map.keys, unorderedEquals(["list", "map", "scalar"])); - expect(map.nodes.keys, everyElement(new isInstanceOf())); + expect(map.nodes.keys, everyElement(new TypeMatcher())); expect(map.nodes[new YamlScalar.wrap("list")], equals([1, 2, 3])); }); @@ -108,14 +108,14 @@ main() { ])); expect(list.span, isNullSpan(isNull)); - expect(list[0], new isInstanceOf()); - expect(list[0].nodes[0], new isInstanceOf()); + expect(list[0], new TypeMatcher()); + expect(list[0].nodes[0], new TypeMatcher()); expect(list[0].span, isNullSpan(isNull)); - expect(list[1], new isInstanceOf()); - expect(list[1].nodes["foo"], new isInstanceOf()); - expect(list[1]["nested"], new isInstanceOf()); + expect(list[1], new TypeMatcher()); + expect(list[1].nodes["foo"], new TypeMatcher()); + expect(list[1]["nested"], new TypeMatcher()); expect(list[1].span, isNullSpan(isNull)); - expect(list.nodes[2], new isInstanceOf()); + expect(list.nodes[2], new TypeMatcher()); expect(list.nodes[2].value, "value"); expect(list.nodes[2].span, isNullSpan(isNull)); expect(list[2], "value"); @@ -153,7 +153,7 @@ main() { } Matcher isNullSpan(sourceUrl) => predicate((span) { - expect(span, new isInstanceOf()); + expect(span, new TypeMatcher()); expect(span.length, equals(0)); expect(span.text, isEmpty); expect(span.start, equals(span.end)); From 5385e3dbf8fec6382cbff102de1b20034a999d0c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 13 Aug 2018 13:12:05 -0700 Subject: [PATCH 085/179] misc: fix test dependency to work with Dart 2 stable (dart-lang/yaml#47) --- pkgs/yaml/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 9f0897c82..e8782f914 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.15 +version: 2.1.16-dev description: A parser for YAML. author: Dart Team @@ -16,4 +16,4 @@ dependencies: dev_dependencies: path: '>=1.2.0 <2.0.0' - test: '>=0.12.0 <0.13.0' + test: '>=0.12.0 <2.0.0' From 52d96030a0098e45288722b1f1ad8a8892a54d56 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 9 Apr 2019 12:54:15 -0700 Subject: [PATCH 086/179] Enable and fix a number of lints --- pkgs/yaml/analysis_options.yaml | 43 +++++ pkgs/yaml/benchmark/benchmark.dart | 6 +- pkgs/yaml/codereview.settings | 3 - pkgs/yaml/lib/src/equality.dart | 4 +- pkgs/yaml/lib/src/event.dart | 26 +-- pkgs/yaml/lib/src/loader.dart | 70 ++++---- pkgs/yaml/lib/src/null_span.dart | 2 +- pkgs/yaml/lib/src/parser.dart | 176 ++++++++++----------- pkgs/yaml/lib/src/scanner.dart | 132 ++++++++-------- pkgs/yaml/lib/src/style.dart | 18 +-- pkgs/yaml/lib/src/token.dart | 52 +++--- pkgs/yaml/lib/src/utils.dart | 2 +- pkgs/yaml/lib/src/yaml_document.dart | 4 +- pkgs/yaml/lib/src/yaml_node.dart | 18 +-- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 33 ++-- pkgs/yaml/lib/yaml.dart | 16 +- pkgs/yaml/pubspec.yaml | 1 + pkgs/yaml/test/utils.dart | 2 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 52 +++--- pkgs/yaml/test/yaml_test.dart | 14 +- 20 files changed, 347 insertions(+), 327 deletions(-) create mode 100644 pkgs/yaml/analysis_options.yaml delete mode 100644 pkgs/yaml/codereview.settings diff --git a/pkgs/yaml/analysis_options.yaml b/pkgs/yaml/analysis_options.yaml new file mode 100644 index 000000000..7f965d234 --- /dev/null +++ b/pkgs/yaml/analysis_options.yaml @@ -0,0 +1,43 @@ +include: package:pedantic/analysis_options.yaml +analyzer: + strong-mode: + implicit-casts: false +linter: + rules: + - avoid_empty_else + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_unused_constructor_parameters + - await_only_futures + - camel_case_types + - cancel_subscriptions + #- constant_identifier_names + - control_flow_in_finally + - directives_ordering + - empty_catches + - empty_constructor_bodies + - empty_statements + - hash_and_equals + - implementation_imports + - iterable_contains_unrelated_type + - library_names + - library_prefixes + - list_remove_unrelated_type + - non_constant_identifier_names + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_equal_for_default_values + - prefer_final_fields + - prefer_generic_function_type_aliases + - prefer_is_not_empty + - slash_for_doc_comments + - test_types_in_equals + - throw_in_finally + - type_init_formals + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_new + - unrelated_type_equality_checks + - valid_regexps diff --git a/pkgs/yaml/benchmark/benchmark.dart b/pkgs/yaml/benchmark/benchmark.dart index e3521b1ff..5e080ebd0 100644 --- a/pkgs/yaml/benchmark/benchmark.dart +++ b/pkgs/yaml/benchmark/benchmark.dart @@ -23,7 +23,7 @@ void main(List args) { // Run the benchmark several times. This ensures the VM is warmed up and lets // us see how much variance there is. for (var i = 0; i <= numTrials; i++) { - var start = new DateTime.now(); + var start = DateTime.now(); // For a single benchmark, convert the source multiple times. var result; @@ -32,7 +32,7 @@ void main(List args) { } var elapsed = - new DateTime.now().difference(start).inMilliseconds / runsPerTrial; + DateTime.now().difference(start).inMilliseconds / runsPerTrial; // Keep track of the best run so far. if (elapsed >= best) continue; @@ -56,7 +56,7 @@ void main(List args) { String loadFile(String name) { var path = p.join(p.dirname(p.fromUri(Platform.script)), name); - return new File(path).readAsStringSync(); + return File(path).readAsStringSync(); } void printResult(String label, double time) { diff --git a/pkgs/yaml/codereview.settings b/pkgs/yaml/codereview.settings deleted file mode 100644 index 03b6c2745..000000000 --- a/pkgs/yaml/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: https://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/yaml/commit/ -CC_LIST: reviews@dartlang.org \ No newline at end of file diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index 3c947a9c1..66b819643 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -10,13 +10,13 @@ import 'yaml_node.dart'; /// Returns a [Map] that compares its keys based on [deepEquals]. Map deepEqualsMap() => - new HashMap(equals: deepEquals, hashCode: deepHashCode); + HashMap(equals: deepEquals, hashCode: deepHashCode); /// Returns whether two objects are structurally equivalent. /// /// This considers `NaN` values to be equivalent, handles self-referential /// structures, and considers [YamlScalar]s to be equal to their values. -bool deepEquals(obj1, obj2) => new _DeepEquals().equals(obj1, obj2); +bool deepEquals(obj1, obj2) => _DeepEquals().equals(obj1, obj2); /// A class that provides access to the list of parent objects used for loop /// detection. diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart index 296df22d6..3be5a0a15 100644 --- a/pkgs/yaml/lib/src/event.dart +++ b/pkgs/yaml/lib/src/event.dart @@ -38,7 +38,7 @@ class DocumentStartEvent implements Event { DocumentStartEvent(this.span, {this.versionDirective, List tagDirectives, - this.isImplicit: true}) + this.isImplicit = true}) : tagDirectives = tagDirectives == null ? [] : tagDirectives; String toString() => "DOCUMENT_START"; @@ -53,7 +53,7 @@ class DocumentEndEvent implements Event { /// `...` sequence). final bool isImplicit; - DocumentEndEvent(this.span, {this.isImplicit: true}); + DocumentEndEvent(this.span, {this.isImplicit = true}); String toString() => "DOCUMENT_END"; } @@ -81,7 +81,7 @@ abstract class _ValueEvent implements Event { String get tag; String toString() { - var buffer = new StringBuffer('$type'); + var buffer = StringBuffer('$type'); if (anchor != null) buffer.write(" &$anchor"); if (tag != null) buffer.write(" $tag"); return buffer.toString(); @@ -134,20 +134,20 @@ class MappingStartEvent extends _ValueEvent { /// An enum of types of [Event] object. class EventType { - static const STREAM_START = const EventType._("STREAM_START"); - static const STREAM_END = const EventType._("STREAM_END"); + static const STREAM_START = EventType._("STREAM_START"); + static const STREAM_END = EventType._("STREAM_END"); - static const DOCUMENT_START = const EventType._("DOCUMENT_START"); - static const DOCUMENT_END = const EventType._("DOCUMENT_END"); + static const DOCUMENT_START = EventType._("DOCUMENT_START"); + static const DOCUMENT_END = EventType._("DOCUMENT_END"); - static const ALIAS = const EventType._("ALIAS"); - static const SCALAR = const EventType._("SCALAR"); + static const ALIAS = EventType._("ALIAS"); + static const SCALAR = EventType._("SCALAR"); - static const SEQUENCE_START = const EventType._("SEQUENCE_START"); - static const SEQUENCE_END = const EventType._("SEQUENCE_END"); + static const SEQUENCE_START = EventType._("SEQUENCE_START"); + static const SEQUENCE_END = EventType._("SEQUENCE_END"); - static const MAPPING_START = const EventType._("MAPPING_START"); - static const MAPPING_END = const EventType._("MAPPING_END"); + static const MAPPING_START = EventType._("MAPPING_START"); + static const MAPPING_END = EventType._("MAPPING_END"); final String name; diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 956b17ce7..70aec36fd 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -23,7 +23,7 @@ class Loader { final Parser _parser; /// Aliases by the alias name. - final _aliases = new Map(); + final _aliases = Map(); /// The span of the entire stream emitted so far. FileSpan get span => _span; @@ -33,7 +33,7 @@ class Loader { /// /// [sourceUrl] can be a String or a [Uri]. Loader(String source, {sourceUrl}) - : _parser = new Parser(source, sourceUrl: sourceUrl) { + : _parser = Parser(source, sourceUrl: sourceUrl) { var event = _parser.parse(); _span = event.span; assert(event.type == EventType.STREAM_START); @@ -51,8 +51,8 @@ class Loader { return null; } - var document = _loadDocument(event); - _span = _span.expand(document.span); + var document = _loadDocument(event as DocumentStartEvent); + _span = _span.expand(document.span as FileSpan); _aliases.clear(); return document; } @@ -64,7 +64,7 @@ class Loader { var lastEvent = _parser.parse() as DocumentEndEvent; assert(lastEvent.type == EventType.DOCUMENT_END); - return new YamlDocument.internal( + return YamlDocument.internal( contents, firstEvent.span.expand(lastEvent.span), firstEvent.versionDirective, @@ -77,13 +77,13 @@ class Loader { YamlNode _loadNode(Event firstEvent) { switch (firstEvent.type) { case EventType.ALIAS: - return _loadAlias(firstEvent); + return _loadAlias(firstEvent as AliasEvent); case EventType.SCALAR: - return _loadScalar(firstEvent); + return _loadScalar(firstEvent as ScalarEvent); case EventType.SEQUENCE_START: - return _loadSequence(firstEvent); + return _loadSequence(firstEvent as SequenceStartEvent); case EventType.MAPPING_START: - return _loadMapping(firstEvent); + return _loadMapping(firstEvent as MappingStartEvent); default: throw "Unreachable"; } @@ -105,14 +105,14 @@ class Loader { var alias = _aliases[event.name]; if (alias != null) return alias; - throw new YamlException("Undefined alias.", event.span); + throw YamlException("Undefined alias.", event.span); } /// Composes a scalar node. YamlNode _loadScalar(ScalarEvent scalar) { - var node; + YamlNode node; if (scalar.tag == "!") { - node = new YamlScalar.internal(scalar.value, scalar); + node = YamlScalar.internal(scalar.value, scalar); } else if (scalar.tag != null) { node = _parseByTag(scalar); } else { @@ -128,12 +128,11 @@ class Loader { if (firstEvent.tag != "!" && firstEvent.tag != null && firstEvent.tag != "tag:yaml.org,2002:seq") { - throw new YamlException("Invalid tag for sequence.", firstEvent.span); + throw YamlException("Invalid tag for sequence.", firstEvent.span); } var children = []; - var node = - new YamlList.internal(children, firstEvent.span, firstEvent.style); + var node = YamlList.internal(children, firstEvent.span, firstEvent.style); _registerAnchor(firstEvent.anchor, node); var event = _parser.parse(); @@ -151,12 +150,11 @@ class Loader { if (firstEvent.tag != "!" && firstEvent.tag != null && firstEvent.tag != "tag:yaml.org,2002:map") { - throw new YamlException("Invalid tag for mapping.", firstEvent.span); + throw YamlException("Invalid tag for mapping.", firstEvent.span); } var children = deepEqualsMap(); - var node = - new YamlMap.internal(children, firstEvent.span, firstEvent.style); + var node = YamlMap.internal(children, firstEvent.span, firstEvent.style); _registerAnchor(firstEvent.anchor, node); var event = _parser.parse(); @@ -164,7 +162,7 @@ class Loader { var key = _loadNode(event); var value = _loadNode(_parser.parse()); if (children.containsKey(key)) { - throw new YamlException("Duplicate mapping key.", key.span); + throw YamlException("Duplicate mapping key.", key.span); } children[key] = value; @@ -181,29 +179,29 @@ class Loader { case "tag:yaml.org,2002:null": var result = _parseNull(scalar); if (result != null) return result; - throw new YamlException("Invalid null scalar.", scalar.span); + throw YamlException("Invalid null scalar.", scalar.span); case "tag:yaml.org,2002:bool": var result = _parseBool(scalar); if (result != null) return result; - throw new YamlException("Invalid bool scalar.", scalar.span); + throw YamlException("Invalid bool scalar.", scalar.span); case "tag:yaml.org,2002:int": var result = _parseNumber(scalar, allowFloat: false); if (result != null) return result; - throw new YamlException("Invalid int scalar.", scalar.span); + throw YamlException("Invalid int scalar.", scalar.span); case "tag:yaml.org,2002:float": var result = _parseNumber(scalar, allowInt: false); if (result != null) return result; - throw new YamlException("Invalid float scalar.", scalar.span); + throw YamlException("Invalid float scalar.", scalar.span); case "tag:yaml.org,2002:str": - return new YamlScalar.internal(scalar.value, scalar); + return YamlScalar.internal(scalar.value, scalar); default: - throw new YamlException('Undefined tag: ${scalar.tag}.', scalar.span); + throw YamlException('Undefined tag: ${scalar.tag}.', scalar.span); } } /// Parses [scalar], which may be one of several types. YamlScalar _parseScalar(ScalarEvent scalar) => - _tryParseScalar(scalar) ?? new YamlScalar.internal(scalar.value, scalar); + _tryParseScalar(scalar) ?? YamlScalar.internal(scalar.value, scalar); /// Tries to parse [scalar]. /// @@ -212,7 +210,7 @@ class Loader { YamlScalar _tryParseScalar(ScalarEvent scalar) { // Quickly check for the empty string, which means null. var length = scalar.value.length; - if (length == 0) return new YamlScalar.internal(null, scalar); + if (length == 0) return YamlScalar.internal(null, scalar); // Dispatch on the first character. var firstChar = scalar.value.codeUnitAt(0); @@ -231,7 +229,7 @@ class Loader { case $F: return length == 5 ? _parseBool(scalar) : null; case $tilde: - return length == 1 ? new YamlScalar.internal(null, scalar) : null; + return length == 1 ? YamlScalar.internal(null, scalar) : null; default: if (firstChar >= $0 && firstChar <= $9) return _parseNumber(scalar); return null; @@ -248,7 +246,7 @@ class Loader { case "Null": case "NULL": case "~": - return new YamlScalar.internal(null, scalar); + return YamlScalar.internal(null, scalar); default: return null; } @@ -262,11 +260,11 @@ class Loader { case "true": case "True": case "TRUE": - return new YamlScalar.internal(true, scalar); + return YamlScalar.internal(true, scalar); case "false": case "False": case "FALSE": - return new YamlScalar.internal(false, scalar); + return YamlScalar.internal(false, scalar); default: return null; } @@ -275,18 +273,18 @@ class Loader { /// Parses a numeric scalar. /// /// Returns `null` if parsing fails. - YamlNode _parseNumber(ScalarEvent scalar, - {bool allowInt: true, bool allowFloat: true}) { + YamlScalar _parseNumber(ScalarEvent scalar, + {bool allowInt = true, bool allowFloat = true}) { var value = _parseNumberValue(scalar.value, allowInt: allowInt, allowFloat: allowFloat); - return value == null ? null : new YamlScalar.internal(value, scalar); + return value == null ? null : YamlScalar.internal(value, scalar); } /// Parses the value of a number. /// /// Returns the number if it's parsed successfully, or `null` if it's not. num _parseNumberValue(String contents, - {bool allowInt: true, bool allowFloat: true}) { + {bool allowInt = true, bool allowFloat = true}) { assert(allowInt || allowFloat); var firstChar = contents.codeUnitAt(0); @@ -317,7 +315,7 @@ class Loader { secondChar >= $0 && secondChar <= $9)) { // Try to parse an int or, failing that, a double. - var result = null; + num result; if (allowInt) { // Pass "radix: 10" explicitly to ensure that "-0x10", which is valid // Dart but invalid YAML, doesn't get parsed. diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index eab4ec06d..7f0c9d6f0 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -14,5 +14,5 @@ class NullSpan extends SourceSpanMixin { SourceLocation get end => start; final text = ""; - NullSpan(sourceUrl) : start = new SourceLocation(0, sourceUrl: sourceUrl); + NullSpan(sourceUrl) : start = SourceLocation(0, sourceUrl: sourceUrl); } diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 24e9e029a..bffaa174e 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -23,13 +23,13 @@ class Parser { final Scanner _scanner; /// The stack of parse states for nested contexts. - final _states = new List<_State>(); + final _states = List<_State>(); /// The current parse state. var _state = _State.STREAM_START; /// The custom tag directives, by tag handle. - final _tagDirectives = new Map(); + final _tagDirectives = Map(); /// Whether the parser has finished parsing. bool get isDone => _state == _State.END; @@ -38,16 +38,16 @@ class Parser { /// /// [sourceUrl] can be a String or a [Uri]. Parser(String source, {sourceUrl}) - : _scanner = new Scanner(source, sourceUrl: sourceUrl); + : _scanner = Scanner(source, sourceUrl: sourceUrl); /// Consumes and returns the next event. Event parse() { try { - if (isDone) throw new StateError("No more events."); + if (isDone) throw StateError("No more events."); var event = _stateMachine(); return event; } on StringScannerException catch (error) { - throw new YamlException(error.message, error.span); + throw YamlException(error.message, error.span); } } @@ -119,7 +119,7 @@ class Parser { assert(token.type == TokenType.STREAM_START); _state = _State.DOCUMENT_START; - return new Event(EventType.STREAM_START, token.span); + return Event(EventType.STREAM_START, token.span); } /// Parses the productions: @@ -149,13 +149,13 @@ class Parser { _processDirectives(); _states.add(_State.DOCUMENT_END); _state = _State.BLOCK_NODE; - return new DocumentStartEvent(token.span.start.pointSpan()); + return DocumentStartEvent(token.span.start.pointSpan()); } if (token.type == TokenType.STREAM_END) { _state = _State.END; _scanner.scan(); - return new Event(EventType.STREAM_END, token.span); + return Event(EventType.STREAM_END, token.span); } // Parse an explicit document. @@ -165,13 +165,13 @@ class Parser { var tagDirectives = pair.last; token = _scanner.peek(); if (token.type != TokenType.DOCUMENT_START) { - throw new YamlException("Expected document start.", token.span); + throw YamlException("Expected document start.", token.span); } _states.add(_State.DOCUMENT_END); _state = _State.DOCUMENT_CONTENT; _scanner.scan(); - return new DocumentStartEvent(start.expand(token.span), + return DocumentStartEvent(start.expand(token.span), versionDirective: versionDirective, tagDirectives: tagDirectives, isImplicit: false); @@ -212,10 +212,9 @@ class Parser { var token = _scanner.peek(); if (token.type == TokenType.DOCUMENT_END) { _scanner.scan(); - return new DocumentEndEvent(token.span, isImplicit: false); + return DocumentEndEvent(token.span, isImplicit: false); } else { - return new DocumentEndEvent(token.span.start.pointSpan(), - isImplicit: true); + return DocumentEndEvent(token.span.start.pointSpan(), isImplicit: true); } } @@ -246,46 +245,46 @@ class Parser { /// ****** /// flow_content ::= flow_collection | SCALAR /// ****** - Event _parseNode({bool block: false, bool indentlessSequence: false}) { + Event _parseNode({bool block = false, bool indentlessSequence = false}) { var token = _scanner.peek(); if (token is AliasToken) { _scanner.scan(); _state = _states.removeLast(); - return new AliasEvent(token.span, token.name); + return AliasEvent(token.span, token.name); } - var anchor; - var tagToken; + String anchor; + TagToken tagToken; var span = token.span.start.pointSpan(); - parseAnchor(token) { + Token parseAnchor(AnchorToken token) { anchor = token.name; span = span.expand(token.span); return _scanner.advance(); } - parseTag(token) { + Token parseTag(TagToken token) { tagToken = token; span = span.expand(token.span); return _scanner.advance(); } if (token is AnchorToken) { - token = parseAnchor(token); - if (token is TagToken) token = parseTag(token); + token = parseAnchor(token as AnchorToken); + if (token is TagToken) token = parseTag(token as TagToken); } else if (token is TagToken) { - token = parseTag(token); - if (token is AnchorToken) token = parseAnchor(token); + token = parseTag(token as TagToken); + if (token is AnchorToken) token = parseAnchor(token as AnchorToken); } - var tag; + String tag; if (tagToken != null) { if (tagToken.handle == null) { tag = tagToken.suffix; } else { var tagDirective = _tagDirectives[tagToken.handle]; if (tagDirective == null) { - throw new YamlException("Undefined tag handle.", tagToken.span); + throw YamlException("Undefined tag handle.", tagToken.span); } tag = tagDirective.prefix + tagToken.suffix; @@ -294,8 +293,7 @@ class Parser { if (indentlessSequence && token.type == TokenType.BLOCK_ENTRY) { _state = _State.INDENTLESS_SEQUENCE_ENTRY; - return new SequenceStartEvent( - span.expand(token.span), CollectionStyle.BLOCK, + return SequenceStartEvent(span.expand(token.span), CollectionStyle.BLOCK, anchor: anchor, tag: tag); } @@ -305,45 +303,40 @@ class Parser { _state = _states.removeLast(); _scanner.scan(); - return new ScalarEvent(span.expand(token.span), token.value, token.style, + return ScalarEvent(span.expand(token.span), token.value, token.style, anchor: anchor, tag: tag); } if (token.type == TokenType.FLOW_SEQUENCE_START) { _state = _State.FLOW_SEQUENCE_FIRST_ENTRY; - return new SequenceStartEvent( - span.expand(token.span), CollectionStyle.FLOW, + return SequenceStartEvent(span.expand(token.span), CollectionStyle.FLOW, anchor: anchor, tag: tag); } if (token.type == TokenType.FLOW_MAPPING_START) { _state = _State.FLOW_MAPPING_FIRST_KEY; - return new MappingStartEvent( - span.expand(token.span), CollectionStyle.FLOW, + return MappingStartEvent(span.expand(token.span), CollectionStyle.FLOW, anchor: anchor, tag: tag); } if (block && token.type == TokenType.BLOCK_SEQUENCE_START) { _state = _State.BLOCK_SEQUENCE_FIRST_ENTRY; - return new SequenceStartEvent( - span.expand(token.span), CollectionStyle.BLOCK, + return SequenceStartEvent(span.expand(token.span), CollectionStyle.BLOCK, anchor: anchor, tag: tag); } if (block && token.type == TokenType.BLOCK_MAPPING_START) { _state = _State.BLOCK_MAPPING_FIRST_KEY; - return new MappingStartEvent( - span.expand(token.span), CollectionStyle.BLOCK, + return MappingStartEvent(span.expand(token.span), CollectionStyle.BLOCK, anchor: anchor, tag: tag); } if (anchor != null || tag != null) { _state = _states.removeLast(); - return new ScalarEvent(span, '', ScalarStyle.PLAIN, - anchor: anchor, tag: tag); + return ScalarEvent(span, '', ScalarStyle.PLAIN, anchor: anchor, tag: tag); } - throw new YamlException("Expected node content.", span); + throw YamlException("Expected node content.", span); } /// Parses the productions: @@ -370,10 +363,10 @@ class Parser { if (token.type == TokenType.BLOCK_END) { _scanner.scan(); _state = _states.removeLast(); - return new Event(EventType.SEQUENCE_END, token.span); + return Event(EventType.SEQUENCE_END, token.span); } - throw new YamlException("While parsing a block collection, expected '-'.", + throw YamlException("While parsing a block collection, expected '-'.", token.span.start.pointSpan()); } @@ -386,7 +379,7 @@ class Parser { if (token.type != TokenType.BLOCK_ENTRY) { _state = _states.removeLast(); - return new Event(EventType.SEQUENCE_END, token.span.start.pointSpan()); + return Event(EventType.SEQUENCE_END, token.span.start.pointSpan()); } var start = token.span.start; @@ -442,10 +435,10 @@ class Parser { if (token.type == TokenType.BLOCK_END) { _scanner.scan(); _state = _states.removeLast(); - return new Event(EventType.MAPPING_END, token.span); + return Event(EventType.MAPPING_END, token.span); } - throw new YamlException("Expected a key while parsing a block mapping.", + throw YamlException("Expected a key while parsing a block mapping.", token.span.start.pointSpan()); } @@ -493,14 +486,14 @@ class Parser { /// flow_sequence_entry ::= /// flow_node | KEY flow_node? (VALUE flow_node?)? /// * - Event _parseFlowSequenceEntry({bool first: false}) { + Event _parseFlowSequenceEntry({bool first = false}) { if (first) _scanner.scan(); var token = _scanner.peek(); if (token.type != TokenType.FLOW_SEQUENCE_END) { if (!first) { if (token.type != TokenType.FLOW_ENTRY) { - throw new YamlException( + throw YamlException( "While parsing a flow sequence, expected ',' or ']'.", token.span.start.pointSpan()); } @@ -511,7 +504,7 @@ class Parser { if (token.type == TokenType.KEY) { _state = _State.FLOW_SEQUENCE_ENTRY_MAPPING_KEY; _scanner.scan(); - return new MappingStartEvent(token.span, CollectionStyle.FLOW); + return MappingStartEvent(token.span, CollectionStyle.FLOW); } else if (token.type != TokenType.FLOW_SEQUENCE_END) { _states.add(_State.FLOW_SEQUENCE_ENTRY); return _parseNode(); @@ -520,7 +513,7 @@ class Parser { _scanner.scan(); _state = _states.removeLast(); - return new Event(EventType.SEQUENCE_END, token.span); + return Event(EventType.SEQUENCE_END, token.span); } /// Parses the productions: @@ -575,8 +568,7 @@ class Parser { /// * Event _parseFlowSequenceEntryMappingEnd() { _state = _State.FLOW_SEQUENCE_ENTRY; - return new Event( - EventType.MAPPING_END, _scanner.peek().span.start.pointSpan()); + return Event(EventType.MAPPING_END, _scanner.peek().span.start.pointSpan()); } /// Parses the productions: @@ -592,14 +584,14 @@ class Parser { /// flow_mapping_entry ::= /// flow_node | KEY flow_node? (VALUE flow_node?)? /// * *** * - Event _parseFlowMappingKey({bool first: false}) { + Event _parseFlowMappingKey({bool first = false}) { if (first) _scanner.scan(); var token = _scanner.peek(); if (token.type != TokenType.FLOW_MAPPING_END) { if (!first) { if (token.type != TokenType.FLOW_ENTRY) { - throw new YamlException( + throw YamlException( "While parsing a flow mapping, expected ',' or '}'.", token.span.start.pointSpan()); } @@ -626,7 +618,7 @@ class Parser { _scanner.scan(); _state = _states.removeLast(); - return new Event(EventType.MAPPING_END, token.span); + return Event(EventType.MAPPING_END, token.span); } /// Parses the productions: @@ -634,7 +626,7 @@ class Parser { /// flow_mapping_entry ::= /// flow_node | KEY flow_node? (VALUE flow_node?)? /// * ***** * - Event _parseFlowMappingValue({bool empty: false}) { + Event _parseFlowMappingValue({bool empty = false}) { var token = _scanner.peek(); if (empty) { @@ -657,7 +649,7 @@ class Parser { /// Generate an empty scalar event. Event _processEmptyScalar(SourceLocation location) => - new ScalarEvent(location.pointSpan(), '', ScalarStyle.PLAIN); + ScalarEvent(location.pointSpan() as FileSpan, '', ScalarStyle.PLAIN); /// Parses directives. Pair> _processDirectives() { @@ -669,11 +661,11 @@ class Parser { token.type == TokenType.TAG_DIRECTIVE) { if (token is VersionDirectiveToken) { if (versionDirective != null) { - throw new YamlException("Duplicate %YAML directive.", token.span); + throw YamlException("Duplicate %YAML directive.", token.span); } if (token.major != 1 || token.minor == 0) { - throw new YamlException( + throw YamlException( "Incompatible YAML document. This parser only supports YAML 1.1 " "and 1.2.", token.span); @@ -684,9 +676,9 @@ class Parser { token.span); } - versionDirective = new VersionDirective(token.major, token.minor); + versionDirective = VersionDirective(token.major, token.minor); } else if (token is TagDirectiveToken) { - var tagDirective = new TagDirective(token.handle, token.prefix); + var tagDirective = TagDirective(token.handle, token.prefix); _appendTagDirective(tagDirective, token.span); tagDirectives.add(tagDirective); } @@ -694,22 +686,21 @@ class Parser { token = _scanner.advance(); } - _appendTagDirective( - new TagDirective("!", "!"), token.span.start.pointSpan(), + _appendTagDirective(TagDirective("!", "!"), token.span.start.pointSpan(), allowDuplicates: true); - _appendTagDirective(new TagDirective("!!", "tag:yaml.org,2002:"), - token.span.start.pointSpan(), + _appendTagDirective( + TagDirective("!!", "tag:yaml.org,2002:"), token.span.start.pointSpan(), allowDuplicates: true); - return new Pair(versionDirective, tagDirectives); + return Pair(versionDirective, tagDirectives); } /// Adds a tag directive to the directives stack. void _appendTagDirective(TagDirective newDirective, FileSpan span, - {bool allowDuplicates: false}) { + {bool allowDuplicates = false}) { if (_tagDirectives.containsKey(newDirective.handle)) { if (allowDuplicates) return; - throw new YamlException("Duplicate %TAG directive.", span); + throw YamlException("Duplicate %TAG directive.", span); } _tagDirectives[newDirective.handle] = newDirective; @@ -719,86 +710,81 @@ class Parser { /// The possible states for the parser. class _State { /// Expect [TokenType.STREAM_START]. - static const STREAM_START = const _State("STREAM_START"); + static const STREAM_START = _State("STREAM_START"); /// Expect the beginning of an implicit document. - static const IMPLICIT_DOCUMENT_START = - const _State("IMPLICIT_DOCUMENT_START"); + static const IMPLICIT_DOCUMENT_START = _State("IMPLICIT_DOCUMENT_START"); /// Expect [TokenType.DOCUMENT_START]. - static const DOCUMENT_START = const _State("DOCUMENT_START"); + static const DOCUMENT_START = _State("DOCUMENT_START"); /// Expect the content of a document. - static const DOCUMENT_CONTENT = const _State("DOCUMENT_CONTENT"); + static const DOCUMENT_CONTENT = _State("DOCUMENT_CONTENT"); /// Expect [TokenType.DOCUMENT_END]. - static const DOCUMENT_END = const _State("DOCUMENT_END"); + static const DOCUMENT_END = _State("DOCUMENT_END"); /// Expect a block node. - static const BLOCK_NODE = const _State("BLOCK_NODE"); + static const BLOCK_NODE = _State("BLOCK_NODE"); /// Expect a block node or indentless sequence. static const BLOCK_NODE_OR_INDENTLESS_SEQUENCE = - const _State("BLOCK_NODE_OR_INDENTLESS_SEQUENCE"); + _State("BLOCK_NODE_OR_INDENTLESS_SEQUENCE"); /// Expect a flow node. - static const FLOW_NODE = const _State("FLOW_NODE"); + static const FLOW_NODE = _State("FLOW_NODE"); /// Expect the first entry of a block sequence. static const BLOCK_SEQUENCE_FIRST_ENTRY = - const _State("BLOCK_SEQUENCE_FIRST_ENTRY"); + _State("BLOCK_SEQUENCE_FIRST_ENTRY"); /// Expect an entry of a block sequence. - static const BLOCK_SEQUENCE_ENTRY = const _State("BLOCK_SEQUENCE_ENTRY"); + static const BLOCK_SEQUENCE_ENTRY = _State("BLOCK_SEQUENCE_ENTRY"); /// Expect an entry of an indentless sequence. - static const INDENTLESS_SEQUENCE_ENTRY = - const _State("INDENTLESS_SEQUENCE_ENTRY"); + static const INDENTLESS_SEQUENCE_ENTRY = _State("INDENTLESS_SEQUENCE_ENTRY"); /// Expect the first key of a block mapping. - static const BLOCK_MAPPING_FIRST_KEY = - const _State("BLOCK_MAPPING_FIRST_KEY"); + static const BLOCK_MAPPING_FIRST_KEY = _State("BLOCK_MAPPING_FIRST_KEY"); /// Expect a block mapping key. - static const BLOCK_MAPPING_KEY = const _State("BLOCK_MAPPING_KEY"); + static const BLOCK_MAPPING_KEY = _State("BLOCK_MAPPING_KEY"); /// Expect a block mapping value. - static const BLOCK_MAPPING_VALUE = const _State("BLOCK_MAPPING_VALUE"); + static const BLOCK_MAPPING_VALUE = _State("BLOCK_MAPPING_VALUE"); /// Expect the first entry of a flow sequence. - static const FLOW_SEQUENCE_FIRST_ENTRY = - const _State("FLOW_SEQUENCE_FIRST_ENTRY"); + static const FLOW_SEQUENCE_FIRST_ENTRY = _State("FLOW_SEQUENCE_FIRST_ENTRY"); /// Expect an entry of a flow sequence. - static const FLOW_SEQUENCE_ENTRY = const _State("FLOW_SEQUENCE_ENTRY"); + static const FLOW_SEQUENCE_ENTRY = _State("FLOW_SEQUENCE_ENTRY"); /// Expect a key of an ordered mapping. static const FLOW_SEQUENCE_ENTRY_MAPPING_KEY = - const _State("FLOW_SEQUENCE_ENTRY_MAPPING_KEY"); + _State("FLOW_SEQUENCE_ENTRY_MAPPING_KEY"); /// Expect a value of an ordered mapping. static const FLOW_SEQUENCE_ENTRY_MAPPING_VALUE = - const _State("FLOW_SEQUENCE_ENTRY_MAPPING_VALUE"); + _State("FLOW_SEQUENCE_ENTRY_MAPPING_VALUE"); /// Expect the and of an ordered mapping entry. static const FLOW_SEQUENCE_ENTRY_MAPPING_END = - const _State("FLOW_SEQUENCE_ENTRY_MAPPING_END"); + _State("FLOW_SEQUENCE_ENTRY_MAPPING_END"); /// Expect the first key of a flow mapping. - static const FLOW_MAPPING_FIRST_KEY = const _State("FLOW_MAPPING_FIRST_KEY"); + static const FLOW_MAPPING_FIRST_KEY = _State("FLOW_MAPPING_FIRST_KEY"); /// Expect a key of a flow mapping. - static const FLOW_MAPPING_KEY = const _State("FLOW_MAPPING_KEY"); + static const FLOW_MAPPING_KEY = _State("FLOW_MAPPING_KEY"); /// Expect a value of a flow mapping. - static const FLOW_MAPPING_VALUE = const _State("FLOW_MAPPING_VALUE"); + static const FLOW_MAPPING_VALUE = _State("FLOW_MAPPING_VALUE"); /// Expect an empty value of a flow mapping. - static const FLOW_MAPPING_EMPTY_VALUE = - const _State("FLOW_MAPPING_EMPTY_VALUE"); + static const FLOW_MAPPING_EMPTY_VALUE = _State("FLOW_MAPPING_EMPTY_VALUE"); /// Expect nothing. - static const END = const _State("END"); + static const END = _State("END"); final String name; diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 91556af4e..637c8dda1 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -3,8 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'package:collection/collection.dart'; -import 'package:string_scanner/string_scanner.dart'; import 'package:source_span/source_span.dart'; +import 'package:string_scanner/string_scanner.dart'; import 'style.dart'; import 'token.dart'; @@ -108,7 +108,7 @@ class Scanner { /// These are queued up in advance so that [TokenType.KEY] tokens can be /// inserted once the scanner determines that a series of tokens represents a /// mapping key. - final _tokens = new QueueList(); + final _tokens = QueueList(); /// The number of tokens that have been emitted. /// @@ -291,11 +291,11 @@ class Scanner { /// /// [sourceUrl] can be a String or a [Uri]. Scanner(String source, {sourceUrl}) - : _scanner = new SpanScanner.eager(source, sourceUrl: sourceUrl); + : _scanner = SpanScanner.eager(source, sourceUrl: sourceUrl); /// Consumes and returns the next token. Token scan() { - if (_streamEndProduced) throw new StateError("Out of tokens."); + if (_streamEndProduced) throw StateError("Out of tokens."); if (!_tokenAvailable) _fetchMoreTokens(); var token = _tokens.removeFirst(); @@ -488,7 +488,7 @@ class Scanner { if (key.line == _scanner.line) continue; if (key.required) { - throw new YamlException("Expected ':'.", _scanner.emptySpan); + throw YamlException("Expected ':'.", _scanner.emptySpan); } _simpleKeys[i] = null; @@ -511,7 +511,7 @@ class Scanner { // If the current position may start a simple key, save it. _removeSimpleKey(); - _simpleKeys[_simpleKeys.length - 1] = new _SimpleKey( + _simpleKeys[_simpleKeys.length - 1] = _SimpleKey( _tokensParsed + _tokens.length, _scanner.line, _scanner.column, @@ -523,7 +523,7 @@ class Scanner { void _removeSimpleKey() { var key = _simpleKeys.last; if (key != null && key.required) { - throw new YamlException("Could not find expected ':' for simple key.", + throw YamlException("Could not find expected ':' for simple key.", key.location.pointSpan()); } @@ -557,7 +557,7 @@ class Scanner { _indents.add(column); // Create a token and insert it into the queue. - var token = new Token(type, location.pointSpan()); + var token = Token(type, location.pointSpan() as FileSpan); if (tokenNumber == null) { _tokens.add(token); } else { @@ -573,7 +573,7 @@ class Scanner { if (!_inBlockContext) return; while (_indent > column) { - _tokens.add(new Token(TokenType.BLOCK_END, _scanner.emptySpan)); + _tokens.add(Token(TokenType.BLOCK_END, _scanner.emptySpan)); _indents.removeLast(); } } @@ -589,7 +589,7 @@ class Scanner { // Much of libyaml's initialization logic here is done in variable // initializers instead. _streamStartProduced = true; - _tokens.add(new Token(TokenType.STREAM_START, _scanner.emptySpan)); + _tokens.add(Token(TokenType.STREAM_START, _scanner.emptySpan)); } /// Produces a [TokenType.STREAM_END] token. @@ -597,7 +597,7 @@ class Scanner { _resetIndent(); _removeSimpleKey(); _simpleKeyAllowed = false; - _tokens.add(new Token(TokenType.STREAM_END, _scanner.emptySpan)); + _tokens.add(Token(TokenType.STREAM_END, _scanner.emptySpan)); } /// Produces a [TokenType.VERSION_DIRECTIVE] or [TokenType.TAG_DIRECTIVE] @@ -622,7 +622,7 @@ class Scanner { _scanner.readChar(); _scanner.readChar(); - _tokens.add(new Token(type, _scanner.spanFrom(start))); + _tokens.add(Token(type, _scanner.spanFrom(start))); } /// Produces a [TokenType.FLOW_SEQUENCE_START] or @@ -654,7 +654,7 @@ class Scanner { void _fetchBlockEntry() { if (_inBlockContext) { if (!_simpleKeyAllowed) { - throw new YamlException( + throw YamlException( "Block sequence entries are not allowed here.", _scanner.emptySpan); } @@ -675,7 +675,7 @@ class Scanner { void _fetchKey() { if (_inBlockContext) { if (!_simpleKeyAllowed) { - throw new YamlException( + throw YamlException( "Mapping keys are not allowed here.", _scanner.emptySpan); } @@ -695,7 +695,7 @@ class Scanner { // Add a [TokenType.KEY] directive before the first token of the simple // key so the parser knows that it's part of a key/value pair. _tokens.insert(simpleKey.tokenNumber - _tokensParsed, - new Token(TokenType.KEY, simpleKey.location.pointSpan())); + Token(TokenType.KEY, simpleKey.location.pointSpan() as FileSpan)); // In the block context, we may need to add the // [TokenType.BLOCK_MAPPING_START] token. @@ -710,7 +710,7 @@ class Scanner { _simpleKeyAllowed = false; } else if (_inBlockContext) { if (!_simpleKeyAllowed) { - throw new YamlException( + throw YamlException( "Mapping values are not allowed here. Did you miss a colon " "earlier?", _scanner.emptySpan); @@ -737,11 +737,11 @@ class Scanner { void _addCharToken(TokenType type) { var start = _scanner.state; _scanner.readChar(); - _tokens.add(new Token(type, _scanner.spanFrom(start))); + _tokens.add(Token(type, _scanner.spanFrom(start))); } /// Produces a [TokenType.ALIAS] or [TokenType.ANCHOR] token. - void _fetchAnchor({bool anchor: true}) { + void _fetchAnchor({bool anchor = true}) { _saveSimpleKey(); _simpleKeyAllowed = false; _tokens.add(_scanAnchor(anchor: anchor)); @@ -756,7 +756,7 @@ class Scanner { /// Produces a [TokenType.SCALAR] token with style [ScalarStyle.LITERAL] or /// [ScalarStyle.FOLDED]. - void _fetchBlockScalar({bool literal: false}) { + void _fetchBlockScalar({bool literal = false}) { _removeSimpleKey(); _simpleKeyAllowed = true; _tokens.add(_scanBlockScalar(literal: literal)); @@ -764,7 +764,7 @@ class Scanner { /// Produces a [TokenType.SCALAR] token with style [ScalarStyle.SINGLE_QUOTED] /// or [ScalarStyle.DOUBLE_QUOTED]. - void _fetchFlowScalar({bool singleQuote: false}) { + void _fetchFlowScalar({bool singleQuote = false}) { _saveSimpleKey(); _simpleKeyAllowed = false; _tokens.add(_scanFlowScalar(singleQuote: singleQuote)); @@ -828,7 +828,7 @@ class Scanner { // Eat '%'. _scanner.readChar(); - var token; + Token token; var name = _scanDirectiveName(); if (name == "YAML") { token = _scanVersionDirectiveValue(start); @@ -851,7 +851,7 @@ class Scanner { _skipComment(); if (!_isBreakOrEnd) { - throw new YamlException("Expected comment or line break after directive.", + throw YamlException("Expected comment or line break after directive.", _scanner.spanFrom(start)); } @@ -875,9 +875,9 @@ class Scanner { var name = _scanner.substring(start); if (name.isEmpty) { - throw new YamlException("Expected directive name.", _scanner.emptySpan); + throw YamlException("Expected directive name.", _scanner.emptySpan); } else if (!_isBlankOrEnd) { - throw new YamlException( + throw YamlException( "Unexpected character in directive name.", _scanner.emptySpan); } @@ -895,7 +895,7 @@ class Scanner { _scanner.expect('.'); var minor = _scanVersionDirectiveNumber(); - return new VersionDirectiveToken(_scanner.spanFrom(start), major, minor); + return VersionDirectiveToken(_scanner.spanFrom(start), major, minor); } /// Scans the version number of a version directive. @@ -912,7 +912,7 @@ class Scanner { var number = _scanner.substring(start); if (number.isEmpty) { - throw new YamlException("Expected version number.", _scanner.emptySpan); + throw YamlException("Expected version number.", _scanner.emptySpan); } return int.parse(number); @@ -927,21 +927,21 @@ class Scanner { var handle = _scanTagHandle(directive: true); if (!_isBlank) { - throw new YamlException("Expected whitespace.", _scanner.emptySpan); + throw YamlException("Expected whitespace.", _scanner.emptySpan); } _skipBlanks(); var prefix = _scanTagUri(); if (!_isBlankOrEnd) { - throw new YamlException("Expected whitespace.", _scanner.emptySpan); + throw YamlException("Expected whitespace.", _scanner.emptySpan); } - return new TagDirectiveToken(_scanner.spanFrom(start), handle, prefix); + return TagDirectiveToken(_scanner.spanFrom(start), handle, prefix); } /// Scans a [TokenType.ANCHOR] token. - Token _scanAnchor({bool anchor: true}) { + Token _scanAnchor({bool anchor = true}) { var start = _scanner.state; // Eat the indicator character. @@ -966,21 +966,21 @@ class Scanner { next != PERCENT && next != AT && next != GRAVE_ACCENT)) { - throw new YamlException( + throw YamlException( "Expected alphanumeric character.", _scanner.emptySpan); } if (anchor) { - return new AnchorToken(_scanner.spanFrom(start), name); + return AnchorToken(_scanner.spanFrom(start), name); } else { - return new AliasToken(_scanner.spanFrom(start), name); + return AliasToken(_scanner.spanFrom(start), name); } } /// Scans a [TokenType.TAG] token. Token _scanTag() { - var handle; - var suffix; + String handle; + String suffix; var start = _scanner.state; // Check if the tag is in the canonical form. @@ -1018,14 +1018,14 @@ class Scanner { // libyaml insists on whitespace after a tag, but example 7.2 indicates // that it's not required: http://yaml.org/spec/1.2/spec.html#id2786720. - return new TagToken(_scanner.spanFrom(start), handle, suffix); + return TagToken(_scanner.spanFrom(start), handle, suffix); } /// Scans a tag handle. - String _scanTagHandle({bool directive: false}) { + String _scanTagHandle({bool directive = false}) { _scanner.expect('!'); - var buffer = new StringBuffer('!'); + var buffer = StringBuffer('!'); // libyaml only allows word characters in tags, but the spec disagrees: // http://yaml.org/spec/1.2/spec.html#ns-tag-char. @@ -1052,9 +1052,9 @@ class Scanner { /// [head] is the initial portion of the tag that's already been scanned. /// [flowSeparators] indicates whether the tag URI can contain flow /// separators. - String _scanTagUri({String head, bool flowSeparators: true}) { + String _scanTagUri({String head, bool flowSeparators = true}) { var length = head == null ? 0 : head.length; - var buffer = new StringBuffer(); + var buffer = StringBuffer(); // Copy the head if needed. // @@ -1083,7 +1083,7 @@ class Scanner { } /// Scans a block scalar. - Token _scanBlockScalar({bool literal: false}) { + Token _scanBlockScalar({bool literal = false}) { var start = _scanner.state; // Eat the indicator '|' or '>'. @@ -1101,8 +1101,7 @@ class Scanner { if (_isDigit) { // Check that the indentation is greater than 0. if (_scanner.peekChar() == NUMBER_0) { - throw new YamlException( - "0 may not be used as an indentation indicator.", + throw YamlException("0 may not be used as an indentation indicator.", _scanner.spanFrom(start)); } @@ -1111,8 +1110,7 @@ class Scanner { } else if (_isDigit) { // Do the same as above, but in the opposite order. if (_scanner.peekChar() == NUMBER_0) { - throw new YamlException( - "0 may not be used as an indentation indicator.", + throw YamlException("0 may not be used as an indentation indicator.", _scanner.spanFrom(start)); } @@ -1131,7 +1129,7 @@ class Scanner { // Check if we're at the end of the line. if (!_isBreakOrEnd) { - throw new YamlException( + throw YamlException( "Expected comment or line break.", _scanner.emptySpan); } @@ -1152,7 +1150,7 @@ class Scanner { var trailingBreaks = pair.last; // Scan the block scalar contents. - var buffer = new StringBuffer(); + var buffer = StringBuffer(); var leadingBreak = ''; var leadingBlank = false; var trailingBlank = false; @@ -1208,7 +1206,7 @@ class Scanner { if (chomping != _Chomping.STRIP) buffer.write(leadingBreak); if (chomping == _Chomping.KEEP) buffer.write(trailingBreaks); - return new ScalarToken(_scanner.spanFrom(start, end), buffer.toString(), + return ScalarToken(_scanner.spanFrom(start, end), buffer.toString(), literal ? ScalarStyle.LITERAL : ScalarStyle.FOLDED); } @@ -1218,7 +1216,7 @@ class Scanner { /// level and the text of the line breaks. Pair _scanBlockScalarBreaks(int indent) { var maxIndent = 0; - var breaks = new StringBuffer(); + var breaks = StringBuffer(); while (true) { while ((indent == 0 || _scanner.column < indent) && @@ -1244,13 +1242,13 @@ class Scanner { // be supported by the spec. } - return new Pair(indent, breaks.toString()); + return Pair(indent, breaks.toString()); } // Scans a quoted scalar. - Token _scanFlowScalar({bool singleQuote: false}) { + Token _scanFlowScalar({bool singleQuote = false}) { var start = _scanner.state; - var buffer = new StringBuffer(); + var buffer = StringBuffer(); // Eat the left quote. _scanner.readChar(); @@ -1263,7 +1261,7 @@ class Scanner { } if (_scanner.isDone) { - throw new YamlException("Unexpected end of file.", _scanner.emptySpan); + throw YamlException("Unexpected end of file.", _scanner.emptySpan); } var leadingBlanks = false; @@ -1289,7 +1287,7 @@ class Scanner { var escapeStart = _scanner.state; // An escape sequence. - var codeLength = null; + int codeLength; switch (_scanner.peekChar(1)) { case NUMBER_0: buffer.writeCharCode(NULL); @@ -1350,7 +1348,7 @@ class Scanner { codeLength = 8; break; default: - throw new YamlException( + throw YamlException( "Unknown escape character.", _scanner.spanFrom(escapeStart)); } @@ -1362,7 +1360,7 @@ class Scanner { for (var i = 0; i < codeLength; i++) { if (!_isHex) { _scanner.readChar(); - throw new YamlException( + throw YamlException( "Expected $codeLength-digit hexidecimal number.", _scanner.spanFrom(escapeStart)); } @@ -1372,7 +1370,7 @@ class Scanner { // Check the value and write the character. if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) { - throw new YamlException("Invalid Unicode character escape code.", + throw YamlException("Invalid Unicode character escape code.", _scanner.spanFrom(escapeStart)); } @@ -1388,9 +1386,9 @@ class Scanner { break; } - var whitespace = new StringBuffer(); + var whitespace = StringBuffer(); var leadingBreak = ''; - var trailingBreaks = new StringBuffer(); + var trailingBreaks = StringBuffer(); while (_isBlank || _isBreak) { if (_isBlank) { // Consume a space or a tab. @@ -1427,7 +1425,7 @@ class Scanner { // Eat the right quote. _scanner.readChar(); - return new ScalarToken(_scanner.spanFrom(start), buffer.toString(), + return ScalarToken(_scanner.spanFrom(start), buffer.toString(), singleQuote ? ScalarStyle.SINGLE_QUOTED : ScalarStyle.DOUBLE_QUOTED); } @@ -1435,10 +1433,10 @@ class Scanner { Token _scanPlainScalar() { var start = _scanner.state; var end = _scanner.state; - var buffer = new StringBuffer(); + var buffer = StringBuffer(); var leadingBreak = ''; var trailingBreaks = ''; - var whitespace = new StringBuffer(); + var whitespace = StringBuffer(); var indent = _indent + 1; while (true) { @@ -1508,7 +1506,7 @@ class Scanner { // Allow a simple key after a plain scalar with leading blanks. if (leadingBreak.isNotEmpty) _simpleKeyAllowed = true; - return new ScalarToken( + return ScalarToken( _scanner.spanFrom(start, end), buffer.toString(), ScalarStyle.PLAIN); } @@ -1527,7 +1525,7 @@ class Scanner { // libyaml supports NEL, PS, and LS characters as line separators, but this // is explicitly forbidden in section 5.4 of the YAML spec. if (char != CR && char != LF) { - throw new YamlException("Expected newline.", _scanner.emptySpan); + throw YamlException("Expected newline.", _scanner.emptySpan); } _scanner.readChar(); @@ -1670,13 +1668,13 @@ class _SimpleKey { /// See http://yaml.org/spec/1.2/spec.html#id2794534. class _Chomping { /// All trailing whitespace is discarded. - static const STRIP = const _Chomping("STRIP"); + static const STRIP = _Chomping("STRIP"); /// A single trailing newline is retained. - static const CLIP = const _Chomping("CLIP"); + static const CLIP = _Chomping("CLIP"); /// All trailing whitespace is preserved. - static const KEEP = const _Chomping("KEEP"); + static const KEEP = _Chomping("KEEP"); final String name; diff --git a/pkgs/yaml/lib/src/style.dart b/pkgs/yaml/lib/src/style.dart index 30082cfa6..e945da871 100644 --- a/pkgs/yaml/lib/src/style.dart +++ b/pkgs/yaml/lib/src/style.dart @@ -7,32 +7,32 @@ class ScalarStyle { /// No source style was specified. /// /// This usually indicates a scalar constructed with [YamlScalar.wrap]. - static const ANY = const ScalarStyle._("ANY"); + static const ANY = ScalarStyle._("ANY"); /// The plain scalar style, unquoted and without a prefix. /// /// See http://yaml.org/spec/1.2/spec.html#style/flow/plain. - static const PLAIN = const ScalarStyle._("PLAIN"); + static const PLAIN = ScalarStyle._("PLAIN"); /// The literal scalar style, with a `|` prefix. /// /// See http://yaml.org/spec/1.2/spec.html#id2795688. - static const LITERAL = const ScalarStyle._("LITERAL"); + static const LITERAL = ScalarStyle._("LITERAL"); /// The folded scalar style, with a `>` prefix. /// /// See http://yaml.org/spec/1.2/spec.html#id2796251. - static const FOLDED = const ScalarStyle._("FOLDED"); + static const FOLDED = ScalarStyle._("FOLDED"); /// The single-quoted scalar style. /// /// See http://yaml.org/spec/1.2/spec.html#style/flow/single-quoted. - static const SINGLE_QUOTED = const ScalarStyle._("SINGLE_QUOTED"); + static const SINGLE_QUOTED = ScalarStyle._("SINGLE_QUOTED"); /// The double-quoted scalar style. /// /// See http://yaml.org/spec/1.2/spec.html#style/flow/double-quoted. - static const DOUBLE_QUOTED = const ScalarStyle._("DOUBLE_QUOTED"); + static const DOUBLE_QUOTED = ScalarStyle._("DOUBLE_QUOTED"); final String name; @@ -50,17 +50,17 @@ class CollectionStyle { /// /// This usually indicates a collection constructed with [YamlList.wrap] or /// [YamlMap.wrap]. - static const ANY = const CollectionStyle._("ANY"); + static const ANY = CollectionStyle._("ANY"); /// The indentation-based block style. /// /// See http://yaml.org/spec/1.2/spec.html#id2797293. - static const BLOCK = const CollectionStyle._("BLOCK"); + static const BLOCK = CollectionStyle._("BLOCK"); /// The delimiter-based block style. /// /// See http://yaml.org/spec/1.2/spec.html#id2790088. - static const FLOW = const CollectionStyle._("FLOW"); + static const FLOW = CollectionStyle._("FLOW"); final String name; diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 5f91ce9b8..62c7c58aa 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -111,32 +111,32 @@ class ScalarToken implements Token { /// An enum of types of [Token] object. class TokenType { - static const STREAM_START = const TokenType._("STREAM_START"); - static const STREAM_END = const TokenType._("STREAM_END"); - - static const VERSION_DIRECTIVE = const TokenType._("VERSION_DIRECTIVE"); - static const TAG_DIRECTIVE = const TokenType._("TAG_DIRECTIVE"); - static const DOCUMENT_START = const TokenType._("DOCUMENT_START"); - static const DOCUMENT_END = const TokenType._("DOCUMENT_END"); - - static const BLOCK_SEQUENCE_START = const TokenType._("BLOCK_SEQUENCE_START"); - static const BLOCK_MAPPING_START = const TokenType._("BLOCK_MAPPING_START"); - static const BLOCK_END = const TokenType._("BLOCK_END"); - - static const FLOW_SEQUENCE_START = const TokenType._("FLOW_SEQUENCE_START"); - static const FLOW_SEQUENCE_END = const TokenType._("FLOW_SEQUENCE_END"); - static const FLOW_MAPPING_START = const TokenType._("FLOW_MAPPING_START"); - static const FLOW_MAPPING_END = const TokenType._("FLOW_MAPPING_END"); - - static const BLOCK_ENTRY = const TokenType._("BLOCK_ENTRY"); - static const FLOW_ENTRY = const TokenType._("FLOW_ENTRY"); - static const KEY = const TokenType._("KEY"); - static const VALUE = const TokenType._("VALUE"); - - static const ALIAS = const TokenType._("ALIAS"); - static const ANCHOR = const TokenType._("ANCHOR"); - static const TAG = const TokenType._("TAG"); - static const SCALAR = const TokenType._("SCALAR"); + static const STREAM_START = TokenType._("STREAM_START"); + static const STREAM_END = TokenType._("STREAM_END"); + + static const VERSION_DIRECTIVE = TokenType._("VERSION_DIRECTIVE"); + static const TAG_DIRECTIVE = TokenType._("TAG_DIRECTIVE"); + static const DOCUMENT_START = TokenType._("DOCUMENT_START"); + static const DOCUMENT_END = TokenType._("DOCUMENT_END"); + + static const BLOCK_SEQUENCE_START = TokenType._("BLOCK_SEQUENCE_START"); + static const BLOCK_MAPPING_START = TokenType._("BLOCK_MAPPING_START"); + static const BLOCK_END = TokenType._("BLOCK_END"); + + static const FLOW_SEQUENCE_START = TokenType._("FLOW_SEQUENCE_START"); + static const FLOW_SEQUENCE_END = TokenType._("FLOW_SEQUENCE_END"); + static const FLOW_MAPPING_START = TokenType._("FLOW_MAPPING_START"); + static const FLOW_MAPPING_END = TokenType._("FLOW_MAPPING_END"); + + static const BLOCK_ENTRY = TokenType._("BLOCK_ENTRY"); + static const FLOW_ENTRY = TokenType._("FLOW_ENTRY"); + static const KEY = TokenType._("KEY"); + static const VALUE = TokenType._("VALUE"); + + static const ALIAS = TokenType._("ALIAS"); + static const ANCHOR = TokenType._("ANCHOR"); + static const TAG = TokenType._("TAG"); + static const SCALAR = TokenType._("SCALAR"); final String name; diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 36e4e938c..93954aace 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -25,7 +25,7 @@ void warn(String message, [SourceSpan span]) => /// [message] is the text of the warning. If [span] is passed, it's the portion /// of the document that the warning is associated with and should be included /// in the printed warning. -typedef YamlWarningCallback(String message, [SourceSpan span]); +typedef YamlWarningCallback = Function(String message, [SourceSpan span]); /// A callback for emitting a warning. /// diff --git a/pkgs/yaml/lib/src/yaml_document.dart b/pkgs/yaml/lib/src/yaml_document.dart index b3732238a..07806e972 100644 --- a/pkgs/yaml/lib/src/yaml_document.dart +++ b/pkgs/yaml/lib/src/yaml_document.dart @@ -32,8 +32,8 @@ class YamlDocument { /// Users of the library should not use this constructor. YamlDocument.internal(this.contents, this.span, this.versionDirective, List tagDirectives, - {this.startImplicit: false, this.endImplicit: false}) - : tagDirectives = new UnmodifiableListView(tagDirectives); + {this.startImplicit = false, this.endImplicit = false}) + : tagDirectives = UnmodifiableListView(tagDirectives); String toString() => contents.toString(); } diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 7190c8180..3b0a98364 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -64,7 +64,7 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - factory YamlMap({sourceUrl}) => new YamlMapWrapper(const {}, sourceUrl); + factory YamlMap({sourceUrl}) => YamlMapWrapper(const {}, sourceUrl); /// Wraps a Dart map so that it can be accessed (recursively) like a /// [YamlMap]. @@ -76,11 +76,11 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. factory YamlMap.wrap(Map dartMap, {sourceUrl}) => - new YamlMapWrapper(dartMap, sourceUrl); + YamlMapWrapper(dartMap, sourceUrl); /// Users of the library should not use this constructor. YamlMap.internal(Map nodes, SourceSpan span, this.style) - : nodes = new UnmodifiableMapView(nodes) { + : nodes = UnmodifiableMapView(nodes) { _span = span; } @@ -103,7 +103,7 @@ class YamlList extends YamlNode with collection.ListMixin { int get length => nodes.length; set length(int index) { - throw new UnsupportedError("Cannot modify an unmodifiable List"); + throw UnsupportedError("Cannot modify an unmodifiable List"); } /// Creates an empty YamlList. @@ -113,7 +113,7 @@ class YamlList extends YamlNode with collection.ListMixin { /// [sourceUrl] is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - factory YamlList({sourceUrl}) => new YamlListWrapper(const [], sourceUrl); + factory YamlList({sourceUrl}) => YamlListWrapper(const [], sourceUrl); /// Wraps a Dart list so that it can be accessed (recursively) like a /// [YamlList]. @@ -125,18 +125,18 @@ class YamlList extends YamlNode with collection.ListMixin { /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. factory YamlList.wrap(List dartList, {sourceUrl}) => - new YamlListWrapper(dartList, sourceUrl); + YamlListWrapper(dartList, sourceUrl); /// Users of the library should not use this constructor. YamlList.internal(List nodes, SourceSpan span, this.style) - : nodes = new UnmodifiableListView(nodes) { + : nodes = UnmodifiableListView(nodes) { _span = span; } operator [](int index) => nodes[index].value; operator []=(int index, value) { - throw new UnsupportedError("Cannot modify an unmodifiable List"); + throw UnsupportedError("Cannot modify an unmodifiable List"); } } @@ -155,7 +155,7 @@ class YamlScalar extends YamlNode { /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. YamlScalar.wrap(this.value, {sourceUrl}) : style = ScalarStyle.ANY { - _span = new NullSpan(sourceUrl); + _span = NullSpan(sourceUrl); } /// Users of the library should not use this constructor. diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index bcb0faac0..fc987afc3 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -27,18 +27,17 @@ class YamlMapWrapper extends MapBase Iterable get keys => _dartMap.keys; - YamlMapWrapper(Map dartMap, sourceUrl) - : this._(dartMap, new NullSpan(sourceUrl)); + YamlMapWrapper(Map dartMap, sourceUrl) : this._(dartMap, NullSpan(sourceUrl)); YamlMapWrapper._(Map dartMap, SourceSpan span) : _dartMap = dartMap, span = span, - nodes = new _YamlMapNodes(dartMap, span); + nodes = _YamlMapNodes(dartMap, span); operator [](Object key) { var value = _dartMap[key]; - if (value is Map) return new YamlMapWrapper._(value, span); - if (value is List) return new YamlListWrapper._(value, span); + if (value is Map) return YamlMapWrapper._(value, span); + if (value is List) return YamlListWrapper._(value, span); return value; } @@ -57,7 +56,7 @@ class _YamlMapNodes extends MapBase final SourceSpan _span; Iterable get keys => - _dartMap.keys.map((key) => new YamlScalar.internalWithSpan(key, _span)); + _dartMap.keys.map((key) => YamlScalar.internalWithSpan(key, _span)); _YamlMapNodes(this._dartMap, this._span); @@ -90,26 +89,26 @@ class YamlListWrapper extends ListBase implements YamlList { int get length => _dartList.length; set length(int index) { - throw new UnsupportedError("Cannot modify an unmodifiable List."); + throw UnsupportedError("Cannot modify an unmodifiable List."); } YamlListWrapper(List dartList, sourceUrl) - : this._(dartList, new NullSpan(sourceUrl)); + : this._(dartList, NullSpan(sourceUrl)); YamlListWrapper._(List dartList, SourceSpan span) : _dartList = dartList, span = span, - nodes = new _YamlListNodes(dartList, span); + nodes = _YamlListNodes(dartList, span); operator [](int index) { var value = _dartList[index]; - if (value is Map) return new YamlMapWrapper._(value, span); - if (value is List) return new YamlListWrapper._(value, span); + if (value is Map) return YamlMapWrapper._(value, span); + if (value is List) return YamlListWrapper._(value, span); return value; } operator []=(int index, value) { - throw new UnsupportedError("Cannot modify an unmodifiable List."); + throw UnsupportedError("Cannot modify an unmodifiable List."); } int get hashCode => _dartList.hashCode; @@ -129,7 +128,7 @@ class _YamlListNodes extends ListBase { int get length => _dartList.length; set length(int index) { - throw new UnsupportedError("Cannot modify an unmodifiable List."); + throw UnsupportedError("Cannot modify an unmodifiable List."); } _YamlListNodes(this._dartList, this._span); @@ -137,7 +136,7 @@ class _YamlListNodes extends ListBase { YamlNode operator [](int index) => _nodeForValue(_dartList[index], _span); operator []=(int index, value) { - throw new UnsupportedError("Cannot modify an unmodifiable List."); + throw UnsupportedError("Cannot modify an unmodifiable List."); } int get hashCode => _dartList.hashCode; @@ -147,7 +146,7 @@ class _YamlListNodes extends ListBase { } YamlNode _nodeForValue(value, SourceSpan span) { - if (value is Map) return new YamlMapWrapper._(value, span); - if (value is List) return new YamlListWrapper._(value, span); - return new YamlScalar.internalWithSpan(value, span); + if (value is Map) return YamlMapWrapper._(value, span); + if (value is List) return YamlListWrapper._(value, span); + return YamlScalar.internalWithSpan(value, span); } diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 13d6dc271..e2435ad0f 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -47,18 +47,16 @@ YamlNode loadYamlNode(String yaml, {sourceUrl}) => /// normal Dart value this returns a [YamlDocument] instead. This allows the /// caller to access document metadata. YamlDocument loadYamlDocument(String yaml, {sourceUrl}) { - var loader = new Loader(yaml, sourceUrl: sourceUrl); + var loader = Loader(yaml, sourceUrl: sourceUrl); var document = loader.load(); if (document == null) { - return new YamlDocument.internal( - new YamlScalar.internalWithSpan(null, loader.span), - loader.span, - null, const []); + return YamlDocument.internal(YamlScalar.internalWithSpan(null, loader.span), + loader.span, null, const []); } var nextDocument = loader.load(); if (nextDocument != null) { - throw new YamlException("Only expected one document.", nextDocument.span); + throw YamlException("Only expected one document.", nextDocument.span); } return document; @@ -78,7 +76,7 @@ YamlDocument loadYamlDocument(String yaml, {sourceUrl}) { /// If [sourceUrl] is passed, it's used as the URL from which the YAML /// originated for error reporting. It can be a [String], a [Uri], or `null`. YamlList loadYamlStream(String yaml, {sourceUrl}) { - var loader = new Loader(yaml, sourceUrl: sourceUrl); + var loader = Loader(yaml, sourceUrl: sourceUrl); var documents = []; var document = loader.load(); @@ -89,7 +87,7 @@ YamlList loadYamlStream(String yaml, {sourceUrl}) { // TODO(jmesserly): the type on the `document` parameter is a workaround for: // https://github.com/dart-lang/dev_compiler/issues/203 - return new YamlList.internal( + return YamlList.internal( documents.map((YamlDocument document) => document.contents).toList(), loader.span, CollectionStyle.ANY); @@ -100,7 +98,7 @@ YamlList loadYamlStream(String yaml, {sourceUrl}) { /// This is like [loadYamlStream], except that it returns [YamlDocument]s with /// metadata wrapping the document contents. List loadYamlDocuments(String yaml, {sourceUrl}) { - var loader = new Loader(yaml, sourceUrl: sourceUrl); + var loader = Loader(yaml, sourceUrl: sourceUrl); var documents = []; var document = loader.load(); diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index e8782f914..e42ab4218 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -15,5 +15,6 @@ dependencies: source_span: '>=1.0.0 <2.0.0' dev_dependencies: + pedantic: ^1.0.0 path: '>=1.2.0 <2.0.0' test: '>=0.12.0 <2.0.0' diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index 39fe203de..5ecbd142f 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -7,7 +7,7 @@ import 'package:yaml/src/equality.dart' as equality; import 'package:yaml/yaml.dart'; /// A matcher that validates that a closure or Future throws a [YamlException]. -final Matcher throwsYamlException = throwsA(new TypeMatcher()); +final Matcher throwsYamlException = throwsA(TypeMatcher()); /// Returns a matcher that asserts that the value equals [expected]. /// diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index d9b501050..f9b02728e 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -8,31 +8,31 @@ import 'package:yaml/yaml.dart'; main() { test("YamlMap() with no sourceUrl", () { - var map = new YamlMap(); + var map = YamlMap(); expect(map, isEmpty); expect(map.nodes, isEmpty); expect(map.span, isNullSpan(isNull)); }); test("YamlMap() with a sourceUrl", () { - var map = new YamlMap(sourceUrl: "source"); + var map = YamlMap(sourceUrl: "source"); expect(map.span, isNullSpan(Uri.parse("source"))); }); test("YamlList() with no sourceUrl", () { - var list = new YamlList(); + var list = YamlList(); expect(list, isEmpty); expect(list.nodes, isEmpty); expect(list.span, isNullSpan(isNull)); }); test("YamlList() with a sourceUrl", () { - var list = new YamlList(sourceUrl: "source"); + var list = YamlList(sourceUrl: "source"); expect(list.span, isNullSpan(Uri.parse("source"))); }); test("YamlMap.wrap() with no sourceUrl", () { - var map = new YamlMap.wrap({ + var map = YamlMap.wrap({ "list": [1, 2, 3], "map": { "foo": "bar", @@ -53,24 +53,24 @@ main() { })); expect(map.span, isNullSpan(isNull)); - expect(map["list"], new TypeMatcher()); - expect(map["list"].nodes[0], new TypeMatcher()); + expect(map["list"], TypeMatcher()); + expect(map["list"].nodes[0], TypeMatcher()); expect(map["list"].span, isNullSpan(isNull)); - expect(map["map"], new TypeMatcher()); - expect(map["map"].nodes["foo"], new TypeMatcher()); - expect(map["map"]["nested"], new TypeMatcher()); + expect(map["map"], TypeMatcher()); + expect(map["map"].nodes["foo"], TypeMatcher()); + expect(map["map"]["nested"], TypeMatcher()); expect(map["map"].span, isNullSpan(isNull)); - expect(map.nodes["scalar"], new TypeMatcher()); + expect(map.nodes["scalar"], TypeMatcher()); expect(map.nodes["scalar"].value, "value"); expect(map.nodes["scalar"].span, isNullSpan(isNull)); expect(map["scalar"], "value"); expect(map.keys, unorderedEquals(["list", "map", "scalar"])); - expect(map.nodes.keys, everyElement(new TypeMatcher())); - expect(map.nodes[new YamlScalar.wrap("list")], equals([1, 2, 3])); + expect(map.nodes.keys, everyElement(TypeMatcher())); + expect(map.nodes[YamlScalar.wrap("list")], equals([1, 2, 3])); }); test("YamlMap.wrap() with a sourceUrl", () { - var map = new YamlMap.wrap({ + var map = YamlMap.wrap({ "list": [1, 2, 3], "map": { "foo": "bar", @@ -87,7 +87,7 @@ main() { }); test("YamlList.wrap() with no sourceUrl", () { - var list = new YamlList.wrap([ + var list = YamlList.wrap([ [1, 2, 3], { "foo": "bar", @@ -108,21 +108,21 @@ main() { ])); expect(list.span, isNullSpan(isNull)); - expect(list[0], new TypeMatcher()); - expect(list[0].nodes[0], new TypeMatcher()); + expect(list[0], TypeMatcher()); + expect(list[0].nodes[0], TypeMatcher()); expect(list[0].span, isNullSpan(isNull)); - expect(list[1], new TypeMatcher()); - expect(list[1].nodes["foo"], new TypeMatcher()); - expect(list[1]["nested"], new TypeMatcher()); + expect(list[1], TypeMatcher()); + expect(list[1].nodes["foo"], TypeMatcher()); + expect(list[1]["nested"], TypeMatcher()); expect(list[1].span, isNullSpan(isNull)); - expect(list.nodes[2], new TypeMatcher()); + expect(list.nodes[2], TypeMatcher()); expect(list.nodes[2].value, "value"); expect(list.nodes[2].span, isNullSpan(isNull)); expect(list[2], "value"); }); test("YamlList.wrap() with a sourceUrl", () { - var list = new YamlList.wrap([ + var list = YamlList.wrap([ [1, 2, 3], { "foo": "bar", @@ -138,22 +138,22 @@ main() { }); test("re-wrapped objects equal one another", () { - var list = new YamlList.wrap([ + var list = YamlList.wrap([ [1, 2, 3], {"foo": "bar"} ]); expect(list[0] == list[0], isTrue); expect(list[0].nodes == list[0].nodes, isTrue); - expect(list[0] == new YamlList.wrap([1, 2, 3]), isFalse); + expect(list[0] == YamlList.wrap([1, 2, 3]), isFalse); expect(list[1] == list[1], isTrue); expect(list[1].nodes == list[1].nodes, isTrue); - expect(list[1] == new YamlMap.wrap({"foo": "bar"}), isFalse); + expect(list[1] == YamlMap.wrap({"foo": "bar"}), isFalse); }); } Matcher isNullSpan(sourceUrl) => predicate((span) { - expect(span, new TypeMatcher()); + expect(span, TypeMatcher()); expect(span.length, equals(0)); expect(span.text, isEmpty); expect(span.start, equals(span.end)); diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 727ee8e1c..27b202555 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -476,19 +476,19 @@ main() { // Chapter 5: Characters group('5.1: Character Set', () { expectAllowsCharacter(int charCode) { - var char = new String.fromCharCodes([charCode]); + var char = String.fromCharCodes([charCode]); expectYamlLoads('The character "$char" is allowed', 'The character "$char" is allowed'); } expectAllowsQuotedCharacter(int charCode) { - var char = new String.fromCharCodes([charCode]); + var char = String.fromCharCodes([charCode]); expectYamlLoads("The character '$char' is allowed", '"The character \'$char\' is allowed"'); } expectDisallowsCharacter(int charCode) { - var char = new String.fromCharCodes([charCode]); + var char = String.fromCharCodes([charCode]); expectYamlFails('The character "$char" is disallowed'); } @@ -635,10 +635,10 @@ main() { test('[Example 5.13]', () { expectYamlLoads( "Fun with \x5C " - "\x22 \x07 \x08 \x1B \x0C " - "\x0A \x0D \x09 \x0B \x00 " - "\x20 \xA0 \x85 \u2028 \u2029 " - "A A A", + "\x22 \x07 \x08 \x1B \x0C " + "\x0A \x0D \x09 \x0B \x00 " + "\x20 \xA0 \x85 \u2028 \u2029 " + "A A A", ''' "Fun with \\\\ \\" \\a \\b \\e \\f \\ From bcc814d97cb1520fadfb26db27e8f742b324e0f5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 9 Apr 2019 12:56:16 -0700 Subject: [PATCH 087/179] test on oldest supported SDK --- pkgs/yaml/.travis.yml | 4 +++- pkgs/yaml/pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml index 6105af8bc..63ec5c2c2 100644 --- a/pkgs/yaml/.travis.yml +++ b/pkgs/yaml/.travis.yml @@ -1,12 +1,14 @@ language: dart dart: + - 2.0.0 - dev + dart_task: - test: -p vm xvfb: false - test: -p firefox - - dartanalyzer + - dartanalyzer: --fatal-warnings --fatal-infos . matrix: include: diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index e42ab4218..da41f3a45 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -6,7 +6,7 @@ author: Dart Team homepage: https://github.com/dart-lang/yaml environment: - sdk: '>=2.0.0-dev.49.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: charcode: ^1.1.0 From 80fe101bc2d0d19c560c356eb5b6049a870429c3 Mon Sep 17 00:00:00 2001 From: scarger Date: Tue, 9 Apr 2019 17:27:18 -0400 Subject: [PATCH 088/179] Replace deprecated JSON with json from dart:convert (dart-lang/yaml#48) --- pkgs/yaml/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index 6f77bcdc6..93a790914 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -15,7 +15,7 @@ main() { ``` This library currently doesn't support dumping to YAML. You should use -`JSON.encode` from `dart:convert` instead: +`json.encode` from `dart:convert` instead: ```dart import 'dart:convert'; @@ -23,6 +23,6 @@ import 'package:yaml/yaml.dart'; main() { var doc = loadYaml("YAML: YAML Ain't Markup Language"); - print(JSON.encode(doc)); + print(json.encode(doc)); } ``` From 26070a96f9b592c09da0668cbc7326c8b8342135 Mon Sep 17 00:00:00 2001 From: BC Ko Date: Tue, 9 Apr 2019 14:27:52 -0700 Subject: [PATCH 089/179] Update .gitignore to new `dart_tool` pub cache (dart-lang/yaml#44) dart-lang/sdkdart-lang/yaml#32030 --- pkgs/yaml/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/yaml/.gitignore b/pkgs/yaml/.gitignore index 7dbf0350d..ab3cb76e6 100644 --- a/pkgs/yaml/.gitignore +++ b/pkgs/yaml/.gitignore @@ -1,5 +1,6 @@ # Don’t commit the following directories created by pub. .buildlog +.dart_tool/ .pub/ build/ packages @@ -12,4 +13,4 @@ packages *.js.map # Include when developing application packages. -pubspec.lock \ No newline at end of file +pubspec.lock From 90811109a95bb5eec77d850f964fbb39ebbb5d15 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 9 Apr 2019 14:18:00 -0700 Subject: [PATCH 090/179] Add test to validate SourceSpan values for nodes Preparing for https://github.com/dart-lang/yaml/issues/51 --- pkgs/yaml/test/span_test.dart | 89 +++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 pkgs/yaml/test/span_test.dart diff --git a/pkgs/yaml/test/span_test.dart b/pkgs/yaml/test/span_test.dart new file mode 100644 index 000000000..7ef61d306 --- /dev/null +++ b/pkgs/yaml/test/span_test.dart @@ -0,0 +1,89 @@ +// Copyright (c) 2019, 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. + +import 'dart:convert'; + +import 'package:source_span/source_span.dart'; +import 'package:test/test.dart'; +import 'package:yaml/yaml.dart'; + +void _expectSpan(SourceSpan source, String expected) { + final result = source.message('message'); + printOnFailure("r'''\n$result'''"); + + expect(result, expected); +} + +void main() { + YamlMap yaml; + + setUpAll(() { + yaml = loadYaml(const JsonEncoder.withIndent(' ').convert({ + 'num': 42, + 'nested': { + 'null': null, + 'num': 42, + }, + 'null': null, + })) as YamlMap; + }); + + test('first root key', () { + _expectSpan( + yaml.nodes['num'].span, + r''' +line 2, column 9: message + ╷ +2 │ "num": 42, + │ ^^ + ╵''', + ); + }); + + test('first root key', () { + _expectSpan( + yaml.nodes['null'].span, + r''' +line 7, column 10: message + ╷ +7 │ "null": null + │ ^^^^ + ╵''', + ); + }); + + group('nested', () { + YamlMap nestedMap; + + setUpAll(() { + nestedMap = yaml.nodes['nested'] as YamlMap; + }); + + test('first root key', () { + _expectSpan( + nestedMap.nodes['null'].span, + r''' +line 4, column 11: message + ╷ +4 │ "null": null, + │ ^^^^ + ╵''', + ); + }); + + test('first root key', () { + _expectSpan( + nestedMap.nodes['num'].span, + r''' +line 5, column 10: message + ╷ +5 │ "num": 42 + │ ┌──────────^ +6 │ │ }, + │ └─^ + ╵''', + ); + }); + }); +} From cb3cf763349f1f7997a4fc7b2b402062b2a8f915 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 9 Apr 2019 14:26:22 -0700 Subject: [PATCH 091/179] Improve the YamlScalar.span values with trailing whitespace Fixes https://github.com/dart-lang/yaml/issues/51 Also remove dead line from changelog --- pkgs/yaml/CHANGELOG.md | 9 ++++++--- pkgs/yaml/lib/src/parser.dart | 17 ++++++++++++++++- pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/span_test.dart | 21 ++++++--------------- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 143e1c2d0..c0b306308 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.1.16 + +* Improve the `span` associated with `YamlScalar` values with trailing + whitespace. + ## 2.1.15 * Set max SDK version to `<3.0.0`, and adjust other dependencies. @@ -110,12 +115,10 @@ constructors make it possible to use the same API to access non-YAML data as YAML data. -* Make `YamlException` inherit from source_map's [`SpanFormatException`][]. This +* Make `YamlException` inherit from source_map's `SpanFormatException`. This improves the error formatting and allows callers access to source range information. -[SpanFormatException]: (http://www.dartdocs.org/documentation/source_maps/0.9.2/index.html#source_maps/source_maps.SpanFormatException) - ## 1.0.0+1 * Fix a variable name typo. diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index bffaa174e..0971e7f47 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -303,7 +303,22 @@ class Parser { _state = _states.removeLast(); _scanner.scan(); - return ScalarEvent(span.expand(token.span), token.value, token.style, + + span = span.expand(token.span); + if (span.text != token.value) { + // If the only difference between the span and the token is trailing + // whitespace + if (span.text.trimRight() == token.value) { + span = span.file.span( + span.start.offset, + // TODO(kevmoo): The length of `token.value` may be incorrect + // with some UNICODE values. Find a more clean solution. + span.start.offset + token.value.length, + ); + } + } + + return ScalarEvent(span, token.value, token.style, anchor: anchor, tag: tag); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index da41f3a45..d0fb672d8 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.16-dev +version: 2.1.16 description: A parser for YAML. author: Dart Team diff --git a/pkgs/yaml/test/span_test.dart b/pkgs/yaml/test/span_test.dart index 7ef61d306..09e461cab 100644 --- a/pkgs/yaml/test/span_test.dart +++ b/pkgs/yaml/test/span_test.dart @@ -8,13 +8,6 @@ import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; -void _expectSpan(SourceSpan source, String expected) { - final result = source.message('message'); - printOnFailure("r'''\n$result'''"); - - expect(result, expected); -} - void main() { YamlMap yaml; @@ -33,7 +26,6 @@ void main() { _expectSpan( yaml.nodes['num'].span, r''' -line 2, column 9: message ╷ 2 │ "num": 42, │ ^^ @@ -45,7 +37,6 @@ line 2, column 9: message _expectSpan( yaml.nodes['null'].span, r''' -line 7, column 10: message ╷ 7 │ "null": null │ ^^^^ @@ -64,7 +55,6 @@ line 7, column 10: message _expectSpan( nestedMap.nodes['null'].span, r''' -line 4, column 11: message ╷ 4 │ "null": null, │ ^^^^ @@ -76,14 +66,15 @@ line 4, column 11: message _expectSpan( nestedMap.nodes['num'].span, r''' -line 5, column 10: message ╷ -5 │ "num": 42 - │ ┌──────────^ -6 │ │ }, - │ └─^ +5 │ "num": 42 + │ ^^ ╵''', ); }); }); } + +void _expectSpan(SourceSpan source, String expected) { + expect(source.highlight(), expected); +} From aa6f6a39e66a86e8f65acad12686abaa687a4f8f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 9 Apr 2019 16:59:12 -0700 Subject: [PATCH 092/179] Revert "Improve the YamlScalar.span values with trailing whitespace" This reverts commit cb3cf763349f1f7997a4fc7b2b402062b2a8f915. https://github.com/dart-lang/yaml/issues/51 only seems to affect JSON-encoded source files. Not worth this hack. --- pkgs/yaml/CHANGELOG.md | 9 +++------ pkgs/yaml/lib/src/parser.dart | 17 +---------------- pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/span_test.dart | 21 +++++++++++++++------ 4 files changed, 20 insertions(+), 29 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index c0b306308..143e1c2d0 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,8 +1,3 @@ -## 2.1.16 - -* Improve the `span` associated with `YamlScalar` values with trailing - whitespace. - ## 2.1.15 * Set max SDK version to `<3.0.0`, and adjust other dependencies. @@ -115,10 +110,12 @@ constructors make it possible to use the same API to access non-YAML data as YAML data. -* Make `YamlException` inherit from source_map's `SpanFormatException`. This +* Make `YamlException` inherit from source_map's [`SpanFormatException`][]. This improves the error formatting and allows callers access to source range information. +[SpanFormatException]: (http://www.dartdocs.org/documentation/source_maps/0.9.2/index.html#source_maps/source_maps.SpanFormatException) + ## 1.0.0+1 * Fix a variable name typo. diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 0971e7f47..bffaa174e 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -303,22 +303,7 @@ class Parser { _state = _states.removeLast(); _scanner.scan(); - - span = span.expand(token.span); - if (span.text != token.value) { - // If the only difference between the span and the token is trailing - // whitespace - if (span.text.trimRight() == token.value) { - span = span.file.span( - span.start.offset, - // TODO(kevmoo): The length of `token.value` may be incorrect - // with some UNICODE values. Find a more clean solution. - span.start.offset + token.value.length, - ); - } - } - - return ScalarEvent(span, token.value, token.style, + return ScalarEvent(span.expand(token.span), token.value, token.style, anchor: anchor, tag: tag); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index d0fb672d8..da41f3a45 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.16 +version: 2.1.16-dev description: A parser for YAML. author: Dart Team diff --git a/pkgs/yaml/test/span_test.dart b/pkgs/yaml/test/span_test.dart index 09e461cab..7ef61d306 100644 --- a/pkgs/yaml/test/span_test.dart +++ b/pkgs/yaml/test/span_test.dart @@ -8,6 +8,13 @@ import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; +void _expectSpan(SourceSpan source, String expected) { + final result = source.message('message'); + printOnFailure("r'''\n$result'''"); + + expect(result, expected); +} + void main() { YamlMap yaml; @@ -26,6 +33,7 @@ void main() { _expectSpan( yaml.nodes['num'].span, r''' +line 2, column 9: message ╷ 2 │ "num": 42, │ ^^ @@ -37,6 +45,7 @@ void main() { _expectSpan( yaml.nodes['null'].span, r''' +line 7, column 10: message ╷ 7 │ "null": null │ ^^^^ @@ -55,6 +64,7 @@ void main() { _expectSpan( nestedMap.nodes['null'].span, r''' +line 4, column 11: message ╷ 4 │ "null": null, │ ^^^^ @@ -66,15 +76,14 @@ void main() { _expectSpan( nestedMap.nodes['num'].span, r''' +line 5, column 10: message ╷ -5 │ "num": 42 - │ ^^ +5 │ "num": 42 + │ ┌──────────^ +6 │ │ }, + │ └─^ ╵''', ); }); }); } - -void _expectSpan(SourceSpan source, String expected) { - expect(source.highlight(), expected); -} From f33e8cbf077dad3fd548a946778d9a0ea478630e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 17 Jun 2019 12:19:48 -0700 Subject: [PATCH 093/179] Prepare to release 2.1.16 (dart-lang/yaml#54) --- pkgs/yaml/CHANGELOG.md | 9 ++++++--- pkgs/yaml/README.md | 1 + pkgs/yaml/pubspec.yaml | 6 +++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 143e1c2d0..26942865e 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.1.16 + +* Fixed deprecated API usage in README. +* Fixed lints that affect package score. + ## 2.1.15 * Set max SDK version to `<3.0.0`, and adjust other dependencies. @@ -110,12 +115,10 @@ constructors make it possible to use the same API to access non-YAML data as YAML data. -* Make `YamlException` inherit from source_map's [`SpanFormatException`][]. This +* Make `YamlException` inherit from source_map's `SpanFormatException`. This improves the error formatting and allows callers access to source range information. -[SpanFormatException]: (http://www.dartdocs.org/documentation/source_maps/0.9.2/index.html#source_maps/source_maps.SpanFormatException) - ## 1.0.0+1 * Fix a variable name typo. diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index 93a790914..991fc5c02 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -1,5 +1,6 @@ A parser for [YAML](http://www.yaml.org/). +[![Pub Package](https://img.shields.io/pub/v/yaml.svg)](https://pub.dev/packages/yaml) [![Build Status](https://travis-ci.org/dart-lang/yaml.svg?branch=master)](https://travis-ci.org/dart-lang/yaml) Use `loadYaml` to load a single document, or `loadYamlStream` to load a diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index da41f3a45..0548bef3f 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,13 +1,13 @@ name: yaml -version: 2.1.16-dev +version: 2.1.16 -description: A parser for YAML. +description: A parser for YAML, a human-friendly data serialization standard author: Dart Team homepage: https://github.com/dart-lang/yaml environment: sdk: '>=2.0.0 <3.0.0' - + dependencies: charcode: ^1.1.0 collection: '>=1.1.0 <2.0.0' From a9fb9009f08e67b3cce9cb6185f815acdc090e08 Mon Sep 17 00:00:00 2001 From: Yegor Date: Wed, 18 Sep 2019 16:38:20 -0700 Subject: [PATCH 094/179] Preserve parsed key order in maps (dart-lang/yaml#57) Preserve key order in YamlMap when parsing YAML. --- pkgs/yaml/CHANGELOG.md | 6 ++++++ pkgs/yaml/lib/src/equality.dart | 2 +- pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/yaml_test.dart | 29 +++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 26942865e..bc0cb78db 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2.2.0 + +* POSSIBLY BREAKING CHANGE: Make `YamlMap` preserve parsed key order. + This is breaking because some programs may rely on the + `HashMap` sort order. + ## 2.1.16 * Fixed deprecated API usage in README. diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index 66b819643..299dfe802 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -10,7 +10,7 @@ import 'yaml_node.dart'; /// Returns a [Map] that compares its keys based on [deepEquals]. Map deepEqualsMap() => - HashMap(equals: deepEquals, hashCode: deepHashCode); + LinkedHashMap(equals: deepEquals, hashCode: deepHashCode); /// Returns whether two objects are structurally equivalent. /// diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 0548bef3f..6d056da48 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.1.16 +version: 2.2.0 description: A parser for YAML, a human-friendly data serialization standard author: Dart Team diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 27b202555..dcc506a34 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -1806,4 +1806,33 @@ main() { Also floats: [ .inf, -.Inf, +.INF, .NAN ]'''); }); }); + + test('preserves key order', () { + const keys = ['a', 'b', 'c', 'd', 'e', 'f']; + int sanityCheckCount = 0; + for (List permutation in _generatePermutations(keys)) { + final yaml = permutation.map((key) => '$key: value').join('\n'); + expect(loadYaml(yaml).keys.toList(), permutation); + sanityCheckCount++; + } + final expectedPermutationCount = + List.generate(keys.length, (i) => i + 1).reduce((n, i) => n * i); + expect(sanityCheckCount, expectedPermutationCount); + }); +} + +Iterable> _generatePermutations(List keys) sync* { + if (keys.length <= 1) { + yield keys; + return; + } + for (int i = 0; i < keys.length; i++) { + final first = keys[i]; + final rest = [] + ..addAll(keys.sublist(0, i)) + ..addAll(keys.sublist(i + 1)); + for (List subPermutation in _generatePermutations(rest)) { + yield [first]..addAll(subPermutation); + } + } } From 2cbb0fbc69963b3f11998003f06edce570d0c7d5 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 6 Dec 2019 16:19:09 -0800 Subject: [PATCH 095/179] Fix newly enforced package:pedantic lints (dart-lang/yaml#58) - always_declare_return_types - annotate_overrides - omit_local_variable_types - prefer_collection_literals - prefer_if_null_operators - prefer_single_quotes - prefer_spread_collections Bump min SDK to 2.3.0 to allow spreads in collection literals. --- pkgs/yaml/.travis.yml | 2 +- pkgs/yaml/benchmark/benchmark.dart | 12 +- pkgs/yaml/lib/src/equality.dart | 2 +- pkgs/yaml/lib/src/event.dart | 71 +- pkgs/yaml/lib/src/loader.dart | 86 +-- pkgs/yaml/lib/src/null_span.dart | 5 +- pkgs/yaml/lib/src/parser.dart | 81 +- pkgs/yaml/lib/src/scanner.dart | 65 +- pkgs/yaml/lib/src/style.dart | 20 +- pkgs/yaml/lib/src/token.dart | 86 ++- pkgs/yaml/lib/src/utils.dart | 1 + pkgs/yaml/lib/src/yaml_document.dart | 7 +- pkgs/yaml/lib/src/yaml_node.dart | 25 +- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 52 +- pkgs/yaml/lib/yaml.dart | 4 +- pkgs/yaml/pubspec.yaml | 4 +- pkgs/yaml/test/utils.dart | 6 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 124 +-- pkgs/yaml/test/yaml_test.dart | 842 ++++++++++----------- 19 files changed, 792 insertions(+), 703 deletions(-) diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml index 63ec5c2c2..78ba59000 100644 --- a/pkgs/yaml/.travis.yml +++ b/pkgs/yaml/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: - - 2.0.0 + - 2.3.0 - dev dart_task: diff --git a/pkgs/yaml/benchmark/benchmark.dart b/pkgs/yaml/benchmark/benchmark.dart index 5e080ebd0..f5dc9e763 100644 --- a/pkgs/yaml/benchmark/benchmark.dart +++ b/pkgs/yaml/benchmark/benchmark.dart @@ -14,8 +14,8 @@ import 'package:yaml/yaml.dart'; const numTrials = 100; const runsPerTrial = 1000; -final source = loadFile("input.yaml"); -final expected = loadFile("output.json"); +final source = loadFile('input.yaml'); +final expected = loadFile('output.json'); void main(List args) { var best = double.infinity; @@ -41,7 +41,7 @@ void main(List args) { // Sanity check to make sure the output is what we expect and to make sure // the VM doesn't optimize "dead" code away. if (jsonEncode(result) != expected) { - print("Incorrect output:\n${jsonEncode(result)}"); + print('Incorrect output:\n${jsonEncode(result)}'); exit(1); } @@ -51,7 +51,7 @@ void main(List args) { printResult("Run ${padLeft('#$i', 3)}", elapsed); } - printResult("Best ", best); + printResult('Best ', best); } String loadFile(String name) { @@ -60,14 +60,14 @@ String loadFile(String name) { } void printResult(String label, double time) { - print("$label: ${padLeft(time.toStringAsFixed(3), 4)}ms " + print('$label: ${padLeft(time.toStringAsFixed(3), 4)}ms ' "${'=' * ((time * 100).toInt())}"); } String padLeft(input, int length) { var result = input.toString(); if (result.length < length) { - result = " " * (length - result.length) + result; + result = ' ' * (length - result.length) + result; } return result; diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index 299dfe802..b232eb9f6 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -100,7 +100,7 @@ class _DeepEquals { int deepHashCode(obj) { var parents = []; - _deepHashCode(value) { + int _deepHashCode(value) { if (parents.any((parent) => identical(parent, value))) return -1; parents.add(value); diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart index 3be5a0a15..733e39d6f 100644 --- a/pkgs/yaml/lib/src/event.dart +++ b/pkgs/yaml/lib/src/event.dart @@ -17,12 +17,15 @@ class Event { Event(this.type, this.span); + @override String toString() => type.toString(); } /// An event indicating the beginning of a YAML document. class DocumentStartEvent implements Event { - get type => EventType.DOCUMENT_START; + @override + EventType get type => EventType.DOCUMENT_START; + @override final FileSpan span; /// The document's `%YAML` directive, or `null` if there was none. @@ -39,14 +42,17 @@ class DocumentStartEvent implements Event { {this.versionDirective, List tagDirectives, this.isImplicit = true}) - : tagDirectives = tagDirectives == null ? [] : tagDirectives; + : tagDirectives = tagDirectives ?? []; - String toString() => "DOCUMENT_START"; + @override + String toString() => 'DOCUMENT_START'; } /// An event indicating the end of a YAML document. class DocumentEndEvent implements Event { - get type => EventType.DOCUMENT_END; + @override + EventType get type => EventType.DOCUMENT_END; + @override final FileSpan span; /// Whether the document ended implicitly (that is, without an explicit @@ -55,12 +61,15 @@ class DocumentEndEvent implements Event { DocumentEndEvent(this.span, {this.isImplicit = true}); - String toString() => "DOCUMENT_END"; + @override + String toString() => 'DOCUMENT_END'; } /// An event indicating that an alias was referenced. class AliasEvent implements Event { - get type => EventType.ALIAS; + @override + EventType get type => EventType.ALIAS; + @override final FileSpan span; /// The name of the anchor. @@ -68,7 +77,8 @@ class AliasEvent implements Event { AliasEvent(this.span, this.name); - String toString() => "ALIAS $name"; + @override + String toString() => 'ALIAS $name'; } /// A base class for events that can have anchor and tag properties associated @@ -80,19 +90,24 @@ abstract class _ValueEvent implements Event { /// The text of the value's tag, or `null` if it wasn't tagged. String get tag; + @override String toString() { var buffer = StringBuffer('$type'); - if (anchor != null) buffer.write(" &$anchor"); - if (tag != null) buffer.write(" $tag"); + if (anchor != null) buffer.write(' &$anchor'); + if (tag != null) buffer.write(' $tag'); return buffer.toString(); } } /// An event indicating a single scalar value. class ScalarEvent extends _ValueEvent { - get type => EventType.SCALAR; + @override + EventType get type => EventType.SCALAR; + @override final FileSpan span; + @override final String anchor; + @override final String tag; /// The contents of the scalar. @@ -103,14 +118,19 @@ class ScalarEvent extends _ValueEvent { ScalarEvent(this.span, this.value, this.style, {this.anchor, this.tag}); - String toString() => "${super.toString()} \"$value\""; + @override + String toString() => '${super.toString()} "$value"'; } /// An event indicating the beginning of a sequence. class SequenceStartEvent extends _ValueEvent { - get type => EventType.SEQUENCE_START; + @override + EventType get type => EventType.SEQUENCE_START; + @override final FileSpan span; + @override final String anchor; + @override final String tag; /// The style of the collection in the original source. @@ -121,9 +141,13 @@ class SequenceStartEvent extends _ValueEvent { /// An event indicating the beginning of a mapping. class MappingStartEvent extends _ValueEvent { - get type => EventType.MAPPING_START; + @override + EventType get type => EventType.MAPPING_START; + @override final FileSpan span; + @override final String anchor; + @override final String tag; /// The style of the collection in the original source. @@ -134,24 +158,25 @@ class MappingStartEvent extends _ValueEvent { /// An enum of types of [Event] object. class EventType { - static const STREAM_START = EventType._("STREAM_START"); - static const STREAM_END = EventType._("STREAM_END"); + static const STREAM_START = EventType._('STREAM_START'); + static const STREAM_END = EventType._('STREAM_END'); - static const DOCUMENT_START = EventType._("DOCUMENT_START"); - static const DOCUMENT_END = EventType._("DOCUMENT_END"); + static const DOCUMENT_START = EventType._('DOCUMENT_START'); + static const DOCUMENT_END = EventType._('DOCUMENT_END'); - static const ALIAS = EventType._("ALIAS"); - static const SCALAR = EventType._("SCALAR"); + static const ALIAS = EventType._('ALIAS'); + static const SCALAR = EventType._('SCALAR'); - static const SEQUENCE_START = EventType._("SEQUENCE_START"); - static const SEQUENCE_END = EventType._("SEQUENCE_END"); + static const SEQUENCE_START = EventType._('SEQUENCE_START'); + static const SEQUENCE_END = EventType._('SEQUENCE_END'); - static const MAPPING_START = EventType._("MAPPING_START"); - static const MAPPING_END = EventType._("MAPPING_END"); + static const MAPPING_START = EventType._('MAPPING_START'); + static const MAPPING_END = EventType._('MAPPING_END'); final String name; const EventType._(this.name); + @override String toString() => name; } diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 70aec36fd..08b254435 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -23,7 +23,7 @@ class Loader { final Parser _parser; /// Aliases by the alias name. - final _aliases = Map(); + final _aliases = {}; /// The span of the entire stream emitted so far. FileSpan get span => _span; @@ -85,7 +85,7 @@ class Loader { case EventType.MAPPING_START: return _loadMapping(firstEvent as MappingStartEvent); default: - throw "Unreachable"; + throw 'Unreachable'; } } @@ -105,13 +105,13 @@ class Loader { var alias = _aliases[event.name]; if (alias != null) return alias; - throw YamlException("Undefined alias.", event.span); + throw YamlException('Undefined alias.', event.span); } /// Composes a scalar node. YamlNode _loadScalar(ScalarEvent scalar) { YamlNode node; - if (scalar.tag == "!") { + if (scalar.tag == '!') { node = YamlScalar.internal(scalar.value, scalar); } else if (scalar.tag != null) { node = _parseByTag(scalar); @@ -125,10 +125,10 @@ class Loader { /// Composes a sequence node. YamlNode _loadSequence(SequenceStartEvent firstEvent) { - if (firstEvent.tag != "!" && + if (firstEvent.tag != '!' && firstEvent.tag != null && - firstEvent.tag != "tag:yaml.org,2002:seq") { - throw YamlException("Invalid tag for sequence.", firstEvent.span); + firstEvent.tag != 'tag:yaml.org,2002:seq') { + throw YamlException('Invalid tag for sequence.', firstEvent.span); } var children = []; @@ -147,10 +147,10 @@ class Loader { /// Composes a mapping node. YamlNode _loadMapping(MappingStartEvent firstEvent) { - if (firstEvent.tag != "!" && + if (firstEvent.tag != '!' && firstEvent.tag != null && - firstEvent.tag != "tag:yaml.org,2002:map") { - throw YamlException("Invalid tag for mapping.", firstEvent.span); + firstEvent.tag != 'tag:yaml.org,2002:map') { + throw YamlException('Invalid tag for mapping.', firstEvent.span); } var children = deepEqualsMap(); @@ -162,7 +162,7 @@ class Loader { var key = _loadNode(event); var value = _loadNode(_parser.parse()); if (children.containsKey(key)) { - throw YamlException("Duplicate mapping key.", key.span); + throw YamlException('Duplicate mapping key.', key.span); } children[key] = value; @@ -176,23 +176,23 @@ class Loader { /// Parses a scalar according to its tag name. YamlScalar _parseByTag(ScalarEvent scalar) { switch (scalar.tag) { - case "tag:yaml.org,2002:null": + case 'tag:yaml.org,2002:null': var result = _parseNull(scalar); if (result != null) return result; - throw YamlException("Invalid null scalar.", scalar.span); - case "tag:yaml.org,2002:bool": + throw YamlException('Invalid null scalar.', scalar.span); + case 'tag:yaml.org,2002:bool': var result = _parseBool(scalar); if (result != null) return result; - throw YamlException("Invalid bool scalar.", scalar.span); - case "tag:yaml.org,2002:int": + throw YamlException('Invalid bool scalar.', scalar.span); + case 'tag:yaml.org,2002:int': var result = _parseNumber(scalar, allowFloat: false); if (result != null) return result; - throw YamlException("Invalid int scalar.", scalar.span); - case "tag:yaml.org,2002:float": + throw YamlException('Invalid int scalar.', scalar.span); + case 'tag:yaml.org,2002:float': var result = _parseNumber(scalar, allowInt: false); if (result != null) return result; - throw YamlException("Invalid float scalar.", scalar.span); - case "tag:yaml.org,2002:str": + throw YamlException('Invalid float scalar.', scalar.span); + case 'tag:yaml.org,2002:str': return YamlScalar.internal(scalar.value, scalar); default: throw YamlException('Undefined tag: ${scalar.tag}.', scalar.span); @@ -241,11 +241,11 @@ class Loader { /// Returns a Dart `null` if parsing fails. YamlScalar _parseNull(ScalarEvent scalar) { switch (scalar.value) { - case "": - case "null": - case "Null": - case "NULL": - case "~": + case '': + case 'null': + case 'Null': + case 'NULL': + case '~': return YamlScalar.internal(null, scalar); default: return null; @@ -257,13 +257,13 @@ class Loader { /// Returns `null` if parsing fails. YamlScalar _parseBool(ScalarEvent scalar) { switch (scalar.value) { - case "true": - case "True": - case "TRUE": + case 'true': + case 'True': + case 'TRUE': return YamlScalar.internal(true, scalar); - case "false": - case "False": - case "FALSE": + case 'false': + case 'False': + case 'FALSE': return YamlScalar.internal(false, scalar); default: return null; @@ -335,13 +335,13 @@ class Loader { // Starting with a . and a number or a sign followed by a dot. if (length == 5) { switch (contents) { - case "+.inf": - case "+.Inf": - case "+.INF": + case '+.inf': + case '+.Inf': + case '+.INF': return double.infinity; - case "-.inf": - case "-.Inf": - case "-.INF": + case '-.inf': + case '-.Inf': + case '-.INF': return -double.infinity; } } @@ -351,13 +351,13 @@ class Loader { if (length == 4 && firstChar == $dot) { switch (contents) { - case ".inf": - case ".Inf": - case ".INF": + case '.inf': + case '.Inf': + case '.INF': return double.infinity; - case ".nan": - case ".NaN": - case ".NAN": + case '.nan': + case '.NaN': + case '.NAN': return double.nan; } } diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index 7f0c9d6f0..64b3551ed 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -10,9 +10,12 @@ import 'package:source_span/source_span.dart'; /// accessing a non-YAML map that behaves transparently like a map parsed from /// YAML. class NullSpan extends SourceSpanMixin { + @override final SourceLocation start; + @override SourceLocation get end => start; - final text = ""; + @override + final text = ''; NullSpan(sourceUrl) : start = SourceLocation(0, sourceUrl: sourceUrl); } diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index bffaa174e..4beb1de00 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -23,13 +23,13 @@ class Parser { final Scanner _scanner; /// The stack of parse states for nested contexts. - final _states = List<_State>(); + final _states = <_State>[]; /// The current parse state. var _state = _State.STREAM_START; /// The custom tag directives, by tag handle. - final _tagDirectives = Map(); + final _tagDirectives = {}; /// Whether the parser has finished parsing. bool get isDone => _state == _State.END; @@ -43,7 +43,7 @@ class Parser { /// Consumes and returns the next event. Event parse() { try { - if (isDone) throw StateError("No more events."); + if (isDone) throw StateError('No more events.'); var event = _stateMachine(); return event; } on StringScannerException catch (error) { @@ -105,7 +105,7 @@ class Parser { case _State.FLOW_MAPPING_EMPTY_VALUE: return _parseFlowMappingValue(empty: true); default: - throw "Unreachable"; + throw 'Unreachable'; } } @@ -165,7 +165,7 @@ class Parser { var tagDirectives = pair.last; token = _scanner.peek(); if (token.type != TokenType.DOCUMENT_START) { - throw YamlException("Expected document start.", token.span); + throw YamlException('Expected document start.', token.span); } _states.add(_State.DOCUMENT_END); @@ -284,7 +284,7 @@ class Parser { } else { var tagDirective = _tagDirectives[tagToken.handle]; if (tagDirective == null) { - throw YamlException("Undefined tag handle.", tagToken.span); + throw YamlException('Undefined tag handle.', tagToken.span); } tag = tagDirective.prefix + tagToken.suffix; @@ -299,7 +299,7 @@ class Parser { if (token is ScalarToken) { // All non-plain scalars have the "!" tag by default. - if (tag == null && token.style != ScalarStyle.PLAIN) tag = "!"; + if (tag == null && token.style != ScalarStyle.PLAIN) tag = '!'; _state = _states.removeLast(); _scanner.scan(); @@ -336,7 +336,7 @@ class Parser { return ScalarEvent(span, '', ScalarStyle.PLAIN, anchor: anchor, tag: tag); } - throw YamlException("Expected node content.", span); + throw YamlException('Expected node content.', span); } /// Parses the productions: @@ -438,7 +438,7 @@ class Parser { return Event(EventType.MAPPING_END, token.span); } - throw YamlException("Expected a key while parsing a block mapping.", + throw YamlException('Expected a key while parsing a block mapping.', token.span.start.pointSpan()); } @@ -661,18 +661,18 @@ class Parser { token.type == TokenType.TAG_DIRECTIVE) { if (token is VersionDirectiveToken) { if (versionDirective != null) { - throw YamlException("Duplicate %YAML directive.", token.span); + throw YamlException('Duplicate %YAML directive.', token.span); } if (token.major != 1 || token.minor == 0) { throw YamlException( - "Incompatible YAML document. This parser only supports YAML 1.1 " - "and 1.2.", + 'Incompatible YAML document. This parser only supports YAML 1.1 ' + 'and 1.2.', token.span); } else if (token.minor > 2) { // TODO(nweiz): Print to stderr when issue 6943 is fixed and dart:io // is available. - warn("Warning: this parser only supports YAML 1.1 and 1.2.", + warn('Warning: this parser only supports YAML 1.1 and 1.2.', token.span); } @@ -686,10 +686,10 @@ class Parser { token = _scanner.advance(); } - _appendTagDirective(TagDirective("!", "!"), token.span.start.pointSpan(), + _appendTagDirective(TagDirective('!', '!'), token.span.start.pointSpan(), allowDuplicates: true); _appendTagDirective( - TagDirective("!!", "tag:yaml.org,2002:"), token.span.start.pointSpan(), + TagDirective('!!', 'tag:yaml.org,2002:'), token.span.start.pointSpan(), allowDuplicates: true); return Pair(versionDirective, tagDirectives); @@ -700,7 +700,7 @@ class Parser { {bool allowDuplicates = false}) { if (_tagDirectives.containsKey(newDirective.handle)) { if (allowDuplicates) return; - throw YamlException("Duplicate %TAG directive.", span); + throw YamlException('Duplicate %TAG directive.', span); } _tagDirectives[newDirective.handle] = newDirective; @@ -710,85 +710,86 @@ class Parser { /// The possible states for the parser. class _State { /// Expect [TokenType.STREAM_START]. - static const STREAM_START = _State("STREAM_START"); + static const STREAM_START = _State('STREAM_START'); /// Expect the beginning of an implicit document. - static const IMPLICIT_DOCUMENT_START = _State("IMPLICIT_DOCUMENT_START"); + static const IMPLICIT_DOCUMENT_START = _State('IMPLICIT_DOCUMENT_START'); /// Expect [TokenType.DOCUMENT_START]. - static const DOCUMENT_START = _State("DOCUMENT_START"); + static const DOCUMENT_START = _State('DOCUMENT_START'); /// Expect the content of a document. - static const DOCUMENT_CONTENT = _State("DOCUMENT_CONTENT"); + static const DOCUMENT_CONTENT = _State('DOCUMENT_CONTENT'); /// Expect [TokenType.DOCUMENT_END]. - static const DOCUMENT_END = _State("DOCUMENT_END"); + static const DOCUMENT_END = _State('DOCUMENT_END'); /// Expect a block node. - static const BLOCK_NODE = _State("BLOCK_NODE"); + static const BLOCK_NODE = _State('BLOCK_NODE'); /// Expect a block node or indentless sequence. static const BLOCK_NODE_OR_INDENTLESS_SEQUENCE = - _State("BLOCK_NODE_OR_INDENTLESS_SEQUENCE"); + _State('BLOCK_NODE_OR_INDENTLESS_SEQUENCE'); /// Expect a flow node. - static const FLOW_NODE = _State("FLOW_NODE"); + static const FLOW_NODE = _State('FLOW_NODE'); /// Expect the first entry of a block sequence. static const BLOCK_SEQUENCE_FIRST_ENTRY = - _State("BLOCK_SEQUENCE_FIRST_ENTRY"); + _State('BLOCK_SEQUENCE_FIRST_ENTRY'); /// Expect an entry of a block sequence. - static const BLOCK_SEQUENCE_ENTRY = _State("BLOCK_SEQUENCE_ENTRY"); + static const BLOCK_SEQUENCE_ENTRY = _State('BLOCK_SEQUENCE_ENTRY'); /// Expect an entry of an indentless sequence. - static const INDENTLESS_SEQUENCE_ENTRY = _State("INDENTLESS_SEQUENCE_ENTRY"); + static const INDENTLESS_SEQUENCE_ENTRY = _State('INDENTLESS_SEQUENCE_ENTRY'); /// Expect the first key of a block mapping. - static const BLOCK_MAPPING_FIRST_KEY = _State("BLOCK_MAPPING_FIRST_KEY"); + static const BLOCK_MAPPING_FIRST_KEY = _State('BLOCK_MAPPING_FIRST_KEY'); /// Expect a block mapping key. - static const BLOCK_MAPPING_KEY = _State("BLOCK_MAPPING_KEY"); + static const BLOCK_MAPPING_KEY = _State('BLOCK_MAPPING_KEY'); /// Expect a block mapping value. - static const BLOCK_MAPPING_VALUE = _State("BLOCK_MAPPING_VALUE"); + static const BLOCK_MAPPING_VALUE = _State('BLOCK_MAPPING_VALUE'); /// Expect the first entry of a flow sequence. - static const FLOW_SEQUENCE_FIRST_ENTRY = _State("FLOW_SEQUENCE_FIRST_ENTRY"); + static const FLOW_SEQUENCE_FIRST_ENTRY = _State('FLOW_SEQUENCE_FIRST_ENTRY'); /// Expect an entry of a flow sequence. - static const FLOW_SEQUENCE_ENTRY = _State("FLOW_SEQUENCE_ENTRY"); + static const FLOW_SEQUENCE_ENTRY = _State('FLOW_SEQUENCE_ENTRY'); /// Expect a key of an ordered mapping. static const FLOW_SEQUENCE_ENTRY_MAPPING_KEY = - _State("FLOW_SEQUENCE_ENTRY_MAPPING_KEY"); + _State('FLOW_SEQUENCE_ENTRY_MAPPING_KEY'); /// Expect a value of an ordered mapping. static const FLOW_SEQUENCE_ENTRY_MAPPING_VALUE = - _State("FLOW_SEQUENCE_ENTRY_MAPPING_VALUE"); + _State('FLOW_SEQUENCE_ENTRY_MAPPING_VALUE'); /// Expect the and of an ordered mapping entry. static const FLOW_SEQUENCE_ENTRY_MAPPING_END = - _State("FLOW_SEQUENCE_ENTRY_MAPPING_END"); + _State('FLOW_SEQUENCE_ENTRY_MAPPING_END'); /// Expect the first key of a flow mapping. - static const FLOW_MAPPING_FIRST_KEY = _State("FLOW_MAPPING_FIRST_KEY"); + static const FLOW_MAPPING_FIRST_KEY = _State('FLOW_MAPPING_FIRST_KEY'); /// Expect a key of a flow mapping. - static const FLOW_MAPPING_KEY = _State("FLOW_MAPPING_KEY"); + static const FLOW_MAPPING_KEY = _State('FLOW_MAPPING_KEY'); /// Expect a value of a flow mapping. - static const FLOW_MAPPING_VALUE = _State("FLOW_MAPPING_VALUE"); + static const FLOW_MAPPING_VALUE = _State('FLOW_MAPPING_VALUE'); /// Expect an empty value of a flow mapping. - static const FLOW_MAPPING_EMPTY_VALUE = _State("FLOW_MAPPING_EMPTY_VALUE"); + static const FLOW_MAPPING_EMPTY_VALUE = _State('FLOW_MAPPING_EMPTY_VALUE'); /// Expect nothing. - static const END = _State("END"); + static const END = _State('END'); final String name; const _State(this.name); + @override String toString() => name; } diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 637c8dda1..66d9d8b8d 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -295,7 +295,7 @@ class Scanner { /// Consumes and returns the next token. Token scan() { - if (_streamEndProduced) throw StateError("Out of tokens."); + if (_streamEndProduced) throw StateError('Out of tokens.'); if (!_tokenAvailable) _fetchMoreTokens(); var token = _tokens.removeFirst(); @@ -467,7 +467,7 @@ class Scanner { /// Throws an error about a disallowed character. void _invalidScalarCharacter() => - _scanner.error("Unexpected character.", length: 1); + _scanner.error('Unexpected character.', length: 1); /// Checks the list of potential simple keys and remove the positions that /// cannot contain simple keys anymore. @@ -655,7 +655,7 @@ class Scanner { if (_inBlockContext) { if (!_simpleKeyAllowed) { throw YamlException( - "Block sequence entries are not allowed here.", _scanner.emptySpan); + 'Block sequence entries are not allowed here.', _scanner.emptySpan); } _rollIndent( @@ -676,7 +676,7 @@ class Scanner { if (_inBlockContext) { if (!_simpleKeyAllowed) { throw YamlException( - "Mapping keys are not allowed here.", _scanner.emptySpan); + 'Mapping keys are not allowed here.', _scanner.emptySpan); } _rollIndent( @@ -711,8 +711,8 @@ class Scanner { } else if (_inBlockContext) { if (!_simpleKeyAllowed) { throw YamlException( - "Mapping values are not allowed here. Did you miss a colon " - "earlier?", + 'Mapping values are not allowed here. Did you miss a colon ' + 'earlier?', _scanner.emptySpan); } @@ -782,7 +782,7 @@ class Scanner { var afterLineBreak = false; while (true) { // Allow the BOM to start a line. - if (_scanner.column == 0) _scanner.scan("\uFEFF"); + if (_scanner.column == 0) _scanner.scan('\uFEFF'); // Eat whitespace. // @@ -795,7 +795,7 @@ class Scanner { } if (_scanner.peekChar() == TAB) { - _scanner.error("Tab characters are not allowed as indentation.", + _scanner.error('Tab characters are not allowed as indentation.', length: 1); } @@ -830,12 +830,12 @@ class Scanner { Token token; var name = _scanDirectiveName(); - if (name == "YAML") { + if (name == 'YAML') { token = _scanVersionDirectiveValue(start); - } else if (name == "TAG") { + } else if (name == 'TAG') { token = _scanTagDirectiveValue(start); } else { - warn("Warning: unknown directive.", _scanner.spanFrom(start)); + warn('Warning: unknown directive.', _scanner.spanFrom(start)); // libyaml doesn't support unknown directives, but the spec says to ignore // them and warn: http://yaml.org/spec/1.2/spec.html#id2781147. @@ -851,7 +851,7 @@ class Scanner { _skipComment(); if (!_isBreakOrEnd) { - throw YamlException("Expected comment or line break after directive.", + throw YamlException('Expected comment or line break after directive.', _scanner.spanFrom(start)); } @@ -875,10 +875,10 @@ class Scanner { var name = _scanner.substring(start); if (name.isEmpty) { - throw YamlException("Expected directive name.", _scanner.emptySpan); + throw YamlException('Expected directive name.', _scanner.emptySpan); } else if (!_isBlankOrEnd) { throw YamlException( - "Unexpected character in directive name.", _scanner.emptySpan); + 'Unexpected character in directive name.', _scanner.emptySpan); } return name; @@ -912,7 +912,7 @@ class Scanner { var number = _scanner.substring(start); if (number.isEmpty) { - throw YamlException("Expected version number.", _scanner.emptySpan); + throw YamlException('Expected version number.', _scanner.emptySpan); } return int.parse(number); @@ -927,14 +927,14 @@ class Scanner { var handle = _scanTagHandle(directive: true); if (!_isBlank) { - throw YamlException("Expected whitespace.", _scanner.emptySpan); + throw YamlException('Expected whitespace.', _scanner.emptySpan); } _skipBlanks(); var prefix = _scanTagUri(); if (!_isBlankOrEnd) { - throw YamlException("Expected whitespace.", _scanner.emptySpan); + throw YamlException('Expected whitespace.', _scanner.emptySpan); } return TagDirectiveToken(_scanner.spanFrom(start), handle, prefix); @@ -967,7 +967,7 @@ class Scanner { next != AT && next != GRAVE_ACCENT)) { throw YamlException( - "Expected alphanumeric character.", _scanner.emptySpan); + 'Expected alphanumeric character.', _scanner.emptySpan); } if (anchor) { @@ -1101,7 +1101,7 @@ class Scanner { if (_isDigit) { // Check that the indentation is greater than 0. if (_scanner.peekChar() == NUMBER_0) { - throw YamlException("0 may not be used as an indentation indicator.", + throw YamlException('0 may not be used as an indentation indicator.', _scanner.spanFrom(start)); } @@ -1110,7 +1110,7 @@ class Scanner { } else if (_isDigit) { // Do the same as above, but in the opposite order. if (_scanner.peekChar() == NUMBER_0) { - throw YamlException("0 may not be used as an indentation indicator.", + throw YamlException('0 may not be used as an indentation indicator.', _scanner.spanFrom(start)); } @@ -1130,7 +1130,7 @@ class Scanner { // Check if we're at the end of the line. if (!_isBreakOrEnd) { throw YamlException( - "Expected comment or line break.", _scanner.emptySpan); + 'Expected comment or line break.', _scanner.emptySpan); } _skipLine(); @@ -1257,11 +1257,11 @@ class Scanner { // Check that there are no document indicators at the beginning of the // line. if (_isDocumentIndicator) { - _scanner.error("Unexpected document indicator."); + _scanner.error('Unexpected document indicator.'); } if (_scanner.isDone) { - throw YamlException("Unexpected end of file.", _scanner.emptySpan); + throw YamlException('Unexpected end of file.', _scanner.emptySpan); } var leadingBlanks = false; @@ -1349,7 +1349,7 @@ class Scanner { break; default: throw YamlException( - "Unknown escape character.", _scanner.spanFrom(escapeStart)); + 'Unknown escape character.', _scanner.spanFrom(escapeStart)); } _scanner.readChar(); @@ -1361,7 +1361,7 @@ class Scanner { if (!_isHex) { _scanner.readChar(); throw YamlException( - "Expected $codeLength-digit hexidecimal number.", + 'Expected $codeLength-digit hexidecimal number.', _scanner.spanFrom(escapeStart)); } @@ -1370,7 +1370,7 @@ class Scanner { // Check the value and write the character. if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) { - throw YamlException("Invalid Unicode character escape code.", + throw YamlException('Invalid Unicode character escape code.', _scanner.spanFrom(escapeStart)); } @@ -1480,7 +1480,7 @@ class Scanner { if (leadingBreak.isNotEmpty && _scanner.column < indent && _scanner.peekChar() == TAB) { - _scanner.error("Expected a space but found a tab.", length: 1); + _scanner.error('Expected a space but found a tab.', length: 1); } if (leadingBreak.isEmpty) { @@ -1525,13 +1525,13 @@ class Scanner { // libyaml supports NEL, PS, and LS characters as line separators, but this // is explicitly forbidden in section 5.4 of the YAML spec. if (char != CR && char != LF) { - throw YamlException("Expected newline.", _scanner.emptySpan); + throw YamlException('Expected newline.', _scanner.emptySpan); } _scanner.readChar(); // CR LF | CR | LF -> LF if (char == CR && _scanner.peekChar() == LF) _scanner.readChar(); - return "\n"; + return '\n'; } // Returns whether the character at [offset] is whitespace. @@ -1668,17 +1668,18 @@ class _SimpleKey { /// See http://yaml.org/spec/1.2/spec.html#id2794534. class _Chomping { /// All trailing whitespace is discarded. - static const STRIP = _Chomping("STRIP"); + static const STRIP = _Chomping('STRIP'); /// A single trailing newline is retained. - static const CLIP = _Chomping("CLIP"); + static const CLIP = _Chomping('CLIP'); /// All trailing whitespace is preserved. - static const KEEP = _Chomping("KEEP"); + static const KEEP = _Chomping('KEEP'); final String name; const _Chomping(this.name); + @override String toString() => name; } diff --git a/pkgs/yaml/lib/src/style.dart b/pkgs/yaml/lib/src/style.dart index e945da871..6ddaf3dba 100644 --- a/pkgs/yaml/lib/src/style.dart +++ b/pkgs/yaml/lib/src/style.dart @@ -7,32 +7,32 @@ class ScalarStyle { /// No source style was specified. /// /// This usually indicates a scalar constructed with [YamlScalar.wrap]. - static const ANY = ScalarStyle._("ANY"); + static const ANY = ScalarStyle._('ANY'); /// The plain scalar style, unquoted and without a prefix. /// /// See http://yaml.org/spec/1.2/spec.html#style/flow/plain. - static const PLAIN = ScalarStyle._("PLAIN"); + static const PLAIN = ScalarStyle._('PLAIN'); /// The literal scalar style, with a `|` prefix. /// /// See http://yaml.org/spec/1.2/spec.html#id2795688. - static const LITERAL = ScalarStyle._("LITERAL"); + static const LITERAL = ScalarStyle._('LITERAL'); /// The folded scalar style, with a `>` prefix. /// /// See http://yaml.org/spec/1.2/spec.html#id2796251. - static const FOLDED = ScalarStyle._("FOLDED"); + static const FOLDED = ScalarStyle._('FOLDED'); /// The single-quoted scalar style. /// /// See http://yaml.org/spec/1.2/spec.html#style/flow/single-quoted. - static const SINGLE_QUOTED = ScalarStyle._("SINGLE_QUOTED"); + static const SINGLE_QUOTED = ScalarStyle._('SINGLE_QUOTED'); /// The double-quoted scalar style. /// /// See http://yaml.org/spec/1.2/spec.html#style/flow/double-quoted. - static const DOUBLE_QUOTED = ScalarStyle._("DOUBLE_QUOTED"); + static const DOUBLE_QUOTED = ScalarStyle._('DOUBLE_QUOTED'); final String name; @@ -41,6 +41,7 @@ class ScalarStyle { const ScalarStyle._(this.name); + @override String toString() => name; } @@ -50,21 +51,22 @@ class CollectionStyle { /// /// This usually indicates a collection constructed with [YamlList.wrap] or /// [YamlMap.wrap]. - static const ANY = CollectionStyle._("ANY"); + static const ANY = CollectionStyle._('ANY'); /// The indentation-based block style. /// /// See http://yaml.org/spec/1.2/spec.html#id2797293. - static const BLOCK = CollectionStyle._("BLOCK"); + static const BLOCK = CollectionStyle._('BLOCK'); /// The delimiter-based block style. /// /// See http://yaml.org/spec/1.2/spec.html#id2790088. - static const FLOW = CollectionStyle._("FLOW"); + static const FLOW = CollectionStyle._('FLOW'); final String name; const CollectionStyle._(this.name); + @override String toString() => name; } diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 62c7c58aa..7381a7dfe 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -16,12 +16,15 @@ class Token { Token(this.type, this.span); + @override String toString() => type.toString(); } /// A token representing a `%YAML` directive. class VersionDirectiveToken implements Token { - get type => TokenType.VERSION_DIRECTIVE; + @override + TokenType get type => TokenType.VERSION_DIRECTIVE; + @override final FileSpan span; /// The declared major version of the document. @@ -32,12 +35,15 @@ class VersionDirectiveToken implements Token { VersionDirectiveToken(this.span, this.major, this.minor); - String toString() => "VERSION_DIRECTIVE $major.$minor"; + @override + String toString() => 'VERSION_DIRECTIVE $major.$minor'; } /// A token representing a `%TAG` directive. class TagDirectiveToken implements Token { - get type => TokenType.TAG_DIRECTIVE; + @override + TokenType get type => TokenType.TAG_DIRECTIVE; + @override final FileSpan span; /// The tag handle used in the document. @@ -48,12 +54,15 @@ class TagDirectiveToken implements Token { TagDirectiveToken(this.span, this.handle, this.prefix); - String toString() => "TAG_DIRECTIVE $handle $prefix"; + @override + String toString() => 'TAG_DIRECTIVE $handle $prefix'; } /// A token representing an anchor (`&foo`). class AnchorToken implements Token { - get type => TokenType.ANCHOR; + @override + TokenType get type => TokenType.ANCHOR; + @override final FileSpan span; /// The name of the anchor. @@ -61,12 +70,15 @@ class AnchorToken implements Token { AnchorToken(this.span, this.name); - String toString() => "ANCHOR $name"; + @override + String toString() => 'ANCHOR $name'; } /// A token representing an alias (`*foo`). class AliasToken implements Token { - get type => TokenType.ALIAS; + @override + TokenType get type => TokenType.ALIAS; + @override final FileSpan span; /// The name of the anchor. @@ -74,12 +86,15 @@ class AliasToken implements Token { AliasToken(this.span, this.name); - String toString() => "ALIAS $name"; + @override + String toString() => 'ALIAS $name'; } /// A token representing a tag (`!foo`). class TagToken implements Token { - get type => TokenType.TAG; + @override + TokenType get type => TokenType.TAG; + @override final FileSpan span; /// The tag handle. @@ -90,12 +105,15 @@ class TagToken implements Token { TagToken(this.span, this.handle, this.suffix); - String toString() => "TAG $handle $suffix"; + @override + String toString() => 'TAG $handle $suffix'; } /// A tkoen representing a scalar value. class ScalarToken implements Token { - get type => TokenType.SCALAR; + @override + TokenType get type => TokenType.SCALAR; + @override final FileSpan span; /// The contents of the scalar. @@ -106,41 +124,43 @@ class ScalarToken implements Token { ScalarToken(this.span, this.value, this.style); - String toString() => "SCALAR $style \"$value\""; + @override + String toString() => 'SCALAR $style "$value"'; } /// An enum of types of [Token] object. class TokenType { - static const STREAM_START = TokenType._("STREAM_START"); - static const STREAM_END = TokenType._("STREAM_END"); + static const STREAM_START = TokenType._('STREAM_START'); + static const STREAM_END = TokenType._('STREAM_END'); - static const VERSION_DIRECTIVE = TokenType._("VERSION_DIRECTIVE"); - static const TAG_DIRECTIVE = TokenType._("TAG_DIRECTIVE"); - static const DOCUMENT_START = TokenType._("DOCUMENT_START"); - static const DOCUMENT_END = TokenType._("DOCUMENT_END"); + static const VERSION_DIRECTIVE = TokenType._('VERSION_DIRECTIVE'); + static const TAG_DIRECTIVE = TokenType._('TAG_DIRECTIVE'); + static const DOCUMENT_START = TokenType._('DOCUMENT_START'); + static const DOCUMENT_END = TokenType._('DOCUMENT_END'); - static const BLOCK_SEQUENCE_START = TokenType._("BLOCK_SEQUENCE_START"); - static const BLOCK_MAPPING_START = TokenType._("BLOCK_MAPPING_START"); - static const BLOCK_END = TokenType._("BLOCK_END"); + static const BLOCK_SEQUENCE_START = TokenType._('BLOCK_SEQUENCE_START'); + static const BLOCK_MAPPING_START = TokenType._('BLOCK_MAPPING_START'); + static const BLOCK_END = TokenType._('BLOCK_END'); - static const FLOW_SEQUENCE_START = TokenType._("FLOW_SEQUENCE_START"); - static const FLOW_SEQUENCE_END = TokenType._("FLOW_SEQUENCE_END"); - static const FLOW_MAPPING_START = TokenType._("FLOW_MAPPING_START"); - static const FLOW_MAPPING_END = TokenType._("FLOW_MAPPING_END"); + static const FLOW_SEQUENCE_START = TokenType._('FLOW_SEQUENCE_START'); + static const FLOW_SEQUENCE_END = TokenType._('FLOW_SEQUENCE_END'); + static const FLOW_MAPPING_START = TokenType._('FLOW_MAPPING_START'); + static const FLOW_MAPPING_END = TokenType._('FLOW_MAPPING_END'); - static const BLOCK_ENTRY = TokenType._("BLOCK_ENTRY"); - static const FLOW_ENTRY = TokenType._("FLOW_ENTRY"); - static const KEY = TokenType._("KEY"); - static const VALUE = TokenType._("VALUE"); + static const BLOCK_ENTRY = TokenType._('BLOCK_ENTRY'); + static const FLOW_ENTRY = TokenType._('FLOW_ENTRY'); + static const KEY = TokenType._('KEY'); + static const VALUE = TokenType._('VALUE'); - static const ALIAS = TokenType._("ALIAS"); - static const ANCHOR = TokenType._("ANCHOR"); - static const TAG = TokenType._("TAG"); - static const SCALAR = TokenType._("SCALAR"); + static const ALIAS = TokenType._('ALIAS'); + static const ANCHOR = TokenType._('ANCHOR'); + static const TAG = TokenType._('TAG'); + static const SCALAR = TokenType._('SCALAR'); final String name; const TokenType._(this.name); + @override String toString() => name; } diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 93954aace..8ce785501 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -11,6 +11,7 @@ class Pair { Pair(this.first, this.last); + @override String toString() => '($first, $last)'; } diff --git a/pkgs/yaml/lib/src/yaml_document.dart b/pkgs/yaml/lib/src/yaml_document.dart index 07806e972..8757418ad 100644 --- a/pkgs/yaml/lib/src/yaml_document.dart +++ b/pkgs/yaml/lib/src/yaml_document.dart @@ -35,6 +35,7 @@ class YamlDocument { {this.startImplicit = false, this.endImplicit = false}) : tagDirectives = UnmodifiableListView(tagDirectives); + @override String toString() => contents.toString(); } @@ -48,7 +49,8 @@ class VersionDirective { VersionDirective(this.major, this.minor); - String toString() => "%YAML $major.$minor"; + @override + String toString() => '%YAML $major.$minor'; } /// A directive describing a custom tag handle. @@ -61,5 +63,6 @@ class TagDirective { TagDirective(this.handle, this.prefix); - String toString() => "%TAG $handle $prefix"; + @override + String toString() => '%TAG $handle $prefix'; } diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 3b0a98364..25982e828 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -35,7 +35,7 @@ abstract class YamlNode { /// For [YamlScalar]s, this will return the wrapped value. For [YamlMap] and /// [YamlList], it will return [this], since they already implement [Map] and /// [List], respectively. - get value; + dynamic get value; } /// A read-only [Map] parsed from YAML. @@ -53,8 +53,10 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// The style used for the map in the original document. final CollectionStyle style; + @override Map get value => this; + @override Iterable get keys => nodes.keys.map((node) => node.value); /// Creates an empty YamlMap. @@ -84,10 +86,8 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { _span = span; } - operator [](key) { - var node = nodes[key]; - return node == null ? null : node.value; - } + @override + dynamic operator [](key) => nodes[key]?.value; } // TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed. @@ -98,12 +98,15 @@ class YamlList extends YamlNode with collection.ListMixin { /// The style used for the list in the original document. final CollectionStyle style; + @override List get value => this; + @override int get length => nodes.length; + @override set length(int index) { - throw UnsupportedError("Cannot modify an unmodifiable List"); + throw UnsupportedError('Cannot modify an unmodifiable List'); } /// Creates an empty YamlList. @@ -133,16 +136,19 @@ class YamlList extends YamlNode with collection.ListMixin { _span = span; } - operator [](int index) => nodes[index].value; + @override + dynamic operator [](int index) => nodes[index].value; + @override operator []=(int index, value) { - throw UnsupportedError("Cannot modify an unmodifiable List"); + throw UnsupportedError('Cannot modify an unmodifiable List'); } } /// A wrapped scalar value parsed from YAML. class YamlScalar extends YamlNode { - final value; + @override + final dynamic value; /// The style used for the scalar in the original document. final ScalarStyle style; @@ -169,6 +175,7 @@ class YamlScalar extends YamlNode { _span = span; } + @override String toString() => value.toString(); } diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index fc987afc3..e714b651f 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -15,16 +15,21 @@ import 'yaml_node.dart'; class YamlMapWrapper extends MapBase with pkg_collection.UnmodifiableMapMixin implements YamlMap { - final CollectionStyle style = CollectionStyle.ANY; + @override + final style = CollectionStyle.ANY; final Map _dartMap; + @override final SourceSpan span; + @override final Map nodes; + @override Map get value => this; + @override Iterable get keys => _dartMap.keys; YamlMapWrapper(Map dartMap, sourceUrl) : this._(dartMap, NullSpan(sourceUrl)); @@ -34,16 +39,19 @@ class YamlMapWrapper extends MapBase span = span, nodes = _YamlMapNodes(dartMap, span); - operator [](Object key) { + @override + dynamic operator [](Object key) { var value = _dartMap[key]; if (value is Map) return YamlMapWrapper._(value, span); if (value is List) return YamlListWrapper._(value, span); return value; } + @override int get hashCode => _dartMap.hashCode; - operator ==(Object other) => + @override + bool operator ==(Object other) => other is YamlMapWrapper && other._dartMap == _dartMap; } @@ -55,11 +63,13 @@ class _YamlMapNodes extends MapBase final SourceSpan _span; + @override Iterable get keys => _dartMap.keys.map((key) => YamlScalar.internalWithSpan(key, _span)); _YamlMapNodes(this._dartMap, this._span); + @override YamlNode operator [](Object key) { // Use "as" here because key being assigned to invalidates type propagation. if (key is YamlScalar) key = (key as YamlScalar).value; @@ -67,29 +77,37 @@ class _YamlMapNodes extends MapBase return _nodeForValue(_dartMap[key], _span); } + @override int get hashCode => _dartMap.hashCode; - operator ==(Object other) => + @override + bool operator ==(Object other) => other is _YamlMapNodes && other._dartMap == _dartMap; } // TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed. /// A wrapper that makes a normal Dart list behave like a [YamlList]. class YamlListWrapper extends ListBase implements YamlList { - final CollectionStyle style = CollectionStyle.ANY; + @override + final style = CollectionStyle.ANY; final List _dartList; + @override final SourceSpan span; + @override final List nodes; + @override List get value => this; + @override int get length => _dartList.length; + @override set length(int index) { - throw UnsupportedError("Cannot modify an unmodifiable List."); + throw UnsupportedError('Cannot modify an unmodifiable List.'); } YamlListWrapper(List dartList, sourceUrl) @@ -100,20 +118,24 @@ class YamlListWrapper extends ListBase implements YamlList { span = span, nodes = _YamlListNodes(dartList, span); - operator [](int index) { + @override + dynamic operator [](int index) { var value = _dartList[index]; if (value is Map) return YamlMapWrapper._(value, span); if (value is List) return YamlListWrapper._(value, span); return value; } + @override operator []=(int index, value) { - throw UnsupportedError("Cannot modify an unmodifiable List."); + throw UnsupportedError('Cannot modify an unmodifiable List.'); } + @override int get hashCode => _dartList.hashCode; - operator ==(Object other) => + @override + bool operator ==(Object other) => other is YamlListWrapper && other._dartList == _dartList; } @@ -125,23 +147,29 @@ class _YamlListNodes extends ListBase { final SourceSpan _span; + @override int get length => _dartList.length; + @override set length(int index) { - throw UnsupportedError("Cannot modify an unmodifiable List."); + throw UnsupportedError('Cannot modify an unmodifiable List.'); } _YamlListNodes(this._dartList, this._span); + @override YamlNode operator [](int index) => _nodeForValue(_dartList[index], _span); + @override operator []=(int index, value) { - throw UnsupportedError("Cannot modify an unmodifiable List."); + throw UnsupportedError('Cannot modify an unmodifiable List.'); } + @override int get hashCode => _dartList.hashCode; - operator ==(Object other) => + @override + bool operator ==(Object other) => other is _YamlListNodes && other._dartList == _dartList; } diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index e2435ad0f..2ef65e7d7 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -30,7 +30,7 @@ export 'src/yaml_node.dart' hide setSpan; /// /// If [sourceUrl] is passed, it's used as the URL from which the YAML /// originated for error reporting. It can be a [String], a [Uri], or `null`. -loadYaml(String yaml, {sourceUrl}) => +dynamic loadYaml(String yaml, {sourceUrl}) => loadYamlNode(yaml, sourceUrl: sourceUrl).value; /// Loads a single document from a YAML string as a [YamlNode]. @@ -56,7 +56,7 @@ YamlDocument loadYamlDocument(String yaml, {sourceUrl}) { var nextDocument = loader.load(); if (nextDocument != null) { - throw YamlException("Only expected one document.", nextDocument.span); + throw YamlException('Only expected one document.', nextDocument.span); } return document; diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 6d056da48..d83ad8ac7 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,12 +1,12 @@ name: yaml -version: 2.2.0 +version: 2.2.1-dev description: A parser for YAML, a human-friendly data serialization standard author: Dart Team homepage: https://github.com/dart-lang/yaml environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.3.0 <3.0.0' dependencies: charcode: ^1.1.0 diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index 5ecbd142f..c49afe2d3 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -13,7 +13,7 @@ final Matcher throwsYamlException = throwsA(TypeMatcher()); /// /// This handles recursive loops and considers `NaN` to equal itself. Matcher deepEquals(expected) => predicate( - (actual) => equality.deepEquals(actual, expected), "equals $expected"); + (actual) => equality.deepEquals(actual, expected), 'equals $expected'); /// Constructs a new yaml.YamlMap, optionally from a normal Map. Map deepEqualsMap([Map from]) { @@ -77,8 +77,8 @@ String indentLiteral(String text) { if (lines.length <= 1) return text; for (var i = 0; i < lines.length; i++) { - lines[i] = " ${lines[i]}"; + lines[i] = ' ${lines[i]}'; } - return lines.join("\n"); + return lines.join('\n'); } diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index f9b02728e..9dc991e87 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -6,94 +6,94 @@ import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; -main() { - test("YamlMap() with no sourceUrl", () { +void main() { + test('YamlMap() with no sourceUrl', () { var map = YamlMap(); expect(map, isEmpty); expect(map.nodes, isEmpty); expect(map.span, isNullSpan(isNull)); }); - test("YamlMap() with a sourceUrl", () { - var map = YamlMap(sourceUrl: "source"); - expect(map.span, isNullSpan(Uri.parse("source"))); + test('YamlMap() with a sourceUrl', () { + var map = YamlMap(sourceUrl: 'source'); + expect(map.span, isNullSpan(Uri.parse('source'))); }); - test("YamlList() with no sourceUrl", () { + test('YamlList() with no sourceUrl', () { var list = YamlList(); expect(list, isEmpty); expect(list.nodes, isEmpty); expect(list.span, isNullSpan(isNull)); }); - test("YamlList() with a sourceUrl", () { - var list = YamlList(sourceUrl: "source"); - expect(list.span, isNullSpan(Uri.parse("source"))); + test('YamlList() with a sourceUrl', () { + var list = YamlList(sourceUrl: 'source'); + expect(list.span, isNullSpan(Uri.parse('source'))); }); - test("YamlMap.wrap() with no sourceUrl", () { + test('YamlMap.wrap() with no sourceUrl', () { var map = YamlMap.wrap({ - "list": [1, 2, 3], - "map": { - "foo": "bar", - "nested": [4, 5, 6] + 'list': [1, 2, 3], + 'map': { + 'foo': 'bar', + 'nested': [4, 5, 6] }, - "scalar": "value" + 'scalar': 'value' }); expect( map, equals({ - "list": [1, 2, 3], - "map": { - "foo": "bar", - "nested": [4, 5, 6] + 'list': [1, 2, 3], + 'map': { + 'foo': 'bar', + 'nested': [4, 5, 6] }, - "scalar": "value" + 'scalar': 'value' })); expect(map.span, isNullSpan(isNull)); - expect(map["list"], TypeMatcher()); - expect(map["list"].nodes[0], TypeMatcher()); - expect(map["list"].span, isNullSpan(isNull)); - expect(map["map"], TypeMatcher()); - expect(map["map"].nodes["foo"], TypeMatcher()); - expect(map["map"]["nested"], TypeMatcher()); - expect(map["map"].span, isNullSpan(isNull)); - expect(map.nodes["scalar"], TypeMatcher()); - expect(map.nodes["scalar"].value, "value"); - expect(map.nodes["scalar"].span, isNullSpan(isNull)); - expect(map["scalar"], "value"); - expect(map.keys, unorderedEquals(["list", "map", "scalar"])); + expect(map['list'], TypeMatcher()); + expect(map['list'].nodes[0], TypeMatcher()); + expect(map['list'].span, isNullSpan(isNull)); + expect(map['map'], TypeMatcher()); + expect(map['map'].nodes['foo'], TypeMatcher()); + expect(map['map']['nested'], TypeMatcher()); + expect(map['map'].span, isNullSpan(isNull)); + expect(map.nodes['scalar'], TypeMatcher()); + expect(map.nodes['scalar'].value, 'value'); + expect(map.nodes['scalar'].span, isNullSpan(isNull)); + expect(map['scalar'], 'value'); + expect(map.keys, unorderedEquals(['list', 'map', 'scalar'])); expect(map.nodes.keys, everyElement(TypeMatcher())); - expect(map.nodes[YamlScalar.wrap("list")], equals([1, 2, 3])); + expect(map.nodes[YamlScalar.wrap('list')], equals([1, 2, 3])); }); - test("YamlMap.wrap() with a sourceUrl", () { + test('YamlMap.wrap() with a sourceUrl', () { var map = YamlMap.wrap({ - "list": [1, 2, 3], - "map": { - "foo": "bar", - "nested": [4, 5, 6] + 'list': [1, 2, 3], + 'map': { + 'foo': 'bar', + 'nested': [4, 5, 6] }, - "scalar": "value" - }, sourceUrl: "source"); + 'scalar': 'value' + }, sourceUrl: 'source'); - var source = Uri.parse("source"); + var source = Uri.parse('source'); expect(map.span, isNullSpan(source)); - expect(map["list"].span, isNullSpan(source)); - expect(map["map"].span, isNullSpan(source)); - expect(map.nodes["scalar"].span, isNullSpan(source)); + expect(map['list'].span, isNullSpan(source)); + expect(map['map'].span, isNullSpan(source)); + expect(map.nodes['scalar'].span, isNullSpan(source)); }); - test("YamlList.wrap() with no sourceUrl", () { + test('YamlList.wrap() with no sourceUrl', () { var list = YamlList.wrap([ [1, 2, 3], { - "foo": "bar", - "nested": [4, 5, 6] + 'foo': 'bar', + 'nested': [4, 5, 6] }, - "value" + 'value' ]); expect( @@ -101,10 +101,10 @@ main() { equals([ [1, 2, 3], { - "foo": "bar", - "nested": [4, 5, 6] + 'foo': 'bar', + 'nested': [4, 5, 6] }, - "value" + 'value' ])); expect(list.span, isNullSpan(isNull)); @@ -112,23 +112,23 @@ main() { expect(list[0].nodes[0], TypeMatcher()); expect(list[0].span, isNullSpan(isNull)); expect(list[1], TypeMatcher()); - expect(list[1].nodes["foo"], TypeMatcher()); - expect(list[1]["nested"], TypeMatcher()); + expect(list[1].nodes['foo'], TypeMatcher()); + expect(list[1]['nested'], TypeMatcher()); expect(list[1].span, isNullSpan(isNull)); expect(list.nodes[2], TypeMatcher()); - expect(list.nodes[2].value, "value"); + expect(list.nodes[2].value, 'value'); expect(list.nodes[2].span, isNullSpan(isNull)); - expect(list[2], "value"); + expect(list[2], 'value'); }); - test("YamlList.wrap() with a sourceUrl", () { + test('YamlList.wrap() with a sourceUrl', () { var list = YamlList.wrap([ [1, 2, 3], { - "foo": "bar", - "nested": [4, 5, 6] + 'foo': 'bar', + 'nested': [4, 5, 6] }, - "value" + 'value' ]); expect(list.span, isNullSpan(isNull)); @@ -137,10 +137,10 @@ main() { expect(list.nodes[2].span, isNullSpan(isNull)); }); - test("re-wrapped objects equal one another", () { + test('re-wrapped objects equal one another', () { var list = YamlList.wrap([ [1, 2, 3], - {"foo": "bar"} + {'foo': 'bar'} ]); expect(list[0] == list[0], isTrue); @@ -148,7 +148,7 @@ main() { expect(list[0] == YamlList.wrap([1, 2, 3]), isFalse); expect(list[1] == list[1], isTrue); expect(list[1].nodes == list[1].nodes, isTrue); - expect(list[1] == YamlMap.wrap({"foo": "bar"}), isFalse); + expect(list[1] == YamlMap.wrap({'foo': 'bar'}), isFalse); }); } diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index dcc506a34..a0fb8f110 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -7,9 +7,9 @@ import 'package:yaml/yaml.dart'; import 'utils.dart'; -main() { - var infinity = double.parse("Infinity"); - var nan = double.parse("NaN"); +void main() { + var infinity = double.parse('Infinity'); + var nan = double.parse('NaN'); group('has a friendly error message for', () { var tabError = predicate((e) => @@ -27,46 +27,46 @@ main() { }); }); - group("refuses", () { + group('refuses', () { // Regression test for #19. - test("invalid contents", () { - expectYamlFails("{"); + test('invalid contents', () { + expectYamlFails('{'); }); - test("duplicate mapping keys", () { - expectYamlFails("{a: 1, a: 2}"); + test('duplicate mapping keys', () { + expectYamlFails('{a: 1, a: 2}'); }); - group("documents that declare version", () { - test("1.0", () { - expectYamlFails(""" + group('documents that declare version', () { + test('1.0', () { + expectYamlFails(''' %YAML 1.0 --- text - """); + '''); }); - test("1.3", () { - expectYamlFails(""" + test('1.3', () { + expectYamlFails(''' %YAML 1.3 --- text - """); + '''); }); - test("2.0", () { - expectYamlFails(""" + test('2.0', () { + expectYamlFails(''' %YAML 2.0 --- text - """); + '''); }); }); }); - test("includes source span information", () { - var yaml = loadYamlNode(r""" + test('includes source span information', () { + var yaml = loadYamlNode(r''' - foo: bar - 123 -""") as YamlList; +''') as YamlList; expect(yaml.span.start.line, equals(0)); expect(yaml.span.start.column, equals(0)); @@ -113,24 +113,24 @@ main() { // the spec. group('2.1: Collections', () { test('[Example 2.1]', () { - expectYamlLoads(["Mark McGwire", "Sammy Sosa", "Ken Griffey"], """ + expectYamlLoads(['Mark McGwire', 'Sammy Sosa', 'Ken Griffey'], ''' - Mark McGwire - Sammy Sosa - - Ken Griffey"""); + - Ken Griffey'''); }); test('[Example 2.2]', () { - expectYamlLoads({"hr": 65, "avg": 0.278, "rbi": 147}, """ + expectYamlLoads({'hr': 65, 'avg': 0.278, 'rbi': 147}, ''' hr: 65 # Home runs avg: 0.278 # Batting average - rbi: 147 # Runs Batted In"""); + rbi: 147 # Runs Batted In'''); }); test('[Example 2.3]', () { expectYamlLoads({ - "american": ["Boston Red Sox", "Detroit Tigers", "New York Yankees"], - "national": ["New York Mets", "Chicago Cubs", "Atlanta Braves"], - }, """ + 'american': ['Boston Red Sox', 'Detroit Tigers', 'New York Yankees'], + 'national': ['New York Mets', 'Chicago Cubs', 'Atlanta Braves'], + }, ''' american: - Boston Red Sox - Detroit Tigers @@ -138,14 +138,14 @@ main() { national: - New York Mets - Chicago Cubs - - Atlanta Braves"""); + - Atlanta Braves'''); }); test('[Example 2.4]', () { expectYamlLoads([ - {"name": "Mark McGwire", "hr": 65, "avg": 0.278}, - {"name": "Sammy Sosa", "hr": 63, "avg": 0.288}, - ], """ + {'name': 'Mark McGwire', 'hr': 65, 'avg': 0.278}, + {'name': 'Sammy Sosa', 'hr': 63, 'avg': 0.288}, + ], ''' - name: Mark McGwire hr: 65 @@ -153,39 +153,39 @@ main() { - name: Sammy Sosa hr: 63 - avg: 0.288"""); + avg: 0.288'''); }); test('[Example 2.5]', () { expectYamlLoads([ - ["name", "hr", "avg"], - ["Mark McGwire", 65, 0.278], - ["Sammy Sosa", 63, 0.288] - ], """ + ['name', 'hr', 'avg'], + ['Mark McGwire', 65, 0.278], + ['Sammy Sosa', 63, 0.288] + ], ''' - [name , hr, avg ] - [Mark McGwire, 65, 0.278] - - [Sammy Sosa , 63, 0.288]"""); + - [Sammy Sosa , 63, 0.288]'''); }); test('[Example 2.6]', () { expectYamlLoads({ - "Mark McGwire": {"hr": 65, "avg": 0.278}, - "Sammy Sosa": {"hr": 63, "avg": 0.288} - }, """ + 'Mark McGwire': {'hr': 65, 'avg': 0.278}, + 'Sammy Sosa': {'hr': 63, 'avg': 0.288} + }, ''' Mark McGwire: {hr: 65, avg: 0.278} Sammy Sosa: { hr: 63, avg: 0.288 - }"""); + }'''); }); }); group('2.2: Structures', () { test('[Example 2.7]', () { expectYamlStreamLoads([ - ["Mark McGwire", "Sammy Sosa", "Ken Griffey"], - ["Chicago Cubs", "St Louis Cardinals"] - ], """ + ['Mark McGwire', 'Sammy Sosa', 'Ken Griffey'], + ['Chicago Cubs', 'St Louis Cardinals'] + ], ''' # Ranking of 1998 home runs --- - Mark McGwire @@ -195,14 +195,14 @@ main() { # Team ranking --- - Chicago Cubs - - St Louis Cardinals"""); + - St Louis Cardinals'''); }); test('[Example 2.8]', () { expectYamlStreamLoads([ - {"time": "20:03:20", "player": "Sammy Sosa", "action": "strike (miss)"}, - {"time": "20:03:47", "player": "Sammy Sosa", "action": "grand slam"}, - ], """ + {'time': '20:03:20', 'player': 'Sammy Sosa', 'action': 'strike (miss)'}, + {'time': '20:03:47', 'player': 'Sammy Sosa', 'action': 'grand slam'}, + ], ''' --- time: 20:03:20 player: Sammy Sosa @@ -212,14 +212,14 @@ main() { time: 20:03:47 player: Sammy Sosa action: grand slam - ..."""); + ...'''); }); test('[Example 2.9]', () { expectYamlLoads({ - "hr": ["Mark McGwire", "Sammy Sosa"], - "rbi": ["Sammy Sosa", "Ken Griffey"] - }, """ + 'hr': ['Mark McGwire', 'Sammy Sosa'], + 'rbi': ['Sammy Sosa', 'Ken Griffey'] + }, ''' --- hr: # 1998 hr ranking - Mark McGwire @@ -227,14 +227,14 @@ main() { rbi: # 1998 rbi ranking - Sammy Sosa - - Ken Griffey"""); + - Ken Griffey'''); }); test('[Example 2.10]', () { expectYamlLoads({ - "hr": ["Mark McGwire", "Sammy Sosa"], - "rbi": ["Sammy Sosa", "Ken Griffey"] - }, """ + 'hr': ['Mark McGwire', 'Sammy Sosa'], + 'rbi': ['Sammy Sosa', 'Ken Griffey'] + }, ''' --- hr: - Mark McGwire @@ -242,18 +242,18 @@ main() { - &SS Sammy Sosa rbi: - *SS # Subsequent occurrence - - Ken Griffey"""); + - Ken Griffey'''); }); test('[Example 2.11]', () { var doc = deepEqualsMap(); - doc[["Detroit Tigers", "Chicago cubs"]] = ["2001-07-23"]; - doc[["New York Yankees", "Atlanta Braves"]] = [ - "2001-07-02", - "2001-08-12", - "2001-08-14" + doc[['Detroit Tigers', 'Chicago cubs']] = ['2001-07-23']; + doc[['New York Yankees', 'Atlanta Braves']] = [ + '2001-07-02', + '2001-08-12', + '2001-08-14' ]; - expectYamlLoads(doc, """ + expectYamlLoads(doc, ''' ? - Detroit Tigers - Chicago cubs : @@ -262,15 +262,15 @@ main() { ? [ New York Yankees, Atlanta Braves ] : [ 2001-07-02, 2001-08-12, - 2001-08-14 ]"""); + 2001-08-14 ]'''); }); test('[Example 2.12]', () { expectYamlLoads([ - {"item": "Super Hoop", "quantity": 1}, - {"item": "Basketball", "quantity": 4}, - {"item": "Big Shoes", "quantity": 1}, - ], """ + {'item': 'Super Hoop', 'quantity': 1}, + {'item': 'Basketball', 'quantity': 4}, + {'item': 'Big Shoes', 'quantity': 1}, + ], ''' --- # Products purchased - item : Super Hoop @@ -278,37 +278,37 @@ main() { - item : Basketball quantity: 4 - item : Big Shoes - quantity: 1"""); + quantity: 1'''); }); }); group('2.3: Scalars', () { test('[Example 2.13]', () { - expectYamlLoads(cleanUpLiteral(""" + expectYamlLoads(cleanUpLiteral(''' \\//||\\/|| - // || ||__"""), """ + // || ||__'''), ''' # ASCII Art --- | \\//||\\/|| - // || ||__"""); + // || ||__'''); }); test('[Example 2.14]', () { - expectYamlLoads("Mark McGwire's year was crippled by a knee injury.", """ + expectYamlLoads("Mark McGwire's year was crippled by a knee injury.", ''' --- > Mark McGwire's year was crippled - by a knee injury."""); + by a knee injury.'''); }); test('[Example 2.15]', () { - expectYamlLoads(cleanUpLiteral(""" + expectYamlLoads(cleanUpLiteral(''' Sammy Sosa completed another fine season with great stats. 63 Home Runs 0.288 Batting Average - What a year!"""), """ + What a year!'''), ''' > Sammy Sosa completed another fine season with great stats. @@ -316,32 +316,32 @@ main() { 63 Home Runs 0.288 Batting Average - What a year!"""); + What a year!'''); }); test('[Example 2.16]', () { expectYamlLoads({ - "name": "Mark McGwire", - "accomplishment": "Mark set a major league home run record in 1998.\n", - "stats": "65 Home Runs\n0.278 Batting Average" - }, """ + 'name': 'Mark McGwire', + 'accomplishment': 'Mark set a major league home run record in 1998.\n', + 'stats': '65 Home Runs\n0.278 Batting Average' + }, ''' name: Mark McGwire accomplishment: > Mark set a major league home run record in 1998. stats: | 65 Home Runs - 0.278 Batting Average"""); + 0.278 Batting Average'''); }); test('[Example 2.17]', () { expectYamlLoads({ - "unicode": "Sosa did fine.\u263A", - "control": "\b1998\t1999\t2000\n", - "hex esc": "\r\n is \r\n", - "single": '"Howdy!" he cried.', - "quoted": " # Not a 'comment'.", - "tie-fighter": "|\\-*-/|" + 'unicode': 'Sosa did fine.\u263A', + 'control': '\b1998\t1999\t2000\n', + 'hex esc': '\r\n is \r\n', + 'single': '"Howdy!" he cried.', + 'quoted': " # Not a 'comment'.", + 'tie-fighter': '|\\-*-/|' }, """ unicode: "Sosa did fine.\\u263A" control: "\\b1998\\t1999\\t2000\\n" @@ -354,8 +354,8 @@ main() { test('[Example 2.18]', () { expectYamlLoads({ - "plain": "This unquoted scalar spans many lines.", - "quoted": "So does this quoted scalar.\n" + 'plain': 'This unquoted scalar spans many lines.', + 'quoted': 'So does this quoted scalar.\n' }, ''' plain: This unquoted scalar @@ -369,36 +369,36 @@ main() { group('2.4: Tags', () { test('[Example 2.19]', () { expectYamlLoads({ - "canonical": 12345, - "decimal": 12345, - "octal": 12, - "hexadecimal": 12 - }, """ + 'canonical': 12345, + 'decimal': 12345, + 'octal': 12, + 'hexadecimal': 12 + }, ''' canonical: 12345 decimal: +12345 octal: 0o14 - hexadecimal: 0xC"""); + hexadecimal: 0xC'''); }); test('[Example 2.20]', () { expectYamlLoads({ - "canonical": 1230.15, - "exponential": 1230.15, - "fixed": 1230.15, - "negative infinity": -infinity, - "not a number": nan - }, """ + 'canonical': 1230.15, + 'exponential': 1230.15, + 'fixed': 1230.15, + 'negative infinity': -infinity, + 'not a number': nan + }, ''' canonical: 1.23015e+3 exponential: 12.3015e+02 fixed: 1230.15 negative infinity: -.inf - not a number: .NaN"""); + not a number: .NaN'''); }); test('[Example 2.21]', () { var doc = deepEqualsMap({ - "booleans": [true, false], - "string": "012345" + 'booleans': [true, false], + 'string': '012345' }); doc[null] = null; expectYamlLoads(doc, """ @@ -418,29 +418,29 @@ main() { test('[Example 2.28]', () { expectYamlStreamLoads([ { - "Time": "2001-11-23 15:01:42 -5", - "User": "ed", - "Warning": "This is an error message for the log file" + 'Time': '2001-11-23 15:01:42 -5', + 'User': 'ed', + 'Warning': 'This is an error message for the log file' }, { - "Time": "2001-11-23 15:02:31 -5", - "User": "ed", - "Warning": "A slightly different error message." + 'Time': '2001-11-23 15:02:31 -5', + 'User': 'ed', + 'Warning': 'A slightly different error message.' }, { - "DateTime": "2001-11-23 15:03:17 -5", - "User": "ed", - "Fatal": 'Unknown variable "bar"', - "Stack": [ + 'DateTime': '2001-11-23 15:03:17 -5', + 'User': 'ed', + 'Fatal': 'Unknown variable "bar"', + 'Stack': [ { - "file": "TopClass.py", - "line": 23, - "code": 'x = MoreObject("345\\n")\n' + 'file': 'TopClass.py', + 'line': 23, + 'code': 'x = MoreObject("345\\n")\n' }, - {"file": "MoreClass.py", "line": 58, "code": "foo = bar"} + {'file': 'MoreClass.py', 'line': 58, 'code': 'foo = bar'} ] } - ], """ + ], ''' --- Time: 2001-11-23 15:01:42 -5 User: ed @@ -466,7 +466,7 @@ main() { - file: MoreClass.py line: 58 code: |- - foo = bar"""); + foo = bar'''); }); }); @@ -475,19 +475,19 @@ main() { // Chapter 5: Characters group('5.1: Character Set', () { - expectAllowsCharacter(int charCode) { + void expectAllowsCharacter(int charCode) { var char = String.fromCharCodes([charCode]); expectYamlLoads('The character "$char" is allowed', 'The character "$char" is allowed'); } - expectAllowsQuotedCharacter(int charCode) { + void expectAllowsQuotedCharacter(int charCode) { var char = String.fromCharCodes([charCode]); expectYamlLoads("The character '$char' is allowed", '"The character \'$char\' is allowed"'); } - expectDisallowsCharacter(int charCode) { + void expectDisallowsCharacter(int charCode) { var char = String.fromCharCodes([charCode]); expectYamlFails('The character "$char" is disallowed'); } @@ -498,7 +498,7 @@ main() { expectDisallowsCharacter(0x1F); }); - test("includes TAB", () => expectAllowsCharacter(0x9)); + test('includes TAB', () => expectAllowsCharacter(0x9)); test("doesn't include DEL", () => expectDisallowsCharacter(0x7F)); test("doesn't include C1 control characters", () { @@ -507,11 +507,11 @@ main() { expectDisallowsCharacter(0x9F); }); - test("includes NEL", () => expectAllowsCharacter(0x85)); + test('includes NEL', () => expectAllowsCharacter(0x85)); - group("within quoted strings", () { - test("includes DEL", () => expectAllowsQuotedCharacter(0x7F)); - test("includes C1 control characters", () { + group('within quoted strings', () { + test('includes DEL', () => expectAllowsQuotedCharacter(0x7F)); + test('includes C1 control characters', () { expectAllowsQuotedCharacter(0x80); expectAllowsQuotedCharacter(0x8A); expectAllowsQuotedCharacter(0x9F); @@ -528,117 +528,117 @@ main() { expectYamlLoads({ 'sequence': ['one', 'two'], 'mapping': {'sky': 'blue', 'sea': 'green'} - }, """ + }, ''' sequence: - one - two mapping: ? sky : blue - sea : green"""); + sea : green'''); }); test('[Example 5.4]', () { expectYamlLoads({ 'sequence': ['one', 'two'], 'mapping': {'sky': 'blue', 'sea': 'green'} - }, """ + }, ''' sequence: [ one, two, ] - mapping: { sky: blue, sea: green }"""); + mapping: { sky: blue, sea: green }'''); }); - test('[Example 5.5]', () => expectYamlLoads(null, "# Comment only.")); + test('[Example 5.5]', () => expectYamlLoads(null, '# Comment only.')); // Skipping 5.6 because it uses an undefined tag. test('[Example 5.7]', () { - expectYamlLoads({'literal': "some\ntext\n", 'folded': "some text\n"}, """ + expectYamlLoads({'literal': 'some\ntext\n', 'folded': 'some text\n'}, ''' literal: | some text folded: > some text - """); + '''); }); test('[Example 5.8]', () { - expectYamlLoads({'single': "text", 'double': "text"}, """ + expectYamlLoads({'single': 'text', 'double': 'text'}, ''' single: 'text' double: "text" - """); + '''); }); test('[Example 5.9]', () { - expectYamlLoads("text", """ + expectYamlLoads('text', ''' %YAML 1.2 - --- text"""); + --- text'''); }); test('[Example 5.10]', () { - expectYamlFails("commercial-at: @text"); - expectYamlFails("commercial-at: `text"); + expectYamlFails('commercial-at: @text'); + expectYamlFails('commercial-at: `text'); }); }); group('5.4: Line Break Characters', () { group('include', () { - test('\\n', () => expectYamlLoads([1, 2], indentLiteral("- 1\n- 2"))); - test('\\r', () => expectYamlLoads([1, 2], "- 1\r- 2")); + test('\\n', () => expectYamlLoads([1, 2], indentLiteral('- 1\n- 2'))); + test('\\r', () => expectYamlLoads([1, 2], '- 1\r- 2')); }); group('do not include', () { - test('form feed', () => expectYamlFails("- 1\x0C- 2")); - test('NEL', () => expectYamlLoads(["1\x85- 2"], "- 1\x85- 2")); - test('0x2028', () => expectYamlLoads(["1\u2028- 2"], "- 1\u2028- 2")); - test('0x2029', () => expectYamlLoads(["1\u2029- 2"], "- 1\u2029- 2")); + test('form feed', () => expectYamlFails('- 1\x0C- 2')); + test('NEL', () => expectYamlLoads(['1\x85- 2'], '- 1\x85- 2')); + test('0x2028', () => expectYamlLoads(['1\u2028- 2'], '- 1\u2028- 2')); + test('0x2029', () => expectYamlLoads(['1\u2029- 2'], '- 1\u2029- 2')); }); group('in a scalar context must be normalized', () { test( - "from \\r to \\n", + 'from \\r to \\n', () => expectYamlLoads( - ["foo\nbar"], indentLiteral('- |\n foo\r bar'))); + ['foo\nbar'], indentLiteral('- |\n foo\r bar'))); test( - "from \\r\\n to \\n", + 'from \\r\\n to \\n', () => expectYamlLoads( - ["foo\nbar"], indentLiteral('- |\n foo\r\n bar'))); + ['foo\nbar'], indentLiteral('- |\n foo\r\n bar'))); }); test('[Example 5.11]', () { - expectYamlLoads(cleanUpLiteral(""" + expectYamlLoads(cleanUpLiteral(''' Line break (no glyph) - Line break (glyphed)"""), """ + Line break (glyphed)'''), ''' | Line break (no glyph) - Line break (glyphed)"""); + Line break (glyphed)'''); }); }); group('5.5: White Space Characters', () { test('[Example 5.12]', () { expectYamlLoads({ - "quoted": "Quoted \t", - "block": 'void main() {\n\tprintf("Hello, world!\\n");\n}\n' - }, """ + 'quoted': 'Quoted \t', + 'block': 'void main() {\n\tprintf("Hello, world!\\n");\n}\n' + }, ''' # Tabs and spaces quoted: "Quoted \t" block:\t| void main() { \tprintf("Hello, world!\\n"); } - """); + '''); }); }); group('5.7: Escaped Characters', () { test('[Example 5.13]', () { expectYamlLoads( - "Fun with \x5C " - "\x22 \x07 \x08 \x1B \x0C " - "\x0A \x0D \x09 \x0B \x00 " - "\x20 \xA0 \x85 \u2028 \u2029 " - "A A A", + 'Fun with \x5C ' + '\x22 \x07 \x08 \x1B \x0C ' + '\x0A \x0D \x09 \x0B \x00 ' + '\x20 \xA0 \x85 \u2028 \u2029 ' + 'A A A', ''' "Fun with \\\\ \\" \\a \\b \\e \\f \\ @@ -656,37 +656,37 @@ main() { // Chapter 6: Basic Structures group('6.1: Indentation Spaces', () { test('may not include TAB characters', () { - expectYamlFails(""" + expectYamlFails(''' - \t- foo - \t- bar"""); + \t- bar'''); }); test('must be the same for all sibling nodes', () { - expectYamlFails(""" + expectYamlFails(''' - - foo - - bar"""); + - bar'''); }); test('may be different for the children of sibling nodes', () { expectYamlLoads([ - ["foo"], - ["bar"] - ], """ + ['foo'], + ['bar'] + ], ''' - - foo - - - bar"""); + - bar'''); }); test('[Example 6.1]', () { expectYamlLoads({ - "Not indented": { - "By one space": "By four\n spaces\n", - "Flow style": ["By two", "Also by two", "Still by two"] + 'Not indented': { + 'By one space': 'By four\n spaces\n', + 'Flow style': ['By two', 'Also by two', 'Still by two'] } - }, """ + }, ''' # Leading comment line spaces are # neither content nor indentation. @@ -698,7 +698,7 @@ main() { By two, # in flow style Also by two, # are neither \tStill by two # content nor - ] # indentation."""); + ] # indentation.'''); }); test('[Example 6.2]', () { @@ -707,11 +707,11 @@ main() { 'b', ['c', 'd'] ] - }, """ + }, ''' ? a : -\tb - -\tc - - d"""); + - d'''); }); }); @@ -720,20 +720,20 @@ main() { expectYamlLoads([ {'foo': 'bar'}, ['baz', 'baz'] - ], """ + ], ''' - foo:\t bar - - baz - -\tbaz"""); + -\tbaz'''); }); }); group('6.3: Line Prefixes', () { test('[Example 6.4]', () { expectYamlLoads({ - "plain": "text lines", - "quoted": "text lines", - "block": "text\n \tlines\n" - }, """ + 'plain': 'text lines', + 'quoted': 'text lines', + 'block': 'text\n \tlines\n' + }, ''' plain: text lines quoted: "text @@ -741,29 +741,29 @@ main() { block: | text \tlines - """); + '''); }); }); group('6.4: Empty Lines', () { test('[Example 6.5]', () { expectYamlLoads({ - "Folding": "Empty line\nas a line feed", - "Chomping": "Clipped empty lines\n", - }, """ + 'Folding': 'Empty line\nas a line feed', + 'Chomping': 'Clipped empty lines\n', + }, ''' Folding: "Empty line \t as a line feed" Chomping: | Clipped empty lines - """); + '''); }); }); group('6.5: Line Folding', () { test('[Example 6.6]', () { - expectYamlLoads("trimmed\n\n\nas space", """ + expectYamlLoads('trimmed\n\n\nas space', ''' >- trimmed @@ -771,22 +771,22 @@ main() { as space - """); + '''); }); test('[Example 6.7]', () { - expectYamlLoads("foo \n\n\t bar\n\nbaz\n", """ + expectYamlLoads('foo \n\n\t bar\n\nbaz\n', ''' > foo \t bar baz - """); + '''); }); test('[Example 6.8]', () { - expectYamlLoads(" foo\nbar\nbaz ", ''' + expectYamlLoads(' foo\nbar\nbaz ', ''' " foo @@ -799,113 +799,113 @@ main() { group('6.6: Comments', () { test('must be separated from other tokens by white space characters', () { - expectYamlLoads("foo#bar", "foo#bar"); - expectYamlLoads("foo:#bar", "foo:#bar"); - expectYamlLoads("-#bar", "-#bar"); + expectYamlLoads('foo#bar', 'foo#bar'); + expectYamlLoads('foo:#bar', 'foo:#bar'); + expectYamlLoads('-#bar', '-#bar'); }); test('[Example 6.9]', () { - expectYamlLoads({'key': 'value'}, """ + expectYamlLoads({'key': 'value'}, ''' key: # Comment - value"""); + value'''); }); group('outside of scalar content', () { test('may appear on a line of their own', () { - expectYamlLoads([1, 2], """ + expectYamlLoads([1, 2], ''' - 1 # Comment - - 2"""); + - 2'''); }); test('are independent of indentation level', () { expectYamlLoads([ [1, 2] - ], """ + ], ''' - - 1 # Comment - - 2"""); + - 2'''); }); test('include lines containing only white space characters', () { - expectYamlLoads([1, 2], """ + expectYamlLoads([1, 2], ''' - 1 \t - - 2"""); + - 2'''); }); }); group('within scalar content', () { test('may not appear on a line of their own', () { - expectYamlLoads(["foo\n# not comment\nbar\n"], """ + expectYamlLoads(['foo\n# not comment\nbar\n'], ''' - | foo # not comment bar - """); + '''); }); test("don't include lines containing only white space characters", () { - expectYamlLoads(["foo\n \t \nbar\n"], """ + expectYamlLoads(['foo\n \t \nbar\n'], ''' - | foo \t bar - """); + '''); }); }); test('[Example 6.10]', () { - expectYamlLoads(null, """ + expectYamlLoads(null, ''' # Comment - """); + '''); }); test('[Example 6.11]', () { - expectYamlLoads({'key': 'value'}, """ + expectYamlLoads({'key': 'value'}, ''' key: # Comment # lines value - """); + '''); }); group('ending a block scalar header', () { test('may not be followed by additional comment lines', () { - expectYamlLoads(["# not comment\nfoo\n"], """ + expectYamlLoads(['# not comment\nfoo\n'], ''' - | # comment # not comment foo - """); + '''); }); }); }); group('6.7: Separation Lines', () { test('may not be used within implicit keys', () { - expectYamlFails(""" + expectYamlFails(''' [1, - 2]: 3"""); + 2]: 3'''); }); test('[Example 6.12]', () { var doc = deepEqualsMap(); doc[{'first': 'Sammy', 'last': 'Sosa'}] = {'hr': 65, 'avg': 0.278}; - expectYamlLoads(doc, """ + expectYamlLoads(doc, ''' { first: Sammy, last: Sosa }: # Statistics: hr: # Home runs 65 avg: # Average - 0.278"""); + 0.278'''); }); }); group('6.8: Directives', () { // TODO(nweiz): assert that this produces a warning test('[Example 6.13]', () { - expectYamlLoads("foo", ''' + expectYamlLoads('foo', ''' %FOO bar baz # Should be ignored # with a warning. --- "foo"'''); @@ -913,7 +913,7 @@ main() { // TODO(nweiz): assert that this produces a warning. test('[Example 6.14]', () { - expectYamlLoads("foo", ''' + expectYamlLoads('foo', ''' %YAML 1.3 # Attempt parsing # with a warning --- @@ -921,24 +921,24 @@ main() { }); test('[Example 6.15]', () { - expectYamlFails(""" + expectYamlFails(''' %YAML 1.2 %YAML 1.1 - foo"""); + foo'''); }); test('[Example 6.16]', () { - expectYamlLoads("foo", ''' + expectYamlLoads('foo', ''' %TAG !yaml! tag:yaml.org,2002: --- !yaml!str "foo"'''); }); test('[Example 6.17]', () { - expectYamlFails(""" + expectYamlFails(''' %TAG ! !foo %TAG ! !foo - bar"""); + bar'''); }); // Examples 6.18 through 6.22 test custom tag URIs, which this @@ -947,13 +947,13 @@ main() { group('6.9: Node Properties', () { test('may be specified in any order', () { - expectYamlLoads(["foo", "bar"], """ + expectYamlLoads(['foo', 'bar'], ''' - !!str &a1 foo - - &a2 !!str bar"""); + - &a2 !!str bar'''); }); test('[Example 6.23]', () { - expectYamlLoads({"foo": "bar", "baz": "foo"}, ''' + expectYamlLoads({'foo': 'bar', 'baz': 'foo'}, ''' !!str &a1 "foo": !!str bar &a2 baz : *a1'''); @@ -963,15 +963,15 @@ main() { // doesn't plan to support. test('[Example 6.25]', () { - expectYamlFails("- ! foo"); - expectYamlFails("- !<\$:?> foo"); + expectYamlFails('- ! foo'); + expectYamlFails('- !<\$:?> foo'); }); // Examples 6.26 and 6.27 test custom tag URIs, which this implementation // currently doesn't plan to support. test('[Example 6.28]', () { - expectYamlLoads(["12", 12, "12"], ''' + expectYamlLoads(['12', 12, '12'], ''' # Assuming conventional resolution: - "12" - 12 @@ -980,50 +980,50 @@ main() { test('[Example 6.29]', () { expectYamlLoads( - {"First occurrence": "Value", "Second occurrence": "Value"}, """ + {'First occurrence': 'Value', 'Second occurrence': 'Value'}, ''' First occurrence: &anchor Value - Second occurrence: *anchor"""); + Second occurrence: *anchor'''); }); }); // Chapter 7: Flow Styles group('7.1: Alias Nodes', () { test("must not use an anchor that doesn't previously occur", () { - expectYamlFails(""" + expectYamlFails(''' - *anchor - - &anchor foo"""); + - &anchor foo'''); }); test("don't have to exist for a given anchor node", () { - expectYamlLoads(["foo"], "- &anchor foo"); + expectYamlLoads(['foo'], '- &anchor foo'); }); group('must not specify', () { - test('tag properties', () => expectYamlFails(""" + test('tag properties', () => expectYamlFails(''' - &anchor foo - - !str *anchor""")); + - !str *anchor''')); - test('anchor properties', () => expectYamlFails(""" + test('anchor properties', () => expectYamlFails(''' - &anchor foo - - &anchor2 *anchor""")); + - &anchor2 *anchor''')); - test('content', () => expectYamlFails(""" + test('content', () => expectYamlFails(''' - &anchor foo - - *anchor bar""")); + - *anchor bar''')); }); test('must preserve structural equality', () { - var doc = loadYaml(cleanUpLiteral(""" + var doc = loadYaml(cleanUpLiteral(''' anchor: &anchor [a, b, c] - alias: *anchor""")); + alias: *anchor''')); var anchorList = doc['anchor']; var aliasList = doc['alias']; expect(anchorList, same(aliasList)); - doc = loadYaml(cleanUpLiteral(""" + doc = loadYaml(cleanUpLiteral(''' ? &anchor [a, b, c] : ? *anchor - : bar""")); + : bar''')); anchorList = doc.keys.first; aliasList = doc[['a', 'b', 'c']].keys.first; expect(anchorList, same(aliasList)); @@ -1031,43 +1031,43 @@ main() { test('[Example 7.1]', () { expectYamlLoads({ - "First occurrence": "Foo", - "Second occurrence": "Foo", - "Override anchor": "Bar", - "Reuse anchor": "Bar", - }, """ + 'First occurrence': 'Foo', + 'Second occurrence': 'Foo', + 'Override anchor': 'Bar', + 'Reuse anchor': 'Bar', + }, ''' First occurrence: &anchor Foo Second occurrence: *anchor Override anchor: &anchor Bar - Reuse anchor: *anchor"""); + Reuse anchor: *anchor'''); }); }); group('7.2: Empty Nodes', () { test('[Example 7.2]', () { - expectYamlLoads({"foo": "", "": "bar"}, """ + expectYamlLoads({'foo': '', '': 'bar'}, ''' { foo : !!str, !!str : bar, - }"""); + }'''); }); test('[Example 7.3]', () { - var doc = deepEqualsMap({"foo": null}); - doc[null] = "bar"; - expectYamlLoads(doc, """ + var doc = deepEqualsMap({'foo': null}); + doc[null] = 'bar'; + expectYamlLoads(doc, ''' { ? foo :, : bar, - }"""); + }'''); }); }); group('7.3: Flow Scalar Styles', () { test('[Example 7.4]', () { expectYamlLoads({ - "implicit block key": [ - {"implicit flow key": "value"} + 'implicit block key': [ + {'implicit flow key': 'value'} ] }, ''' "implicit block key" : [ @@ -1077,7 +1077,7 @@ main() { test('[Example 7.5]', () { expectYamlLoads( - "folded to a space,\nto a line feed, or \t \tnon-content", ''' + 'folded to a space,\nto a line feed, or \t \tnon-content', ''' "folded to a space,\t @@ -1086,7 +1086,7 @@ main() { }); test('[Example 7.6]', () { - expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", ''' + expectYamlLoads(' 1st non-empty\n2nd non-empty 3rd non-empty ', ''' " 1st non-empty 2nd non-empty @@ -1099,8 +1099,8 @@ main() { test('[Example 7.8]', () { expectYamlLoads({ - "implicit block key": [ - {"implicit flow key": "value"} + 'implicit block key': [ + {'implicit flow key': 'value'} ] }, """ 'implicit block key' : [ @@ -1109,7 +1109,7 @@ main() { }); test('[Example 7.9]', () { - expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", """ + expectYamlLoads(' 1st non-empty\n2nd non-empty 3rd non-empty ', """ ' 1st non-empty 2nd non-empty @@ -1118,17 +1118,17 @@ main() { test('[Example 7.10]', () { expectYamlLoads([ - "::vector", - ": - ()", - "Up, up, and away!", + '::vector', + ': - ()', + 'Up, up, and away!', -123, - "http://example.com/foo#bar", + 'http://example.com/foo#bar', [ - "::vector", - ": - ()", - "Up, up, and away!", + '::vector', + ': - ()', + 'Up, up, and away!', -123, - "http://example.com/foo#bar" + 'http://example.com/foo#bar' ] ], ''' # Outside flow collection: @@ -1147,21 +1147,21 @@ main() { test('[Example 7.11]', () { expectYamlLoads({ - "implicit block key": [ - {"implicit flow key": "value"} + 'implicit block key': [ + {'implicit flow key': 'value'} ] - }, """ + }, ''' implicit block key : [ implicit flow key : value, - ]"""); + ]'''); }); test('[Example 7.12]', () { - expectYamlLoads("1st non-empty\n2nd non-empty 3rd non-empty", """ + expectYamlLoads('1st non-empty\n2nd non-empty 3rd non-empty', ''' 1st non-empty 2nd non-empty - \t3rd non-empty"""); + \t3rd non-empty'''); }); }); @@ -1170,18 +1170,18 @@ main() { expectYamlLoads([ ['one', 'two'], ['three', 'four'] - ], """ + ], ''' - [ one, two, ] - - [three ,four]"""); + - [three ,four]'''); }); test('[Example 7.14]', () { expectYamlLoads([ - "double quoted", - "single quoted", - "plain text", - ["nested"], - {"single": "pair"} + 'double quoted', + 'single quoted', + 'plain text', + ['nested'], + {'single': 'pair'} ], """ [ "double @@ -1195,31 +1195,31 @@ main() { test('[Example 7.15]', () { expectYamlLoads([ - {"one": "two", "three": "four"}, - {"five": "six", "seven": "eight"}, - ], """ + {'one': 'two', 'three': 'four'}, + {'five': 'six', 'seven': 'eight'}, + ], ''' - { one : two , three: four , } - - {five: six,seven : eight}"""); + - {five: six,seven : eight}'''); }); test('[Example 7.16]', () { - var doc = deepEqualsMap({"explicit": "entry", "implicit": "entry"}); + var doc = deepEqualsMap({'explicit': 'entry', 'implicit': 'entry'}); doc[null] = null; - expectYamlLoads(doc, """ + expectYamlLoads(doc, ''' { ? explicit: entry, implicit: entry, ? - }"""); + }'''); }); test('[Example 7.17]', () { var doc = deepEqualsMap({ - "unquoted": "separate", - "http://foo.com": null, - "omitted value": null + 'unquoted': 'separate', + 'http://foo.com': null, + 'omitted value': null }); - doc[null] = "omitted key"; + doc[null] = 'omitted key'; expectYamlLoads(doc, ''' { unquoted : "separate", @@ -1231,7 +1231,7 @@ main() { test('[Example 7.18]', () { expectYamlLoads( - {"adjacent": "value", "readable": "value", "empty": null}, ''' + {'adjacent': 'value', 'readable': 'value', 'empty': null}, ''' { "adjacent":value, "readable": value, @@ -1241,40 +1241,40 @@ main() { test('[Example 7.19]', () { expectYamlLoads([ - {"foo": "bar"} - ], """ + {'foo': 'bar'} + ], ''' [ foo: bar - ]"""); + ]'''); }); test('[Example 7.20]', () { expectYamlLoads([ - {"foo bar": "baz"} - ], """ + {'foo bar': 'baz'} + ], ''' [ ? foo bar : baz - ]"""); + ]'''); }); test('[Example 7.21]', () { var el1 = deepEqualsMap(); - el1[null] = "empty key entry"; + el1[null] = 'empty key entry'; var el2 = deepEqualsMap(); - el2[{"JSON": "like"}] = "adjacent"; + el2[{'JSON': 'like'}] = 'adjacent'; expectYamlLoads([ [ - {"YAML": "separate"} + {'YAML': 'separate'} ], [el1], [el2] - ], """ + ], ''' - [ YAML : separate ] - [ : empty key entry ] - - [ {JSON: like}:adjacent ]"""); + - [ {JSON: like}:adjacent ]'''); }); // TODO(nweiz): enable this when we throw an error for long or multiline @@ -1294,33 +1294,33 @@ main() { group('7.5: Flow Nodes', () { test('[Example 7.23]', () { expectYamlLoads([ - ["a", "b"], - {"a": "b"}, - "a", - "b", - "c" - ], """ + ['a', 'b'], + {'a': 'b'}, + 'a', + 'b', + 'c' + ], ''' - [ a, b ] - { a: b } - - "a" + - 'a' - 'b' - - c"""); + - c'''); }); test('[Example 7.24]', () { - expectYamlLoads(["a", "b", "c", "c", ""], """ + expectYamlLoads(['a', 'b', 'c', 'c', ''], ''' - !!str "a" - 'b' - &anchor "c" - *anchor - - !!str"""); + - !!str'''); }); }); // Chapter 8: Block Styles group('8.1: Block Scalar Styles', () { test('[Example 8.1]', () { - expectYamlLoads(["literal\n", " folded\n", "keep\n\n", " strip"], """ + expectYamlLoads(['literal\n', ' folded\n', 'keep\n\n', ' strip'], ''' - | # Empty header literal - >1 # Indentation indicator @@ -1329,7 +1329,7 @@ main() { keep - >1- # Both indicators - strip"""); + strip'''); }); test('[Example 8.2]', () { @@ -1338,47 +1338,47 @@ main() { // confident that "\t\ndetected\n" is correct when parsed according to the // rest of the spec. expectYamlLoads( - ["detected\n", "\n\n# detected\n", " explicit\n", "\t\ndetected\n"], - """ + ['detected\n', '\n\n# detected\n', ' explicit\n', '\t\ndetected\n'], + ''' - | detected - > - - + + # detected - |1 explicit - > \t detected - """); + '''); }); test('[Example 8.3]', () { - expectYamlFails(""" + expectYamlFails(''' - | - text"""); + text'''); - expectYamlFails(""" + expectYamlFails(''' - > text - text"""); + text'''); - expectYamlFails(""" + expectYamlFails(''' - |2 - text"""); + text'''); }); test('[Example 8.4]', () { - expectYamlLoads({"strip": "text", "clip": "text\n", "keep": "text\n"}, """ + expectYamlLoads({'strip': 'text', 'clip': 'text\n', 'keep': 'text\n'}, ''' strip: |- text clip: | text keep: |+ text - """); + '''); }); test('[Example 8.5]', () { @@ -1386,7 +1386,7 @@ main() { // value, but as far as I can tell that's not how it's supposed to be // parsed according to the rest of the spec. expectYamlLoads( - {"strip": "# text", "clip": "# text\n", "keep": "# text\n\n"}, """ + {'strip': '# text', 'clip': '# text\n', 'keep': '# text\n\n'}, ''' # Strip # Comments: strip: |- @@ -1406,30 +1406,30 @@ main() { # Trail # comments. - """); + '''); }); test('[Example 8.6]', () { - expectYamlLoads({"strip": "", "clip": "", "keep": "\n"}, """ + expectYamlLoads({'strip': '', 'clip': '', 'keep': '\n'}, ''' strip: >- clip: > keep: |+ - """); + '''); }); test('[Example 8.7]', () { - expectYamlLoads("literal\n\ttext\n", """ + expectYamlLoads('literal\n\ttext\n', ''' | literal \ttext - """); + '''); }); test('[Example 8.8]', () { - expectYamlLoads("\n\nliteral\n \n\ntext\n", """ + expectYamlLoads('\n\nliteral\n \n\ntext\n', ''' | @@ -1438,19 +1438,19 @@ main() { text - # Comment"""); + # Comment'''); }); test('[Example 8.9]', () { - expectYamlLoads("folded text\n", """ + expectYamlLoads('folded text\n', ''' > folded text - """); + '''); }); test('[Example 8.10]', () { - expectYamlLoads(cleanUpLiteral(""" + expectYamlLoads(cleanUpLiteral(''' folded line next line @@ -1460,7 +1460,7 @@ main() { * lines last line - """), """ + '''), ''' > folded @@ -1476,7 +1476,7 @@ main() { last line - # Comment"""); + # Comment'''); }); // Examples 8.11 through 8.13 are duplicates of 8.10. @@ -1485,55 +1485,55 @@ main() { group('8.2: Block Collection Styles', () { test('[Example 8.14]', () { expectYamlLoads({ - "block sequence": [ - "one", - {"two": "three"} + 'block sequence': [ + 'one', + {'two': 'three'} ] - }, """ + }, ''' block sequence: - one - - two : three"""); + - two : three'''); }); test('[Example 8.15]', () { expectYamlLoads([ null, - "block node\n", - ["one", "two"], - {"one": "two"} - ], """ + 'block node\n', + ['one', 'two'], + {'one': 'two'} + ], ''' - # Empty - | block node - - one # Compact - two # sequence - - one: two # Compact mapping"""); + - one: two # Compact mapping'''); }); test('[Example 8.16]', () { expectYamlLoads({ - "block mapping": {"key": "value"} - }, """ + 'block mapping': {'key': 'value'} + }, ''' block mapping: - key: value"""); + key: value'''); }); test('[Example 8.17]', () { expectYamlLoads({ - "explicit key": null, - "block key\n": ["one", "two"] - }, """ + 'explicit key': null, + 'block key\n': ['one', 'two'] + }, ''' ? explicit key # Empty value ? | block key : - one # Explicit compact - - two # block value"""); + - two # block value'''); }); test('[Example 8.18]', () { var doc = deepEqualsMap({ 'plain key': 'in-line value', - "quoted key": ["entry"] + 'quoted key': ['entry'] }); doc[null] = null; expectYamlLoads(doc, ''' @@ -1549,17 +1549,17 @@ main() { expectYamlLoads([ {'sun': 'yellow'}, el - ], """ + ], ''' - sun: yellow - ? earth: blue - : moon: white"""); + : moon: white'''); }); test('[Example 8.20]', () { expectYamlLoads([ - "flow in block", - "Block scalar\n", - {"foo": "bar"} + 'flow in block', + 'Block scalar\n', + {'foo': 'bar'} ], ''' - "flow in block" @@ -1572,29 +1572,29 @@ main() { test('[Example 8.21]', () { // The spec doesn't include a newline after "value" in the parsed map, but // the block scalar is clipped so it should be retained. - expectYamlLoads({"literal": "value\n", "folded": "value"}, """ + expectYamlLoads({'literal': 'value\n', 'folded': 'value'}, ''' literal: |2 value folded: !!str >1 - value"""); + value'''); }); test('[Example 8.22]', () { expectYamlLoads({ - "sequence": [ - "entry", - ["nested"] + 'sequence': [ + 'entry', + ['nested'] ], - "mapping": {"foo": "bar"} - }, """ + 'mapping': {'foo': 'bar'} + }, ''' sequence: !!seq - entry - !!seq - nested mapping: !!map - foo: bar"""); + foo: bar'''); }); }); @@ -1604,11 +1604,11 @@ main() { // doesn't plan to support. test('[Example 9.2]', () { - expectYamlLoads("Document", """ + expectYamlLoads('Document', ''' %YAML 1.2 --- Document - ... # Suffix"""); + ... # Suffix'''); }); test('[Example 9.3]', () { @@ -1620,7 +1620,7 @@ main() { // indented the same amount, the text would be part of the literal, which // implies that the spec's parse of this document is incorrect. expectYamlStreamLoads( - ["Bare document", "%!PS-Adobe-2.0 # Not the first line\n"], """ + ['Bare document', '%!PS-Adobe-2.0 # Not the first line\n'], ''' Bare document ... @@ -1628,27 +1628,27 @@ main() { ... | %!PS-Adobe-2.0 # Not the first line - """); + '''); }); test('[Example 9.4]', () { expectYamlStreamLoads([ - {"matches %": 20}, + {'matches %': 20}, null - ], """ + ], ''' --- { matches % : 20 } ... --- # Empty - ..."""); + ...'''); }); test('[Example 9.5]', () { // The spec doesn't have a space between the second // "YAML" and "1.2", but this seems to be a typo. - expectYamlStreamLoads(["%!PS-Adobe-2.0\n", null], """ + expectYamlStreamLoads(['%!PS-Adobe-2.0\n', null], ''' %YAML 1.2 --- | %!PS-Adobe-2.0 @@ -1656,22 +1656,22 @@ main() { %YAML 1.2 --- # Empty - ..."""); + ...'''); }); test('[Example 9.6]', () { expectYamlStreamLoads([ - "Document", + 'Document', null, - {"matches %": 20} - ], """ + {'matches %': 20} + ], ''' Document --- # Empty ... %YAML 1.2 --- - matches %: 20"""); + matches %: 20'''); }); }); @@ -1679,38 +1679,38 @@ main() { group('10.1: Failsafe Schema', () { test('[Example 10.1]', () { expectYamlLoads({ - "Block style": { - "Clark": "Evans", - "Ingy": "döt Net", - "Oren": "Ben-Kiki" + 'Block style': { + 'Clark': 'Evans', + 'Ingy': 'döt Net', + 'Oren': 'Ben-Kiki' }, - "Flow style": {"Clark": "Evans", "Ingy": "döt Net", "Oren": "Ben-Kiki"} - }, """ + 'Flow style': {'Clark': 'Evans', 'Ingy': 'döt Net', 'Oren': 'Ben-Kiki'} + }, ''' Block style: !!map Clark : Evans Ingy : döt Net Oren : Ben-Kiki - Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }"""); + Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }'''); }); test('[Example 10.2]', () { expectYamlLoads({ - "Block style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"], - "Flow style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"] - }, """ + 'Block style': ['Clark Evans', 'Ingy döt Net', 'Oren Ben-Kiki'], + 'Flow style': ['Clark Evans', 'Ingy döt Net', 'Oren Ben-Kiki'] + }, ''' Block style: !!seq - Clark Evans - Ingy döt Net - Oren Ben-Kiki - Flow style: !!seq [ Clark Evans, Ingy döt Net, Oren Ben-Kiki ]"""); + Flow style: !!seq [ Clark Evans, Ingy döt Net, Oren Ben-Kiki ]'''); }); test('[Example 10.3]', () { expectYamlLoads({ - "Block style": "String: just a theory.", - "Flow style": "String: just a theory." + 'Block style': 'String: just a theory.', + 'Flow style': 'String: just a theory.' }, ''' Block style: !!str |- String: just a theory. @@ -1789,13 +1789,13 @@ main() { group('10.3: Core Schema', () { test('[Example 10.9]', () { expectYamlLoads({ - "A null": null, - "Also a null": null, - "Not a null": "", - "Booleans": [true, true, false, false], - "Integers": [0, 7, 0x3A, -19], - "Floats": [0, 0, 0.5, 12000, -200000], - "Also floats": [infinity, -infinity, infinity, nan] + 'A null': null, + 'Also a null': null, + 'Not a null': '', + 'Booleans': [true, true, false, false], + 'Integers': [0, 7, 0x3A, -19], + 'Floats': [0, 0, 0.5, 12000, -200000], + 'Also floats': [infinity, -infinity, infinity, nan] }, ''' A null: null Also a null: # Empty @@ -1809,8 +1809,8 @@ main() { test('preserves key order', () { const keys = ['a', 'b', 'c', 'd', 'e', 'f']; - int sanityCheckCount = 0; - for (List permutation in _generatePermutations(keys)) { + var sanityCheckCount = 0; + for (var permutation in _generatePermutations(keys)) { final yaml = permutation.map((key) => '$key: value').join('\n'); expect(loadYaml(yaml).keys.toList(), permutation); sanityCheckCount++; @@ -1826,13 +1826,11 @@ Iterable> _generatePermutations(List keys) sync* { yield keys; return; } - for (int i = 0; i < keys.length; i++) { + for (var i = 0; i < keys.length; i++) { final first = keys[i]; - final rest = [] - ..addAll(keys.sublist(0, i)) - ..addAll(keys.sublist(i + 1)); - for (List subPermutation in _generatePermutations(rest)) { - yield [first]..addAll(subPermutation); + final rest = [...keys.sublist(0, i), ...keys.sublist(i + 1)]; + for (var subPermutation in _generatePermutations(rest)) { + yield [first, ...subPermutation]; } } } From f80f10232a169db22dd73034718d4aef09640b54 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 13 Jan 2020 11:55:56 -0800 Subject: [PATCH 096/179] Update min SDK to 2.4 (dart-lang/yaml#59) Related to https://github.com/dart-lang/test/issues/1141 --- pkgs/yaml/.travis.yml | 2 +- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml index 78ba59000..a25a59e25 100644 --- a/pkgs/yaml/.travis.yml +++ b/pkgs/yaml/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: - - 2.3.0 + - 2.4.0 - dev dart_task: diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index bc0cb78db..258fb625e 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.2.1 + +* Update min Dart SDK to `2.4.0`. + ## 2.2.0 * POSSIBLY BREAKING CHANGE: Make `YamlMap` preserve parsed key order. diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index d83ad8ac7..68f6537ce 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -6,7 +6,7 @@ author: Dart Team homepage: https://github.com/dart-lang/yaml environment: - sdk: '>=2.3.0 <3.0.0' + sdk: '>=2.4.0 <3.0.0' dependencies: charcode: ^1.1.0 From dbe2944e56bf466feb3e612d57c6c69d56652f8b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 17 Jan 2020 15:38:38 -0800 Subject: [PATCH 097/179] remove unused field from private class (dart-lang/yaml#60) --- pkgs/yaml/lib/src/parser.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 4beb1de00..fd24f886f 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -712,9 +712,6 @@ class _State { /// Expect [TokenType.STREAM_START]. static const STREAM_START = _State('STREAM_START'); - /// Expect the beginning of an implicit document. - static const IMPLICIT_DOCUMENT_START = _State('IMPLICIT_DOCUMENT_START'); - /// Expect [TokenType.DOCUMENT_START]. static const DOCUMENT_START = _State('DOCUMENT_START'); From 74991ba27a28c6cea7d8d7d61c10abec90a2a77d Mon Sep 17 00:00:00 2001 From: Ayan Banerjee Date: Mon, 24 Feb 2020 21:30:10 +0530 Subject: [PATCH 098/179] [doc] Add an example.dart file (dart-lang/yaml#64) Pana suggests to add an example.dart file here: https://pub.dev/packages/yaml#-analysis-tab- Closes https://github.com/dart-lang/yaml/issues/45 --- pkgs/yaml/example/example.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 pkgs/yaml/example/example.dart diff --git a/pkgs/yaml/example/example.dart b/pkgs/yaml/example/example.dart new file mode 100644 index 000000000..102d5b193 --- /dev/null +++ b/pkgs/yaml/example/example.dart @@ -0,0 +1,10 @@ +// Copyright (c) 2020, 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. + +import 'package:yaml/yaml.dart'; + +void main() { + var doc = loadYaml("YAML: YAML Ain't Markup Language"); + print(doc['YAML']); +} From 6ec8be0194a53b082b260a0871f31ca1b50d358d Mon Sep 17 00:00:00 2001 From: Sahil Bondre Date: Tue, 25 Feb 2020 13:39:09 -0800 Subject: [PATCH 099/179] Refactor to real enums (dart-lang/yaml#62) --- pkgs/yaml/lib/src/event.dart | 33 ++++++------------ pkgs/yaml/lib/src/scanner.dart | 15 +++------ pkgs/yaml/lib/src/token.dart | 61 +++++++++++++++------------------- 3 files changed, 42 insertions(+), 67 deletions(-) diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart index 733e39d6f..31625f801 100644 --- a/pkgs/yaml/lib/src/event.dart +++ b/pkgs/yaml/lib/src/event.dart @@ -157,26 +157,15 @@ class MappingStartEvent extends _ValueEvent { } /// An enum of types of [Event] object. -class EventType { - static const STREAM_START = EventType._('STREAM_START'); - static const STREAM_END = EventType._('STREAM_END'); - - static const DOCUMENT_START = EventType._('DOCUMENT_START'); - static const DOCUMENT_END = EventType._('DOCUMENT_END'); - - static const ALIAS = EventType._('ALIAS'); - static const SCALAR = EventType._('SCALAR'); - - static const SEQUENCE_START = EventType._('SEQUENCE_START'); - static const SEQUENCE_END = EventType._('SEQUENCE_END'); - - static const MAPPING_START = EventType._('MAPPING_START'); - static const MAPPING_END = EventType._('MAPPING_END'); - - final String name; - - const EventType._(this.name); - - @override - String toString() => name; +enum EventType { + STREAM_START, + STREAM_END, + DOCUMENT_START, + DOCUMENT_END, + ALIAS, + SCALAR, + SEQUENCE_START, + SEQUENCE_END, + MAPPING_START, + MAPPING_END } diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 66d9d8b8d..2e499437b 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -1666,20 +1666,13 @@ class _SimpleKey { /// whitespace for a block scalar. /// /// See http://yaml.org/spec/1.2/spec.html#id2794534. -class _Chomping { +enum _Chomping { /// All trailing whitespace is discarded. - static const STRIP = _Chomping('STRIP'); + STRIP, /// A single trailing newline is retained. - static const CLIP = _Chomping('CLIP'); + CLIP, /// All trailing whitespace is preserved. - static const KEEP = _Chomping('KEEP'); - - final String name; - - const _Chomping(this.name); - - @override - String toString() => name; + KEEP } diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 7381a7dfe..9051d683d 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -129,38 +129,31 @@ class ScalarToken implements Token { } /// An enum of types of [Token] object. -class TokenType { - static const STREAM_START = TokenType._('STREAM_START'); - static const STREAM_END = TokenType._('STREAM_END'); - - static const VERSION_DIRECTIVE = TokenType._('VERSION_DIRECTIVE'); - static const TAG_DIRECTIVE = TokenType._('TAG_DIRECTIVE'); - static const DOCUMENT_START = TokenType._('DOCUMENT_START'); - static const DOCUMENT_END = TokenType._('DOCUMENT_END'); - - static const BLOCK_SEQUENCE_START = TokenType._('BLOCK_SEQUENCE_START'); - static const BLOCK_MAPPING_START = TokenType._('BLOCK_MAPPING_START'); - static const BLOCK_END = TokenType._('BLOCK_END'); - - static const FLOW_SEQUENCE_START = TokenType._('FLOW_SEQUENCE_START'); - static const FLOW_SEQUENCE_END = TokenType._('FLOW_SEQUENCE_END'); - static const FLOW_MAPPING_START = TokenType._('FLOW_MAPPING_START'); - static const FLOW_MAPPING_END = TokenType._('FLOW_MAPPING_END'); - - static const BLOCK_ENTRY = TokenType._('BLOCK_ENTRY'); - static const FLOW_ENTRY = TokenType._('FLOW_ENTRY'); - static const KEY = TokenType._('KEY'); - static const VALUE = TokenType._('VALUE'); - - static const ALIAS = TokenType._('ALIAS'); - static const ANCHOR = TokenType._('ANCHOR'); - static const TAG = TokenType._('TAG'); - static const SCALAR = TokenType._('SCALAR'); - - final String name; - - const TokenType._(this.name); - - @override - String toString() => name; +enum TokenType { + STREAM_START, + STREAM_END, + + VERSION_DIRECTIVE, + TAG_DIRECTIVE, + DOCUMENT_START, + DOCUMENT_END, + + BLOCK_SEQUENCE_START, + BLOCK_MAPPING_START, + BLOCK_END, + + FLOW_SEQUENCE_START, + FLOW_SEQUENCE_END, + FLOW_MAPPING_START, + FLOW_MAPPING_END, + + BLOCK_ENTRY, + FLOW_ENTRY, + KEY, + VALUE, + + ALIAS, + ANCHOR, + TAG, + SCALAR } From c17877f18ffd42e827af5b443f8dd41684cc0fae Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 26 Feb 2020 11:11:39 -0800 Subject: [PATCH 100/179] Use camelcase for enums (dart-lang/yaml#65) - Rename non-public enums to use camel case. - Rephrase some doc comments to use modern style. - Remove some doc comments that add no new information. --- pkgs/yaml/lib/src/event.dart | 42 +++++----- pkgs/yaml/lib/src/loader.dart | 18 ++--- pkgs/yaml/lib/src/parser.dart | 142 ++++++++++++++++----------------- pkgs/yaml/lib/src/scanner.dart | 119 ++++++++++++++------------- pkgs/yaml/lib/src/token.dart | 77 +++++++++--------- 5 files changed, 194 insertions(+), 204 deletions(-) diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart index 31625f801..c4f6a6ddb 100644 --- a/pkgs/yaml/lib/src/event.dart +++ b/pkgs/yaml/lib/src/event.dart @@ -9,10 +9,7 @@ import 'yaml_document.dart'; /// An event emitted by a [Parser]. class Event { - /// The event type. final EventType type; - - /// The span associated with the event. final FileSpan span; Event(this.type, this.span); @@ -24,7 +21,7 @@ class Event { /// An event indicating the beginning of a YAML document. class DocumentStartEvent implements Event { @override - EventType get type => EventType.DOCUMENT_START; + EventType get type => EventType.documentStart; @override final FileSpan span; @@ -51,7 +48,7 @@ class DocumentStartEvent implements Event { /// An event indicating the end of a YAML document. class DocumentEndEvent implements Event { @override - EventType get type => EventType.DOCUMENT_END; + EventType get type => EventType.documentEnd; @override final FileSpan span; @@ -68,11 +65,11 @@ class DocumentEndEvent implements Event { /// An event indicating that an alias was referenced. class AliasEvent implements Event { @override - EventType get type => EventType.ALIAS; + EventType get type => EventType.alias; @override final FileSpan span; - /// The name of the anchor. + /// The alias name. final String name; AliasEvent(this.span, this.name); @@ -81,8 +78,7 @@ class AliasEvent implements Event { String toString() => 'ALIAS $name'; } -/// A base class for events that can have anchor and tag properties associated -/// with them. +/// An event that can have associated anchor and tag properties. abstract class _ValueEvent implements Event { /// The name of the value's anchor, or `null` if it wasn't anchored. String get anchor; @@ -102,7 +98,7 @@ abstract class _ValueEvent implements Event { /// An event indicating a single scalar value. class ScalarEvent extends _ValueEvent { @override - EventType get type => EventType.SCALAR; + EventType get type => EventType.scalar; @override final FileSpan span; @override @@ -125,7 +121,7 @@ class ScalarEvent extends _ValueEvent { /// An event indicating the beginning of a sequence. class SequenceStartEvent extends _ValueEvent { @override - EventType get type => EventType.SEQUENCE_START; + EventType get type => EventType.sequenceStart; @override final FileSpan span; @override @@ -142,7 +138,7 @@ class SequenceStartEvent extends _ValueEvent { /// An event indicating the beginning of a mapping. class MappingStartEvent extends _ValueEvent { @override - EventType get type => EventType.MAPPING_START; + EventType get type => EventType.mappingStart; @override final FileSpan span; @override @@ -156,16 +152,16 @@ class MappingStartEvent extends _ValueEvent { MappingStartEvent(this.span, this.style, {this.anchor, this.tag}); } -/// An enum of types of [Event] object. +/// The types of [Event] objects. enum EventType { - STREAM_START, - STREAM_END, - DOCUMENT_START, - DOCUMENT_END, - ALIAS, - SCALAR, - SEQUENCE_START, - SEQUENCE_END, - MAPPING_START, - MAPPING_END + streamStart, + streamEnd, + documentStart, + documentEnd, + alias, + scalar, + sequenceStart, + sequenceEnd, + mappingStart, + mappingEnd } diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 08b254435..54172b538 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -36,7 +36,7 @@ class Loader { : _parser = Parser(source, sourceUrl: sourceUrl) { var event = _parser.parse(); _span = event.span; - assert(event.type == EventType.STREAM_START); + assert(event.type == EventType.streamStart); } /// Loads the next document from the stream. @@ -46,7 +46,7 @@ class Loader { if (_parser.isDone) return null; var event = _parser.parse(); - if (event.type == EventType.STREAM_END) { + if (event.type == EventType.streamEnd) { _span = _span.expand(event.span); return null; } @@ -62,7 +62,7 @@ class Loader { var contents = _loadNode(_parser.parse()); var lastEvent = _parser.parse() as DocumentEndEvent; - assert(lastEvent.type == EventType.DOCUMENT_END); + assert(lastEvent.type == EventType.documentEnd); return YamlDocument.internal( contents, @@ -76,13 +76,13 @@ class Loader { /// Composes a node. YamlNode _loadNode(Event firstEvent) { switch (firstEvent.type) { - case EventType.ALIAS: + case EventType.alias: return _loadAlias(firstEvent as AliasEvent); - case EventType.SCALAR: + case EventType.scalar: return _loadScalar(firstEvent as ScalarEvent); - case EventType.SEQUENCE_START: + case EventType.sequenceStart: return _loadSequence(firstEvent as SequenceStartEvent); - case EventType.MAPPING_START: + case EventType.mappingStart: return _loadMapping(firstEvent as MappingStartEvent); default: throw 'Unreachable'; @@ -136,7 +136,7 @@ class Loader { _registerAnchor(firstEvent.anchor, node); var event = _parser.parse(); - while (event.type != EventType.SEQUENCE_END) { + while (event.type != EventType.sequenceEnd) { children.add(_loadNode(event)); event = _parser.parse(); } @@ -158,7 +158,7 @@ class Loader { _registerAnchor(firstEvent.anchor, node); var event = _parser.parse(); - while (event.type != EventType.MAPPING_END) { + while (event.type != EventType.mappingEnd) { var key = _loadNode(event); var value = _loadNode(_parser.parse()); if (children.containsKey(key)) { diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index fd24f886f..3eba773f6 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -116,10 +116,10 @@ class Parser { /// ************ Event _parseStreamStart() { var token = _scanner.scan(); - assert(token.type == TokenType.STREAM_START); + assert(token.type == TokenType.streamStart); _state = _State.DOCUMENT_START; - return Event(EventType.STREAM_START, token.span); + return Event(EventType.streamStart, token.span); } /// Parses the productions: @@ -137,14 +137,14 @@ class Parser { // as long as there was an end indicator. // Parse extra document end indicators. - while (token.type == TokenType.DOCUMENT_END) { + while (token.type == TokenType.documentEnd) { token = _scanner.advance(); } - if (token.type != TokenType.VERSION_DIRECTIVE && - token.type != TokenType.TAG_DIRECTIVE && - token.type != TokenType.DOCUMENT_START && - token.type != TokenType.STREAM_END) { + if (token.type != TokenType.versionDirective && + token.type != TokenType.tagDirective && + token.type != TokenType.documentStart && + token.type != TokenType.streamEnd) { // Parse an implicit document. _processDirectives(); _states.add(_State.DOCUMENT_END); @@ -152,10 +152,10 @@ class Parser { return DocumentStartEvent(token.span.start.pointSpan()); } - if (token.type == TokenType.STREAM_END) { + if (token.type == TokenType.streamEnd) { _state = _State.END; _scanner.scan(); - return Event(EventType.STREAM_END, token.span); + return Event(EventType.streamEnd, token.span); } // Parse an explicit document. @@ -164,7 +164,7 @@ class Parser { var versionDirective = pair.first; var tagDirectives = pair.last; token = _scanner.peek(); - if (token.type != TokenType.DOCUMENT_START) { + if (token.type != TokenType.documentStart) { throw YamlException('Expected document start.', token.span); } @@ -186,11 +186,11 @@ class Parser { var token = _scanner.peek(); switch (token.type) { - case TokenType.VERSION_DIRECTIVE: - case TokenType.TAG_DIRECTIVE: - case TokenType.DOCUMENT_START: - case TokenType.DOCUMENT_END: - case TokenType.STREAM_END: + case TokenType.versionDirective: + case TokenType.tagDirective: + case TokenType.documentStart: + case TokenType.documentEnd: + case TokenType.streamEnd: _state = _states.removeLast(); return _processEmptyScalar(token.span.start); default: @@ -210,7 +210,7 @@ class Parser { _state = _State.DOCUMENT_START; var token = _scanner.peek(); - if (token.type == TokenType.DOCUMENT_END) { + if (token.type == TokenType.documentEnd) { _scanner.scan(); return DocumentEndEvent(token.span, isImplicit: false); } else { @@ -291,7 +291,7 @@ class Parser { } } - if (indentlessSequence && token.type == TokenType.BLOCK_ENTRY) { + if (indentlessSequence && token.type == TokenType.blockEntry) { _state = _State.INDENTLESS_SEQUENCE_ENTRY; return SequenceStartEvent(span.expand(token.span), CollectionStyle.BLOCK, anchor: anchor, tag: tag); @@ -307,25 +307,25 @@ class Parser { anchor: anchor, tag: tag); } - if (token.type == TokenType.FLOW_SEQUENCE_START) { + if (token.type == TokenType.flowSequenceStart) { _state = _State.FLOW_SEQUENCE_FIRST_ENTRY; return SequenceStartEvent(span.expand(token.span), CollectionStyle.FLOW, anchor: anchor, tag: tag); } - if (token.type == TokenType.FLOW_MAPPING_START) { + if (token.type == TokenType.flowMappingStart) { _state = _State.FLOW_MAPPING_FIRST_KEY; return MappingStartEvent(span.expand(token.span), CollectionStyle.FLOW, anchor: anchor, tag: tag); } - if (block && token.type == TokenType.BLOCK_SEQUENCE_START) { + if (block && token.type == TokenType.blockSequenceStart) { _state = _State.BLOCK_SEQUENCE_FIRST_ENTRY; return SequenceStartEvent(span.expand(token.span), CollectionStyle.BLOCK, anchor: anchor, tag: tag); } - if (block && token.type == TokenType.BLOCK_MAPPING_START) { + if (block && token.type == TokenType.blockMappingStart) { _state = _State.BLOCK_MAPPING_FIRST_KEY; return MappingStartEvent(span.expand(token.span), CollectionStyle.BLOCK, anchor: anchor, tag: tag); @@ -347,11 +347,11 @@ class Parser { Event _parseBlockSequenceEntry() { var token = _scanner.peek(); - if (token.type == TokenType.BLOCK_ENTRY) { + if (token.type == TokenType.blockEntry) { token = _scanner.advance(); - if (token.type == TokenType.BLOCK_ENTRY || - token.type == TokenType.BLOCK_END) { + if (token.type == TokenType.blockEntry || + token.type == TokenType.blockEnd) { _state = _State.BLOCK_SEQUENCE_ENTRY; return _processEmptyScalar(token.span.end); } else { @@ -360,10 +360,10 @@ class Parser { } } - if (token.type == TokenType.BLOCK_END) { + if (token.type == TokenType.blockEnd) { _scanner.scan(); _state = _states.removeLast(); - return Event(EventType.SEQUENCE_END, token.span); + return Event(EventType.sequenceEnd, token.span); } throw YamlException("While parsing a block collection, expected '-'.", @@ -377,18 +377,18 @@ class Parser { Event _parseIndentlessSequenceEntry() { var token = _scanner.peek(); - if (token.type != TokenType.BLOCK_ENTRY) { + if (token.type != TokenType.blockEntry) { _state = _states.removeLast(); - return Event(EventType.SEQUENCE_END, token.span.start.pointSpan()); + return Event(EventType.sequenceEnd, token.span.start.pointSpan()); } var start = token.span.start; token = _scanner.advance(); - if (token.type == TokenType.BLOCK_ENTRY || - token.type == TokenType.KEY || - token.type == TokenType.VALUE || - token.type == TokenType.BLOCK_END) { + if (token.type == TokenType.blockEntry || + token.type == TokenType.key || + token.type == TokenType.value || + token.type == TokenType.blockEnd) { _state = _State.INDENTLESS_SEQUENCE_ENTRY; return _processEmptyScalar(start); } else { @@ -409,13 +409,13 @@ class Parser { /// ********* Event _parseBlockMappingKey() { var token = _scanner.peek(); - if (token.type == TokenType.KEY) { + if (token.type == TokenType.key) { var start = token.span.start; token = _scanner.advance(); - if (token.type == TokenType.KEY || - token.type == TokenType.VALUE || - token.type == TokenType.BLOCK_END) { + if (token.type == TokenType.key || + token.type == TokenType.value || + token.type == TokenType.blockEnd) { _state = _State.BLOCK_MAPPING_VALUE; return _processEmptyScalar(start); } else { @@ -427,15 +427,15 @@ class Parser { // libyaml doesn't allow empty keys without an explicit key indicator, but // the spec does. See example 8.18: // http://yaml.org/spec/1.2/spec.html#id2798896. - if (token.type == TokenType.VALUE) { + if (token.type == TokenType.value) { _state = _State.BLOCK_MAPPING_VALUE; return _processEmptyScalar(token.span.start); } - if (token.type == TokenType.BLOCK_END) { + if (token.type == TokenType.blockEnd) { _scanner.scan(); _state = _states.removeLast(); - return Event(EventType.MAPPING_END, token.span); + return Event(EventType.mappingEnd, token.span); } throw YamlException('Expected a key while parsing a block mapping.', @@ -455,16 +455,16 @@ class Parser { Event _parseBlockMappingValue() { var token = _scanner.peek(); - if (token.type != TokenType.VALUE) { + if (token.type != TokenType.value) { _state = _State.BLOCK_MAPPING_KEY; return _processEmptyScalar(token.span.start); } var start = token.span.start; token = _scanner.advance(); - if (token.type == TokenType.KEY || - token.type == TokenType.VALUE || - token.type == TokenType.BLOCK_END) { + if (token.type == TokenType.key || + token.type == TokenType.value || + token.type == TokenType.blockEnd) { _state = _State.BLOCK_MAPPING_KEY; return _processEmptyScalar(start); } else { @@ -490,9 +490,9 @@ class Parser { if (first) _scanner.scan(); var token = _scanner.peek(); - if (token.type != TokenType.FLOW_SEQUENCE_END) { + if (token.type != TokenType.flowSequenceEnd) { if (!first) { - if (token.type != TokenType.FLOW_ENTRY) { + if (token.type != TokenType.flowEntry) { throw YamlException( "While parsing a flow sequence, expected ',' or ']'.", token.span.start.pointSpan()); @@ -501,11 +501,11 @@ class Parser { token = _scanner.advance(); } - if (token.type == TokenType.KEY) { + if (token.type == TokenType.key) { _state = _State.FLOW_SEQUENCE_ENTRY_MAPPING_KEY; _scanner.scan(); return MappingStartEvent(token.span, CollectionStyle.FLOW); - } else if (token.type != TokenType.FLOW_SEQUENCE_END) { + } else if (token.type != TokenType.flowSequenceEnd) { _states.add(_State.FLOW_SEQUENCE_ENTRY); return _parseNode(); } @@ -513,7 +513,7 @@ class Parser { _scanner.scan(); _state = _states.removeLast(); - return Event(EventType.SEQUENCE_END, token.span); + return Event(EventType.sequenceEnd, token.span); } /// Parses the productions: @@ -524,9 +524,9 @@ class Parser { Event _parseFlowSequenceEntryMappingKey() { var token = _scanner.peek(); - if (token.type == TokenType.VALUE || - token.type == TokenType.FLOW_ENTRY || - token.type == TokenType.FLOW_SEQUENCE_END) { + if (token.type == TokenType.value || + token.type == TokenType.flowEntry || + token.type == TokenType.flowSequenceEnd) { // libyaml consumes the token here, but that seems like a bug, since it // always causes [_parseFlowSequenceEntryMappingValue] to emit an empty // scalar. @@ -548,10 +548,10 @@ class Parser { Event _parseFlowSequenceEntryMappingValue() { var token = _scanner.peek(); - if (token.type == TokenType.VALUE) { + if (token.type == TokenType.value) { token = _scanner.advance(); - if (token.type != TokenType.FLOW_ENTRY && - token.type != TokenType.FLOW_SEQUENCE_END) { + if (token.type != TokenType.flowEntry && + token.type != TokenType.flowSequenceEnd) { _states.add(_State.FLOW_SEQUENCE_ENTRY_MAPPING_END); return _parseNode(); } @@ -568,7 +568,7 @@ class Parser { /// * Event _parseFlowSequenceEntryMappingEnd() { _state = _State.FLOW_SEQUENCE_ENTRY; - return Event(EventType.MAPPING_END, _scanner.peek().span.start.pointSpan()); + return Event(EventType.mappingEnd, _scanner.peek().span.start.pointSpan()); } /// Parses the productions: @@ -588,9 +588,9 @@ class Parser { if (first) _scanner.scan(); var token = _scanner.peek(); - if (token.type != TokenType.FLOW_MAPPING_END) { + if (token.type != TokenType.flowMappingEnd) { if (!first) { - if (token.type != TokenType.FLOW_ENTRY) { + if (token.type != TokenType.flowEntry) { throw YamlException( "While parsing a flow mapping, expected ',' or '}'.", token.span.start.pointSpan()); @@ -599,18 +599,18 @@ class Parser { token = _scanner.advance(); } - if (token.type == TokenType.KEY) { + if (token.type == TokenType.key) { token = _scanner.advance(); - if (token.type != TokenType.VALUE && - token.type != TokenType.FLOW_ENTRY && - token.type != TokenType.FLOW_MAPPING_END) { + if (token.type != TokenType.value && + token.type != TokenType.flowEntry && + token.type != TokenType.flowMappingEnd) { _states.add(_State.FLOW_MAPPING_VALUE); return _parseNode(); } else { _state = _State.FLOW_MAPPING_VALUE; return _processEmptyScalar(token.span.start); } - } else if (token.type != TokenType.FLOW_MAPPING_END) { + } else if (token.type != TokenType.flowMappingEnd) { _states.add(_State.FLOW_MAPPING_EMPTY_VALUE); return _parseNode(); } @@ -618,7 +618,7 @@ class Parser { _scanner.scan(); _state = _states.removeLast(); - return Event(EventType.MAPPING_END, token.span); + return Event(EventType.mappingEnd, token.span); } /// Parses the productions: @@ -634,10 +634,10 @@ class Parser { return _processEmptyScalar(token.span.start); } - if (token.type == TokenType.VALUE) { + if (token.type == TokenType.value) { token = _scanner.advance(); - if (token.type != TokenType.FLOW_ENTRY && - token.type != TokenType.FLOW_MAPPING_END) { + if (token.type != TokenType.flowEntry && + token.type != TokenType.flowMappingEnd) { _states.add(_State.FLOW_MAPPING_KEY); return _parseNode(); } @@ -657,8 +657,8 @@ class Parser { VersionDirective versionDirective; var tagDirectives = []; - while (token.type == TokenType.VERSION_DIRECTIVE || - token.type == TokenType.TAG_DIRECTIVE) { + while (token.type == TokenType.versionDirective || + token.type == TokenType.tagDirective) { if (token is VersionDirectiveToken) { if (versionDirective != null) { throw YamlException('Duplicate %YAML directive.', token.span); @@ -709,16 +709,16 @@ class Parser { /// The possible states for the parser. class _State { - /// Expect [TokenType.STREAM_START]. + /// Expect [TokenType.streamStart]. static const STREAM_START = _State('STREAM_START'); - /// Expect [TokenType.DOCUMENT_START]. + /// Expect [TokenType.documentStart]. static const DOCUMENT_START = _State('DOCUMENT_START'); /// Expect the content of a document. static const DOCUMENT_CONTENT = _State('DOCUMENT_CONTENT'); - /// Expect [TokenType.DOCUMENT_END]. + /// Expect [TokenType.documentEnd]. static const DOCUMENT_END = _State('DOCUMENT_END'); /// Expect a block node. diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 2e499437b..98d54dfa2 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -95,17 +95,17 @@ class Scanner { /// [SourceSpan]s. final SpanScanner _scanner; - /// Whether this scanner has produced a [TokenType.STREAM_START] token + /// Whether this scanner has produced a [TokenType.streamStart] token /// indicating the beginning of the YAML stream. var _streamStartProduced = false; - /// Whether this scanner has produced a [TokenType.STREAM_END] token + /// Whether this scanner has produced a [TokenType.streamEnd] token /// indicating the end of the YAML stream. var _streamEndProduced = false; /// The queue of tokens yet to be emitted. /// - /// These are queued up in advance so that [TokenType.KEY] tokens can be + /// These are queued up in advance so that [TokenType.key] tokens can be /// inserted once the scanner determines that a series of tokens represents a /// mapping key. final _tokens = QueueList(); @@ -117,7 +117,7 @@ class Scanner { /// Whether the next token in [_tokens] is ready to be returned. /// - /// It might not be ready if there may still be a [TokenType.KEY] inserted + /// It might not be ready if there may still be a [TokenType.key] inserted /// before it. var _tokenAvailable = false; @@ -136,7 +136,7 @@ class Scanner { /// Entries in this list may be `null`, indicating that there is no valid /// simple key for the associated level of nesting. /// - /// When a ":" is parsed and there's a simple key available, a [TokenType.KEY] + /// When a ":" is parsed and there's a simple key available, a [TokenType.key] /// token is inserted in [_tokens] before that key's token. This allows the /// parser to tell that the key is intended to be a mapping key. final _simpleKeys = <_SimpleKey>[null]; @@ -301,7 +301,7 @@ class Scanner { var token = _tokens.removeFirst(); _tokenAvailable = false; _tokensParsed++; - _streamEndProduced = token is Token && token.type == TokenType.STREAM_END; + _streamEndProduced = token is Token && token.type == TokenType.streamEnd; return token; } @@ -325,7 +325,7 @@ class Scanner { _staleSimpleKeys(); // If there are no more tokens to fetch, break. - if (_tokens.last.type == TokenType.STREAM_END) break; + if (_tokens.last.type == TokenType.streamEnd) break; // If the current token could be a simple key, we need to scan more // tokens until we determine whether it is or not. Otherwise we might @@ -365,12 +365,12 @@ class Scanner { if (_isBlankOrEndAt(3)) { if (_scanner.matches('---')) { - _fetchDocumentIndicator(TokenType.DOCUMENT_START); + _fetchDocumentIndicator(TokenType.documentStart); return; } if (_scanner.matches('...')) { - _fetchDocumentIndicator(TokenType.DOCUMENT_END); + _fetchDocumentIndicator(TokenType.documentEnd); return; } } @@ -378,16 +378,16 @@ class Scanner { switch (_scanner.peekChar()) { case LEFT_SQUARE: - _fetchFlowCollectionStart(TokenType.FLOW_SEQUENCE_START); + _fetchFlowCollectionStart(TokenType.flowSequenceStart); return; case LEFT_CURLY: - _fetchFlowCollectionStart(TokenType.FLOW_MAPPING_START); + _fetchFlowCollectionStart(TokenType.flowMappingStart); return; case RIGHT_SQUARE: - _fetchFlowCollectionEnd(TokenType.FLOW_SEQUENCE_END); + _fetchFlowCollectionEnd(TokenType.flowSequenceEnd); return; case RIGHT_CURLY: - _fetchFlowCollectionEnd(TokenType.FLOW_MAPPING_END); + _fetchFlowCollectionEnd(TokenType.flowMappingEnd); return; case COMMA: _fetchFlowEntry(); @@ -442,9 +442,9 @@ class Scanner { // a quoted string) it isn't required to have whitespace after it // since it unambiguously describes a map. var token = _tokens.last; - if (token.type == TokenType.FLOW_SEQUENCE_END || - token.type == TokenType.FLOW_MAPPING_END || - (token.type == TokenType.SCALAR && + if (token.type == TokenType.flowSequenceEnd || + token.type == TokenType.flowMappingEnd || + (token.type == TokenType.scalar && (token as ScalarToken).style.isQuoted)) { _fetchValue(); return; @@ -568,12 +568,12 @@ class Scanner { /// Pops indentation levels from [_indents] until the current level becomes /// less than or equal to [column]. /// - /// For each indentation level, appends a [TokenType.BLOCK_END] token. + /// For each indentation level, appends a [TokenType.blockEnd] token. void _unrollIndent(int column) { if (!_inBlockContext) return; while (_indent > column) { - _tokens.add(Token(TokenType.BLOCK_END, _scanner.emptySpan)); + _tokens.add(Token(TokenType.blockEnd, _scanner.emptySpan)); _indents.removeLast(); } } @@ -581,26 +581,26 @@ class Scanner { /// Pops indentation levels from [_indents] until the current level resets to /// -1. /// - /// For each indentation level, appends a [TokenType.BLOCK_END] token. + /// For each indentation level, appends a [TokenType.blockEnd] token. void _resetIndent() => _unrollIndent(-1); - /// Produces a [TokenType.STREAM_START] token. + /// Produces a [TokenType.streamStart] token. void _fetchStreamStart() { // Much of libyaml's initialization logic here is done in variable // initializers instead. _streamStartProduced = true; - _tokens.add(Token(TokenType.STREAM_START, _scanner.emptySpan)); + _tokens.add(Token(TokenType.streamStart, _scanner.emptySpan)); } - /// Produces a [TokenType.STREAM_END] token. + /// Produces a [TokenType.streamEnd] token. void _fetchStreamEnd() { _resetIndent(); _removeSimpleKey(); _simpleKeyAllowed = false; - _tokens.add(Token(TokenType.STREAM_END, _scanner.emptySpan)); + _tokens.add(Token(TokenType.streamEnd, _scanner.emptySpan)); } - /// Produces a [TokenType.VERSION_DIRECTIVE] or [TokenType.TAG_DIRECTIVE] + /// Produces a [TokenType.versionDirective] or [TokenType.tagDirective] /// token. void _fetchDirective() { _resetIndent(); @@ -610,7 +610,7 @@ class Scanner { if (directive != null) _tokens.add(directive); } - /// Produces a [TokenType.DOCUMENT_START] or [TokenType.DOCUMENT_END] token. + /// Produces a [TokenType.documentStart] or [TokenType.documentEnd] token. void _fetchDocumentIndicator(TokenType type) { _resetIndent(); _removeSimpleKey(); @@ -625,8 +625,8 @@ class Scanner { _tokens.add(Token(type, _scanner.spanFrom(start))); } - /// Produces a [TokenType.FLOW_SEQUENCE_START] or - /// [TokenType.FLOW_MAPPING_START] token. + /// Produces a [TokenType.flowSequenceStart] or + /// [TokenType.flowMappingStart] token. void _fetchFlowCollectionStart(TokenType type) { _saveSimpleKey(); _increaseFlowLevel(); @@ -634,7 +634,7 @@ class Scanner { _addCharToken(type); } - /// Produces a [TokenType.FLOW_SEQUENCE_END] or [TokenType.FLOW_MAPPING_END] + /// Produces a [TokenType.flowSequenceEnd] or [TokenType.flowMappingEnd] /// token. void _fetchFlowCollectionEnd(TokenType type) { _removeSimpleKey(); @@ -643,14 +643,14 @@ class Scanner { _addCharToken(type); } - /// Produces a [TokenType.FLOW_ENTRY] token. + /// Produces a [TokenType.flowEntry] token. void _fetchFlowEntry() { _removeSimpleKey(); _simpleKeyAllowed = true; - _addCharToken(TokenType.FLOW_ENTRY); + _addCharToken(TokenType.flowEntry); } - /// Produces a [TokenType.BLOCK_ENTRY] token. + /// Produces a [TokenType.blockEntry] token. void _fetchBlockEntry() { if (_inBlockContext) { if (!_simpleKeyAllowed) { @@ -659,7 +659,7 @@ class Scanner { } _rollIndent( - _scanner.column, TokenType.BLOCK_SEQUENCE_START, _scanner.location); + _scanner.column, TokenType.blockSequenceStart, _scanner.location); } else { // It is an error for the '-' indicator to occur in the flow context, but // we let the Parser detect and report it because it's able to point to @@ -668,10 +668,10 @@ class Scanner { _removeSimpleKey(); _simpleKeyAllowed = true; - _addCharToken(TokenType.BLOCK_ENTRY); + _addCharToken(TokenType.blockEntry); } - /// Produces the [TokenType.KEY] token. + /// Produces the [TokenType.key] token. void _fetchKey() { if (_inBlockContext) { if (!_simpleKeyAllowed) { @@ -680,27 +680,27 @@ class Scanner { } _rollIndent( - _scanner.column, TokenType.BLOCK_MAPPING_START, _scanner.location); + _scanner.column, TokenType.blockMappingStart, _scanner.location); } // Simple keys are allowed after `?` in a block context. _simpleKeyAllowed = _inBlockContext; - _addCharToken(TokenType.KEY); + _addCharToken(TokenType.key); } - /// Produces the [TokenType.VALUE] token. + /// Produces the [TokenType.value] token. void _fetchValue() { var simpleKey = _simpleKeys.last; if (simpleKey != null) { // Add a [TokenType.KEY] directive before the first token of the simple // key so the parser knows that it's part of a key/value pair. _tokens.insert(simpleKey.tokenNumber - _tokensParsed, - Token(TokenType.KEY, simpleKey.location.pointSpan() as FileSpan)); + Token(TokenType.key, simpleKey.location.pointSpan() as FileSpan)); // In the block context, we may need to add the // [TokenType.BLOCK_MAPPING_START] token. _rollIndent( - simpleKey.column, TokenType.BLOCK_MAPPING_START, simpleKey.location, + simpleKey.column, TokenType.blockMappingStart, simpleKey.location, tokenNumber: simpleKey.tokenNumber); // Remove the simple key. @@ -719,16 +719,16 @@ class Scanner { // If we're here, we've found the ':' indicator following a complex key. _rollIndent( - _scanner.column, TokenType.BLOCK_MAPPING_START, _scanner.location); + _scanner.column, TokenType.blockMappingStart, _scanner.location); _simpleKeyAllowed = true; } else if (_simpleKeyAllowed) { // If we're here, we've found the ':' indicator with an empty key. This // behavior differs from libyaml, which disallows empty implicit keys. _simpleKeyAllowed = false; - _addCharToken(TokenType.KEY); + _addCharToken(TokenType.key); } - _addCharToken(TokenType.VALUE); + _addCharToken(TokenType.value); } /// Adds a token with [type] to [_tokens]. @@ -740,21 +740,21 @@ class Scanner { _tokens.add(Token(type, _scanner.spanFrom(start))); } - /// Produces a [TokenType.ALIAS] or [TokenType.ANCHOR] token. + /// Produces a [TokenType.alias] or [TokenType.anchor] token. void _fetchAnchor({bool anchor = true}) { _saveSimpleKey(); _simpleKeyAllowed = false; _tokens.add(_scanAnchor(anchor: anchor)); } - /// Produces a [TokenType.TAG] token. + /// Produces a [TokenType.tag] token. void _fetchTag() { _saveSimpleKey(); _simpleKeyAllowed = false; _tokens.add(_scanTag()); } - /// Produces a [TokenType.SCALAR] token with style [ScalarStyle.LITERAL] or + /// Produces a [TokenType.scalar] token with style [ScalarStyle.LITERAL] or /// [ScalarStyle.FOLDED]. void _fetchBlockScalar({bool literal = false}) { _removeSimpleKey(); @@ -762,7 +762,7 @@ class Scanner { _tokens.add(_scanBlockScalar(literal: literal)); } - /// Produces a [TokenType.SCALAR] token with style [ScalarStyle.SINGLE_QUOTED] + /// Produces a [TokenType.scalar] token with style [ScalarStyle.SINGLE_QUOTED] /// or [ScalarStyle.DOUBLE_QUOTED]. void _fetchFlowScalar({bool singleQuote = false}) { _saveSimpleKey(); @@ -770,7 +770,7 @@ class Scanner { _tokens.add(_scanFlowScalar(singleQuote: singleQuote)); } - /// Produces a [TokenType.SCALAR] token with style [ScalarStyle.PLAIN]. + /// Produces a [TokenType.scalar] token with style [ScalarStyle.PLAIN]. void _fetchPlainScalar() { _saveSimpleKey(); _simpleKeyAllowed = false; @@ -816,7 +816,7 @@ class Scanner { } } - /// Scans a [TokenType.YAML_DIRECTIVE] or [TokenType.TAG_DIRECTIVE] token. + /// Scans a [TokenType.YAML_DIRECTIVE] or [TokenType.tagDirective] token. /// /// %YAML 1.2 # a comment \n /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -940,7 +940,7 @@ class Scanner { return TagDirectiveToken(_scanner.spanFrom(start), handle, prefix); } - /// Scans a [TokenType.ANCHOR] token. + /// Scans a [TokenType.anchor] token. Token _scanAnchor({bool anchor = true}) { var start = _scanner.state; @@ -977,7 +977,7 @@ class Scanner { } } - /// Scans a [TokenType.TAG] token. + /// Scans a [TokenType.tag] token. Token _scanTag() { String handle; String suffix; @@ -1090,11 +1090,11 @@ class Scanner { _scanner.readChar(); // Check for a chomping indicator. - var chomping = _Chomping.CLIP; + var chomping = _Chomping.clip; var increment = 0; var char = _scanner.peekChar(); if (char == PLUS || char == HYPHEN) { - chomping = char == PLUS ? _Chomping.KEEP : _Chomping.STRIP; + chomping = char == PLUS ? _Chomping.keep : _Chomping.strip; _scanner.readChar(); // Check for an indentation indicator. @@ -1118,7 +1118,7 @@ class Scanner { char = _scanner.peekChar(); if (char == PLUS || char == HYPHEN) { - chomping = char == PLUS ? _Chomping.KEEP : _Chomping.STRIP; + chomping = char == PLUS ? _Chomping.keep : _Chomping.strip; _scanner.readChar(); } } @@ -1203,8 +1203,8 @@ class Scanner { } // Chomp the tail. - if (chomping != _Chomping.STRIP) buffer.write(leadingBreak); - if (chomping == _Chomping.KEEP) buffer.write(trailingBreaks); + if (chomping != _Chomping.strip) buffer.write(leadingBreak); + if (chomping == _Chomping.keep) buffer.write(trailingBreaks); return ScalarToken(_scanner.spanFrom(start, end), buffer.toString(), literal ? ScalarStyle.LITERAL : ScalarStyle.FOLDED); @@ -1662,17 +1662,16 @@ class _SimpleKey { : required = required; } -/// An enum of chomping indicators that describe how to handle trailing -/// whitespace for a block scalar. +/// The ways to handle trailing whitespace for a block scalar. /// /// See http://yaml.org/spec/1.2/spec.html#id2794534. enum _Chomping { /// All trailing whitespace is discarded. - STRIP, + strip, /// A single trailing newline is retained. - CLIP, + clip, /// All trailing whitespace is preserved. - KEEP + keep } diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 9051d683d..84165545f 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -8,10 +8,7 @@ import 'style.dart'; /// A token emitted by a [Scanner]. class Token { - /// The token type. final TokenType type; - - /// The span associated with the token. final FileSpan span; Token(this.type, this.span); @@ -23,7 +20,7 @@ class Token { /// A token representing a `%YAML` directive. class VersionDirectiveToken implements Token { @override - TokenType get type => TokenType.VERSION_DIRECTIVE; + TokenType get type => TokenType.versionDirective; @override final FileSpan span; @@ -42,7 +39,7 @@ class VersionDirectiveToken implements Token { /// A token representing a `%TAG` directive. class TagDirectiveToken implements Token { @override - TokenType get type => TokenType.TAG_DIRECTIVE; + TokenType get type => TokenType.tagDirective; @override final FileSpan span; @@ -61,11 +58,10 @@ class TagDirectiveToken implements Token { /// A token representing an anchor (`&foo`). class AnchorToken implements Token { @override - TokenType get type => TokenType.ANCHOR; + TokenType get type => TokenType.anchor; @override final FileSpan span; - /// The name of the anchor. final String name; AnchorToken(this.span, this.name); @@ -77,11 +73,10 @@ class AnchorToken implements Token { /// A token representing an alias (`*foo`). class AliasToken implements Token { @override - TokenType get type => TokenType.ALIAS; + TokenType get type => TokenType.alias; @override final FileSpan span; - /// The name of the anchor. final String name; AliasToken(this.span, this.name); @@ -93,11 +88,11 @@ class AliasToken implements Token { /// A token representing a tag (`!foo`). class TagToken implements Token { @override - TokenType get type => TokenType.TAG; + TokenType get type => TokenType.tag; @override final FileSpan span; - /// The tag handle. + /// The tag handle for named tags. final String handle; /// The tag suffix, or `null`. @@ -109,14 +104,14 @@ class TagToken implements Token { String toString() => 'TAG $handle $suffix'; } -/// A tkoen representing a scalar value. +/// A scalar value. class ScalarToken implements Token { @override - TokenType get type => TokenType.SCALAR; + TokenType get type => TokenType.scalar; @override final FileSpan span; - /// The contents of the scalar. + /// The unparsed contents of the value.. final String value; /// The style of the scalar in the original source. @@ -128,32 +123,32 @@ class ScalarToken implements Token { String toString() => 'SCALAR $style "$value"'; } -/// An enum of types of [Token] object. +/// The types of [Token] objects. enum TokenType { - STREAM_START, - STREAM_END, - - VERSION_DIRECTIVE, - TAG_DIRECTIVE, - DOCUMENT_START, - DOCUMENT_END, - - BLOCK_SEQUENCE_START, - BLOCK_MAPPING_START, - BLOCK_END, - - FLOW_SEQUENCE_START, - FLOW_SEQUENCE_END, - FLOW_MAPPING_START, - FLOW_MAPPING_END, - - BLOCK_ENTRY, - FLOW_ENTRY, - KEY, - VALUE, - - ALIAS, - ANCHOR, - TAG, - SCALAR + streamStart, + streamEnd, + + versionDirective, + tagDirective, + documentStart, + documentEnd, + + blockSequenceStart, + blockMappingStart, + blockEnd, + + flowSequenceStart, + flowSequenceEnd, + flowMappingStart, + flowMappingEnd, + + blockEntry, + flowEntry, + key, + value, + + alias, + anchor, + tag, + scalar } From 4503cd3a3e8b7dd475a7350b836dd0491f6d2e3c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 13 Mar 2020 12:08:40 -0700 Subject: [PATCH 101/179] remove author from pubspec --- pkgs/yaml/pubspec.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 68f6537ce..c0bfd997a 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -2,7 +2,6 @@ name: yaml version: 2.2.1-dev description: A parser for YAML, a human-friendly data serialization standard -author: Dart Team homepage: https://github.com/dart-lang/yaml environment: From 1d07eedc639e1a888bb1eef8226488c12856aeff Mon Sep 17 00:00:00 2001 From: Adarsh Maurya Date: Mon, 27 Apr 2020 23:41:49 +0530 Subject: [PATCH 102/179] fix for issue 49 (dart-lang/yaml#79) Fixes the span for null nodes in block lists. --- pkgs/yaml/CHANGELOG.md | 1 + pkgs/yaml/lib/src/parser.dart | 3 +- pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/span_test.dart | 81 +++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 258fb625e..5b5113593 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,6 +1,7 @@ ## 2.2.1 * Update min Dart SDK to `2.4.0`. +* Fixed span for null nodes in block lists. ## 2.2.0 diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 3eba773f6..4c8aaaf61 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -348,12 +348,13 @@ class Parser { var token = _scanner.peek(); if (token.type == TokenType.blockEntry) { + var start = token.span.start; token = _scanner.advance(); if (token.type == TokenType.blockEntry || token.type == TokenType.blockEnd) { _state = _State.BLOCK_SEQUENCE_ENTRY; - return _processEmptyScalar(token.span.end); + return _processEmptyScalar(start); } else { _states.add(_State.BLOCK_SEQUENCE_ENTRY); return _parseNode(block: true); diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index c0bfd997a..0641a2d80 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.2.1-dev +version: 2.2.1 description: A parser for YAML, a human-friendly data serialization standard homepage: https://github.com/dart-lang/yaml diff --git a/pkgs/yaml/test/span_test.dart b/pkgs/yaml/test/span_test.dart index 7ef61d306..401786825 100644 --- a/pkgs/yaml/test/span_test.dart +++ b/pkgs/yaml/test/span_test.dart @@ -86,4 +86,85 @@ line 5, column 10: message ); }); }); + + group('block', () { + YamlList list, nestedList; + + setUpAll(() { + const yamlStr = ''' +- foo +- + - one + - + - three + - + - five + - +- + a : b + c : d +- bar +'''; + + list = loadYaml(yamlStr) as YamlList; + nestedList = list.nodes[1] as YamlList; + }); + + test('root nodes span', () { + _expectSpan(list.nodes[0].span, r''' +line 1, column 3: message + ╷ +1 │ - foo + │ ^^^ + ╵'''); + + _expectSpan(list.nodes[1].span, r''' +line 3, column 3: message + ╷ +3 │ ┌ - one +4 │ │ - +5 │ │ - three +6 │ │ - +7 │ │ - five +8 │ └ - + ╵'''); + + _expectSpan(list.nodes[2].span, r''' +line 10, column 3: message + ╷ +10 │ ┌ a : b +11 │ └ c : d + ╵'''); + + _expectSpan(list.nodes[3].span, r''' +line 12, column 3: message + ╷ +12 │ - bar + │ ^^^ + ╵'''); + }); + + test('null nodes span', () { + _expectSpan(nestedList.nodes[1].span, r''' +line 4, column 3: message + ╷ +4 │ - + │ ^ + ╵'''); + + _expectSpan(nestedList.nodes[3].span, r''' +line 6, column 3: message + ╷ +6 │ - + │ ^ + ╵'''); + + _expectSpan(nestedList.nodes[5].span, r''' +line 8, column 3: message + ╷ +8 │ - + │ ^ + ╵'''); + }); + }); } From 8bfac45f4765ddc4ab7a764d755148e25f64c11d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 5 Jun 2020 22:05:17 -0700 Subject: [PATCH 103/179] Switch to Chrome (over FF) in CI (dart-lang/yaml#85) --- pkgs/yaml/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml index a25a59e25..e982192b6 100644 --- a/pkgs/yaml/.travis.yml +++ b/pkgs/yaml/.travis.yml @@ -7,7 +7,7 @@ dart: dart_task: - test: -p vm xvfb: false - - test: -p firefox + - test: -p chrome - dartanalyzer: --fatal-warnings --fatal-infos . matrix: From 44f7e879cb947a08cc6ae19330582eed909983f5 Mon Sep 17 00:00:00 2001 From: Garett Tok Ern Liang <36098015+walnutdust@users.noreply.github.com> Date: Thu, 2 Jul 2020 01:34:30 +0800 Subject: [PATCH 104/179] Added style as an optional named parameter for wrap() (dart-lang/yaml#86) --- pkgs/yaml/CHANGELOG.md | 4 ++ pkgs/yaml/lib/src/yaml_node.dart | 13 ++-- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 27 +++++--- pkgs/yaml/pubspec.yaml | 14 ++-- pkgs/yaml/test/yaml_node_wrapper_test.dart | 75 ++++++++++++++++++++-- 5 files changed, 107 insertions(+), 26 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 5b5113593..4f633990d 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.3.0-dev + +* Allow `YamlNode`s to be wrapped with an optional `style` parameter. + ## 2.2.1 * Update min Dart SDK to `2.4.0`. diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 25982e828..bbba77e25 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -77,8 +77,9 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - factory YamlMap.wrap(Map dartMap, {sourceUrl}) => - YamlMapWrapper(dartMap, sourceUrl); + factory YamlMap.wrap(Map dartMap, + {sourceUrl, CollectionStyle style = CollectionStyle.ANY}) => + YamlMapWrapper(dartMap, sourceUrl, style: style); /// Users of the library should not use this constructor. YamlMap.internal(Map nodes, SourceSpan span, this.style) @@ -127,8 +128,9 @@ class YamlList extends YamlNode with collection.ListMixin { /// passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - factory YamlList.wrap(List dartList, {sourceUrl}) => - YamlListWrapper(dartList, sourceUrl); + factory YamlList.wrap(List dartList, + {sourceUrl, CollectionStyle style = CollectionStyle.ANY}) => + YamlListWrapper(dartList, sourceUrl, style: style); /// Users of the library should not use this constructor. YamlList.internal(List nodes, SourceSpan span, this.style) @@ -160,7 +162,8 @@ class YamlScalar extends YamlNode { /// [sourceUrl] is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - YamlScalar.wrap(this.value, {sourceUrl}) : style = ScalarStyle.ANY { + YamlScalar.wrap(this.value, {sourceUrl, this.style = ScalarStyle.ANY}) { + ArgumentError.checkNotNull(style, 'style'); _span = NullSpan(sourceUrl); } diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index e714b651f..1e44a09e2 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -16,7 +16,7 @@ class YamlMapWrapper extends MapBase with pkg_collection.UnmodifiableMapMixin implements YamlMap { @override - final style = CollectionStyle.ANY; + final style; final Map _dartMap; @@ -32,12 +32,17 @@ class YamlMapWrapper extends MapBase @override Iterable get keys => _dartMap.keys; - YamlMapWrapper(Map dartMap, sourceUrl) : this._(dartMap, NullSpan(sourceUrl)); + YamlMapWrapper(Map dartMap, sourceUrl, + {CollectionStyle style = CollectionStyle.ANY}) + : this._(dartMap, NullSpan(sourceUrl), style: style); - YamlMapWrapper._(Map dartMap, SourceSpan span) + YamlMapWrapper._(Map dartMap, SourceSpan span, + {this.style = CollectionStyle.ANY}) : _dartMap = dartMap, span = span, - nodes = _YamlMapNodes(dartMap, span); + nodes = _YamlMapNodes(dartMap, span) { + ArgumentError.checkNotNull(style, 'style'); + } @override dynamic operator [](Object key) { @@ -89,7 +94,7 @@ class _YamlMapNodes extends MapBase /// A wrapper that makes a normal Dart list behave like a [YamlList]. class YamlListWrapper extends ListBase implements YamlList { @override - final style = CollectionStyle.ANY; + final style; final List _dartList; @@ -110,13 +115,17 @@ class YamlListWrapper extends ListBase implements YamlList { throw UnsupportedError('Cannot modify an unmodifiable List.'); } - YamlListWrapper(List dartList, sourceUrl) - : this._(dartList, NullSpan(sourceUrl)); + YamlListWrapper(List dartList, sourceUrl, + {CollectionStyle style = CollectionStyle.ANY}) + : this._(dartList, NullSpan(sourceUrl), style: style); - YamlListWrapper._(List dartList, SourceSpan span) + YamlListWrapper._(List dartList, SourceSpan span, + {this.style = CollectionStyle.ANY}) : _dartList = dartList, span = span, - nodes = _YamlListNodes(dartList, span); + nodes = _YamlListNodes(dartList, span) { + ArgumentError.checkNotNull(style, 'style'); + } @override dynamic operator [](int index) { diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 0641a2d80..31e50012d 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,19 +1,19 @@ name: yaml -version: 2.2.1 +version: 2.3.0-dev description: A parser for YAML, a human-friendly data serialization standard homepage: https://github.com/dart-lang/yaml environment: - sdk: '>=2.4.0 <3.0.0' + sdk: ">=2.4.0 <3.0.0" dependencies: charcode: ^1.1.0 - collection: '>=1.1.0 <2.0.0' - string_scanner: '>=0.1.4 <2.0.0' - source_span: '>=1.0.0 <2.0.0' + collection: ">=1.1.0 <2.0.0" + string_scanner: ">=0.1.4 <2.0.0" + source_span: ">=1.0.0 <2.0.0" dev_dependencies: pedantic: ^1.0.0 - path: '>=1.2.0 <2.0.0' - test: '>=0.12.0 <2.0.0' + path: ">=1.2.0 <2.0.0" + test: ">=0.12.0 <2.0.0" diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index 9dc991e87..d6da05205 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -67,6 +67,11 @@ void main() { expect(map.keys, unorderedEquals(['list', 'map', 'scalar'])); expect(map.nodes.keys, everyElement(TypeMatcher())); expect(map.nodes[YamlScalar.wrap('list')], equals([1, 2, 3])); + expect(map.style, equals(CollectionStyle.ANY)); + expect((map.nodes['list'] as YamlList).style, equals(CollectionStyle.ANY)); + expect((map.nodes['map'] as YamlMap).style, equals(CollectionStyle.ANY)); + expect((map['map'].nodes['nested'] as YamlList).style, + equals(CollectionStyle.ANY)); }); test('YamlMap.wrap() with a sourceUrl', () { @@ -86,6 +91,23 @@ void main() { expect(map.nodes['scalar'].span, isNullSpan(source)); }); + test('YamlMap.wrap() with a sourceUrl and style', () { + var map = YamlMap.wrap({ + 'list': [1, 2, 3], + 'map': { + 'foo': 'bar', + 'nested': [4, 5, 6] + }, + 'scalar': 'value' + }, sourceUrl: 'source', style: CollectionStyle.BLOCK); + + expect(map.style, equals(CollectionStyle.BLOCK)); + expect((map.nodes['list'] as YamlList).style, equals(CollectionStyle.ANY)); + expect((map.nodes['map'] as YamlMap).style, equals(CollectionStyle.ANY)); + expect((map['map'].nodes['nested'] as YamlList).style, + equals(CollectionStyle.ANY)); + }); + test('YamlList.wrap() with no sourceUrl', () { var list = YamlList.wrap([ [1, 2, 3], @@ -119,6 +141,10 @@ void main() { expect(list.nodes[2].value, 'value'); expect(list.nodes[2].span, isNullSpan(isNull)); expect(list[2], 'value'); + expect(list.style, equals(CollectionStyle.ANY)); + expect((list[0] as YamlList).style, equals(CollectionStyle.ANY)); + expect((list[1] as YamlMap).style, equals(CollectionStyle.ANY)); + expect((list[1]['nested'] as YamlList).style, equals(CollectionStyle.ANY)); }); test('YamlList.wrap() with a sourceUrl', () { @@ -129,12 +155,29 @@ void main() { 'nested': [4, 5, 6] }, 'value' - ]); + ], sourceUrl: 'source'); - expect(list.span, isNullSpan(isNull)); - expect(list[0].span, isNullSpan(isNull)); - expect(list[1].span, isNullSpan(isNull)); - expect(list.nodes[2].span, isNullSpan(isNull)); + var source = Uri.parse('source'); + expect(list.span, isNullSpan(source)); + expect(list[0].span, isNullSpan(source)); + expect(list[1].span, isNullSpan(source)); + expect(list.nodes[2].span, isNullSpan(source)); + }); + + test('YamlList.wrap() with a sourceUrl and style', () { + var list = YamlList.wrap([ + [1, 2, 3], + { + 'foo': 'bar', + 'nested': [4, 5, 6] + }, + 'value' + ], sourceUrl: 'source', style: CollectionStyle.FLOW); + + expect(list.style, equals(CollectionStyle.FLOW)); + expect((list[0] as YamlList).style, equals(CollectionStyle.ANY)); + expect((list[1] as YamlMap).style, equals(CollectionStyle.ANY)); + expect((list[1]['nested'] as YamlList).style, equals(CollectionStyle.ANY)); }); test('re-wrapped objects equal one another', () { @@ -150,6 +193,28 @@ void main() { expect(list[1].nodes == list[1].nodes, isTrue); expect(list[1] == YamlMap.wrap({'foo': 'bar'}), isFalse); }); + + test('YamlScalar.wrap() with no sourceUrl', () { + var scalar = YamlScalar.wrap('foo'); + + expect(scalar.span, isNullSpan(isNull)); + expect(scalar.value, 'foo'); + expect(scalar.style, equals(ScalarStyle.ANY)); + }); + + test('YamlScalar.wrap() with sourceUrl', () { + var scalar = YamlScalar.wrap('foo', sourceUrl: 'source'); + + var source = Uri.parse('source'); + expect(scalar.span, isNullSpan(source)); + }); + + test('YamlScalar.wrap() with sourceUrl and style', () { + var scalar = YamlScalar.wrap('foo', + sourceUrl: 'source', style: ScalarStyle.DOUBLE_QUOTED); + + expect(scalar.style, equals(ScalarStyle.DOUBLE_QUOTED)); + }); } Matcher isNullSpan(sourceUrl) => predicate((span) { From a82e71b745e5e13442f2395f5518e7c17bdc6f42 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 9 Oct 2020 15:39:12 -0700 Subject: [PATCH 105/179] Update README.md --- pkgs/yaml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index 991fc5c02..e6f7aa67e 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -1,4 +1,4 @@ -A parser for [YAML](http://www.yaml.org/). +A parser for [YAML](https://yaml.org/). [![Pub Package](https://img.shields.io/pub/v/yaml.svg)](https://pub.dev/packages/yaml) [![Build Status](https://travis-ci.org/dart-lang/yaml.svg?branch=master)](https://travis-ci.org/dart-lang/yaml) From 6cd35bdb696af4477edf7cac52db90fd04b40370 Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 6 Nov 2020 22:02:35 -0800 Subject: [PATCH 106/179] migrate to nnbd --- pkgs/yaml/lib/src/event.dart | 20 +++--- pkgs/yaml/lib/src/loader.dart | 18 ++--- pkgs/yaml/lib/src/null_span.dart | 1 + pkgs/yaml/lib/src/parser.dart | 84 +++++++++++----------- pkgs/yaml/lib/src/scanner.dart | 30 ++++---- pkgs/yaml/lib/src/token.dart | 7 +- pkgs/yaml/lib/src/utils.dart | 10 +-- pkgs/yaml/lib/src/yaml_document.dart | 2 +- pkgs/yaml/lib/src/yaml_exception.dart | 2 +- pkgs/yaml/lib/src/yaml_node.dart | 4 +- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 6 +- pkgs/yaml/pubspec.yaml | 16 ++--- pkgs/yaml/test/span_test.dart | 18 ++--- pkgs/yaml/test/utils.dart | 2 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 8 +-- pkgs/yaml/test/yaml_test.dart | 32 ++++----- 16 files changed, 128 insertions(+), 132 deletions(-) diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart index c4f6a6ddb..e8879eefc 100644 --- a/pkgs/yaml/lib/src/event.dart +++ b/pkgs/yaml/lib/src/event.dart @@ -26,7 +26,7 @@ class DocumentStartEvent implements Event { final FileSpan span; /// The document's `%YAML` directive, or `null` if there was none. - final VersionDirective versionDirective; + final VersionDirective? versionDirective; /// The document's `%TAG` directives, if any. final List tagDirectives; @@ -37,7 +37,7 @@ class DocumentStartEvent implements Event { DocumentStartEvent(this.span, {this.versionDirective, - List tagDirectives, + List? tagDirectives, this.isImplicit = true}) : tagDirectives = tagDirectives ?? []; @@ -81,10 +81,10 @@ class AliasEvent implements Event { /// An event that can have associated anchor and tag properties. abstract class _ValueEvent implements Event { /// The name of the value's anchor, or `null` if it wasn't anchored. - String get anchor; + String? get anchor; /// The text of the value's tag, or `null` if it wasn't tagged. - String get tag; + String? get tag; @override String toString() { @@ -102,9 +102,9 @@ class ScalarEvent extends _ValueEvent { @override final FileSpan span; @override - final String anchor; + final String? anchor; @override - final String tag; + final String? tag; /// The contents of the scalar. final String value; @@ -125,9 +125,9 @@ class SequenceStartEvent extends _ValueEvent { @override final FileSpan span; @override - final String anchor; + final String? anchor; @override - final String tag; + final String? tag; /// The style of the collection in the original source. final CollectionStyle style; @@ -142,9 +142,9 @@ class MappingStartEvent extends _ValueEvent { @override final FileSpan span; @override - final String anchor; + final String? anchor; @override - final String tag; + final String? tag; /// The style of the collection in the original source. final CollectionStyle style; diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 54172b538..370540609 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -27,7 +27,7 @@ class Loader { /// The span of the entire stream emitted so far. FileSpan get span => _span; - FileSpan _span; + late FileSpan _span; /// Creates a loader that loads [source]. /// @@ -42,7 +42,7 @@ class Loader { /// Loads the next document from the stream. /// /// If there are no more documents, returns `null`. - YamlDocument load() { + YamlDocument? load() { if (_parser.isDone) return null; var event = _parser.parse(); @@ -90,7 +90,7 @@ class Loader { } /// Registers an anchor. - void _registerAnchor(String anchor, YamlNode node) { + void _registerAnchor(String? anchor, YamlNode node) { if (anchor == null) return; // libyaml throws an error for duplicate anchors, but example 7.1 makes it @@ -207,7 +207,7 @@ class Loader { /// /// If parsing fails, this returns `null`, indicating that the scalar should /// be parsed as a string. - YamlScalar _tryParseScalar(ScalarEvent scalar) { + YamlScalar? _tryParseScalar(ScalarEvent scalar) { // Quickly check for the empty string, which means null. var length = scalar.value.length; if (length == 0) return YamlScalar.internal(null, scalar); @@ -239,7 +239,7 @@ class Loader { /// Parse a null scalar. /// /// Returns a Dart `null` if parsing fails. - YamlScalar _parseNull(ScalarEvent scalar) { + YamlScalar? _parseNull(ScalarEvent scalar) { switch (scalar.value) { case '': case 'null': @@ -255,7 +255,7 @@ class Loader { /// Parse a boolean scalar. /// /// Returns `null` if parsing fails. - YamlScalar _parseBool(ScalarEvent scalar) { + YamlScalar? _parseBool(ScalarEvent scalar) { switch (scalar.value) { case 'true': case 'True': @@ -273,7 +273,7 @@ class Loader { /// Parses a numeric scalar. /// /// Returns `null` if parsing fails. - YamlScalar _parseNumber(ScalarEvent scalar, + YamlScalar? _parseNumber(ScalarEvent scalar, {bool allowInt = true, bool allowFloat = true}) { var value = _parseNumberValue(scalar.value, allowInt: allowInt, allowFloat: allowFloat); @@ -283,7 +283,7 @@ class Loader { /// Parses the value of a number. /// /// Returns the number if it's parsed successfully, or `null` if it's not. - num _parseNumberValue(String contents, + num? _parseNumberValue(String contents, {bool allowInt = true, bool allowFloat = true}) { assert(allowInt || allowFloat); @@ -315,7 +315,7 @@ class Loader { secondChar >= $0 && secondChar <= $9)) { // Try to parse an int or, failing that, a double. - num result; + num? result; if (allowInt) { // Pass "radix: 10" explicitly to ensure that "-0x10", which is valid // Dart but invalid YAML, doesn't get parsed. diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index 64b3551ed..dd868b808 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -12,6 +12,7 @@ import 'package:source_span/source_span.dart'; class NullSpan extends SourceSpanMixin { @override final SourceLocation start; + @override SourceLocation get end => start; @override diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 4c8aaaf61..267d7cadf 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -130,7 +130,7 @@ class Parser { /// DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* /// ************************* Event _parseDocumentStart() { - var token = _scanner.peek(); + var token = _scanner.peek()!; // libyaml requires any document beyond the first in the stream to have an // explicit document start indicator, but the spec allows it to be omitted @@ -138,7 +138,7 @@ class Parser { // Parse extra document end indicators. while (token.type == TokenType.documentEnd) { - token = _scanner.advance(); + token = _scanner.advance()!; } if (token.type != TokenType.versionDirective && @@ -163,7 +163,7 @@ class Parser { var pair = _processDirectives(); var versionDirective = pair.first; var tagDirectives = pair.last; - token = _scanner.peek(); + token = _scanner.peek()!; if (token.type != TokenType.documentStart) { throw YamlException('Expected document start.', token.span); } @@ -183,7 +183,7 @@ class Parser { /// DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* /// *********** Event _parseDocumentContent() { - var token = _scanner.peek(); + var token = _scanner.peek()!; switch (token.type) { case TokenType.versionDirective: @@ -209,7 +209,7 @@ class Parser { _tagDirectives.clear(); _state = _State.DOCUMENT_START; - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token.type == TokenType.documentEnd) { _scanner.scan(); return DocumentEndEvent(token.span, isImplicit: false); @@ -246,7 +246,7 @@ class Parser { /// flow_content ::= flow_collection | SCALAR /// ****** Event _parseNode({bool block = false, bool indentlessSequence = false}) { - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token is AliasToken) { _scanner.scan(); @@ -254,40 +254,40 @@ class Parser { return AliasEvent(token.span, token.name); } - String anchor; - TagToken tagToken; + String? anchor; + TagToken? tagToken; var span = token.span.start.pointSpan(); Token parseAnchor(AnchorToken token) { anchor = token.name; span = span.expand(token.span); - return _scanner.advance(); + return _scanner.advance()!; } Token parseTag(TagToken token) { tagToken = token; span = span.expand(token.span); - return _scanner.advance(); + return _scanner.advance()!; } if (token is AnchorToken) { - token = parseAnchor(token as AnchorToken); - if (token is TagToken) token = parseTag(token as TagToken); + token = parseAnchor(token); + if (token is TagToken) token = parseTag(token); } else if (token is TagToken) { - token = parseTag(token as TagToken); - if (token is AnchorToken) token = parseAnchor(token as AnchorToken); + token = parseTag(token); + if (token is AnchorToken) token = parseAnchor(token); } - String tag; + String? tag; if (tagToken != null) { - if (tagToken.handle == null) { - tag = tagToken.suffix; + if (tagToken!.handle == null) { + tag = tagToken!.suffix; } else { - var tagDirective = _tagDirectives[tagToken.handle]; + var tagDirective = _tagDirectives[tagToken!.handle]; if (tagDirective == null) { - throw YamlException('Undefined tag handle.', tagToken.span); + throw YamlException('Undefined tag handle.', tagToken!.span); } - tag = tagDirective.prefix + tagToken.suffix; + tag = tagDirective.prefix + tagToken!.suffix; } } @@ -345,11 +345,11 @@ class Parser { /// BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END /// ******************** *********** * ********* Event _parseBlockSequenceEntry() { - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token.type == TokenType.blockEntry) { var start = token.span.start; - token = _scanner.advance(); + token = _scanner.advance()!; if (token.type == TokenType.blockEntry || token.type == TokenType.blockEnd) { @@ -376,7 +376,7 @@ class Parser { /// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ /// *********** * Event _parseIndentlessSequenceEntry() { - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token.type != TokenType.blockEntry) { _state = _states.removeLast(); @@ -384,7 +384,7 @@ class Parser { } var start = token.span.start; - token = _scanner.advance(); + token = _scanner.advance()!; if (token.type == TokenType.blockEntry || token.type == TokenType.key || @@ -409,10 +409,10 @@ class Parser { /// BLOCK-END /// ********* Event _parseBlockMappingKey() { - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token.type == TokenType.key) { var start = token.span.start; - token = _scanner.advance(); + token = _scanner.advance()!; if (token.type == TokenType.key || token.type == TokenType.value || @@ -454,7 +454,7 @@ class Parser { /// BLOCK-END /// Event _parseBlockMappingValue() { - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token.type != TokenType.value) { _state = _State.BLOCK_MAPPING_KEY; @@ -462,7 +462,7 @@ class Parser { } var start = token.span.start; - token = _scanner.advance(); + token = _scanner.advance()!; if (token.type == TokenType.key || token.type == TokenType.value || token.type == TokenType.blockEnd) { @@ -489,7 +489,7 @@ class Parser { /// * Event _parseFlowSequenceEntry({bool first = false}) { if (first) _scanner.scan(); - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token.type != TokenType.flowSequenceEnd) { if (!first) { @@ -499,7 +499,7 @@ class Parser { token.span.start.pointSpan()); } - token = _scanner.advance(); + token = _scanner.advance()!; } if (token.type == TokenType.key) { @@ -523,7 +523,7 @@ class Parser { /// flow_node | KEY flow_node? (VALUE flow_node?)? /// *** * Event _parseFlowSequenceEntryMappingKey() { - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token.type == TokenType.value || token.type == TokenType.flowEntry || @@ -547,10 +547,10 @@ class Parser { /// flow_node | KEY flow_node? (VALUE flow_node?)? /// ***** * Event _parseFlowSequenceEntryMappingValue() { - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token.type == TokenType.value) { - token = _scanner.advance(); + token = _scanner.advance()!; if (token.type != TokenType.flowEntry && token.type != TokenType.flowSequenceEnd) { _states.add(_State.FLOW_SEQUENCE_ENTRY_MAPPING_END); @@ -569,7 +569,7 @@ class Parser { /// * Event _parseFlowSequenceEntryMappingEnd() { _state = _State.FLOW_SEQUENCE_ENTRY; - return Event(EventType.mappingEnd, _scanner.peek().span.start.pointSpan()); + return Event(EventType.mappingEnd, _scanner.peek()!.span.start.pointSpan()); } /// Parses the productions: @@ -587,7 +587,7 @@ class Parser { /// * *** * Event _parseFlowMappingKey({bool first = false}) { if (first) _scanner.scan(); - var token = _scanner.peek(); + var token = _scanner.peek()!; if (token.type != TokenType.flowMappingEnd) { if (!first) { @@ -597,11 +597,11 @@ class Parser { token.span.start.pointSpan()); } - token = _scanner.advance(); + token = _scanner.advance()!; } if (token.type == TokenType.key) { - token = _scanner.advance(); + token = _scanner.advance()!; if (token.type != TokenType.value && token.type != TokenType.flowEntry && token.type != TokenType.flowMappingEnd) { @@ -628,7 +628,7 @@ class Parser { /// flow_node | KEY flow_node? (VALUE flow_node?)? /// * ***** * Event _parseFlowMappingValue({bool empty = false}) { - var token = _scanner.peek(); + var token = _scanner.peek()!; if (empty) { _state = _State.FLOW_MAPPING_KEY; @@ -636,7 +636,7 @@ class Parser { } if (token.type == TokenType.value) { - token = _scanner.advance(); + token = _scanner.advance()!; if (token.type != TokenType.flowEntry && token.type != TokenType.flowMappingEnd) { _states.add(_State.FLOW_MAPPING_KEY); @@ -654,9 +654,9 @@ class Parser { /// Parses directives. Pair> _processDirectives() { - var token = _scanner.peek(); + var token = _scanner.peek()!; - VersionDirective versionDirective; + VersionDirective? versionDirective; var tagDirectives = []; while (token.type == TokenType.versionDirective || token.type == TokenType.tagDirective) { @@ -684,7 +684,7 @@ class Parser { tagDirectives.add(tagDirective); } - token = _scanner.advance(); + token = _scanner.advance()!; } _appendTagDirective(TagDirective('!', '!'), token.span.start.pointSpan(), diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 98d54dfa2..fac955040 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -139,7 +139,7 @@ class Scanner { /// When a ":" is parsed and there's a simple key available, a [TokenType.key] /// token is inserted in [_tokens] before that key's token. This allows the /// parser to tell that the key is intended to be a mapping key. - final _simpleKeys = <_SimpleKey>[null]; + final _simpleKeys = <_SimpleKey?>[null]; /// The current indentation level. int get _indent => _indents.last; @@ -306,13 +306,13 @@ class Scanner { } /// Consumes the next token and returns the one after that. - Token advance() { + Token? advance() { scan(); return peek(); } /// Returns the next token without consuming it. - Token peek() { + Token? peek() { if (_streamEndProduced) return null; if (!_tokenAvailable) _fetchMoreTokens(); return _tokens.first; @@ -548,7 +548,7 @@ class Scanner { /// [tokenNumber] is provided, the corresponding token will be replaced; /// otherwise, the token will be added at the end. void _rollIndent(int column, TokenType type, SourceLocation location, - {int tokenNumber}) { + {int? tokenNumber}) { if (!_inBlockContext) return; if (_indent != -1 && _indent >= column) return; @@ -822,7 +822,7 @@ class Scanner { /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /// %TAG !yaml! tag:yaml.org,2002: \n /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Token _scanDirective() { + Token? _scanDirective() { var start = _scanner.state; // Eat '%'. @@ -979,7 +979,7 @@ class Scanner { /// Scans a [TokenType.tag] token. Token _scanTag() { - String handle; + String? handle; String suffix; var start = _scanner.state; @@ -1052,14 +1052,14 @@ class Scanner { /// [head] is the initial portion of the tag that's already been scanned. /// [flowSeparators] indicates whether the tag URI can contain flow /// separators. - String _scanTagUri({String head, bool flowSeparators = true}) { + String _scanTagUri({String? head, bool flowSeparators = true}) { var length = head == null ? 0 : head.length; var buffer = StringBuffer(); // Copy the head if needed. // // Note that we don't copy the leading '!' character. - if (length > 1) buffer.write(head.substring(1)); + if (length > 1) buffer.write(head!.substring(1)); // The set of characters that may appear in URI is as follows: // @@ -1146,8 +1146,8 @@ class Scanner { // Scan the leading line breaks to determine the indentation level if // needed. var pair = _scanBlockScalarBreaks(indent); - indent = pair.first; - var trailingBreaks = pair.last; + indent = pair.first!; + var trailingBreaks = pair.last!; // Scan the block scalar contents. var buffer = StringBuffer(); @@ -1198,8 +1198,8 @@ class Scanner { // Eat the following indentation and spaces. var pair = _scanBlockScalarBreaks(indent); - indent = pair.first; - trailingBreaks = pair.last; + indent = pair.first!; + trailingBreaks = pair.last!; } // Chomp the tail. @@ -1287,7 +1287,7 @@ class Scanner { var escapeStart = _scanner.state; // An escape sequence. - int codeLength; + int? codeLength; switch (_scanner.peekChar(1)) { case NUMBER_0: buffer.writeCharCode(NULL); @@ -1324,7 +1324,7 @@ class Scanner { // libyaml doesn't support an escaped forward slash, but it was // added in YAML 1.2. See section 5.7: // http://yaml.org/spec/1.2/spec.html#id2776092 - buffer.writeCharCode(_scanner.peekChar(1)); + buffer.writeCharCode(_scanner.peekChar(1)!); break; case LETTER_CAP_N: buffer.writeCharCode(NEL); @@ -1658,7 +1658,7 @@ class _SimpleKey { final bool required; _SimpleKey(this.tokenNumber, this.line, this.column, this.location, - {bool required}) + {required bool required}) : required = required; } diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 84165545f..7dbfb3bde 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -93,7 +93,7 @@ class TagToken implements Token { final FileSpan span; /// The tag handle for named tags. - final String handle; + final String? handle; /// The tag suffix, or `null`. final String suffix; @@ -127,26 +127,21 @@ class ScalarToken implements Token { enum TokenType { streamStart, streamEnd, - versionDirective, tagDirective, documentStart, documentEnd, - blockSequenceStart, blockMappingStart, blockEnd, - flowSequenceStart, flowSequenceEnd, flowMappingStart, flowMappingEnd, - blockEntry, flowEntry, key, value, - alias, anchor, tag, diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 8ce785501..20210ef1a 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -6,8 +6,8 @@ import 'package:source_span/source_span.dart'; /// A pair of values. class Pair { - final E first; - final F last; + final E? first; + final F? last; Pair(this.first, this.last); @@ -18,7 +18,7 @@ class Pair { /// Print a warning. /// /// If [span] is passed, associates the warning with that span. -void warn(String message, [SourceSpan span]) => +void warn(String message, [SourceSpan? span]) => yamlWarningCallback(message, span); /// A callback for emitting a warning. @@ -26,14 +26,14 @@ void warn(String message, [SourceSpan span]) => /// [message] is the text of the warning. If [span] is passed, it's the portion /// of the document that the warning is associated with and should be included /// in the printed warning. -typedef YamlWarningCallback = Function(String message, [SourceSpan span]); +typedef YamlWarningCallback = Function(String message, [SourceSpan? span]); /// A callback for emitting a warning. /// /// In a very few cases, the YAML spec indicates that an implementation should /// emit a warning. To do so, it calls this callback. The default implementation /// prints a message using [print]. -YamlWarningCallback yamlWarningCallback = (message, [span]) { +YamlWarningCallback yamlWarningCallback = (message, [SourceSpan? span]) { // TODO(nweiz): Print to stderr with color when issue 6943 is fixed and // dart:io is available. if (span != null) message = span.message(message); diff --git a/pkgs/yaml/lib/src/yaml_document.dart b/pkgs/yaml/lib/src/yaml_document.dart index 8757418ad..65b9548df 100644 --- a/pkgs/yaml/lib/src/yaml_document.dart +++ b/pkgs/yaml/lib/src/yaml_document.dart @@ -17,7 +17,7 @@ class YamlDocument { final SourceSpan span; /// The version directive for the document, if any. - final VersionDirective versionDirective; + final VersionDirective? versionDirective; /// The tag directives for the document. final List tagDirectives; diff --git a/pkgs/yaml/lib/src/yaml_exception.dart b/pkgs/yaml/lib/src/yaml_exception.dart index c4b7f28b8..1941f0238 100644 --- a/pkgs/yaml/lib/src/yaml_exception.dart +++ b/pkgs/yaml/lib/src/yaml_exception.dart @@ -6,5 +6,5 @@ import 'package:source_span/source_span.dart'; /// An error thrown by the YAML processor. class YamlException extends SourceSpanFormatException { - YamlException(String message, SourceSpan span) : super(message, span); + YamlException(String message, SourceSpan? span) : super(message, span); } diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index bbba77e25..c8f294b4b 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -26,9 +26,9 @@ abstract class YamlNode { /// /// [SourceSpan.message] can be used to produce a human-friendly message about /// this node. - SourceSpan get span => _span; + SourceSpan? get span => _span; - SourceSpan _span; + SourceSpan? _span; /// The inner value of this node. /// diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index 1e44a09e2..87328ba1c 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -45,7 +45,7 @@ class YamlMapWrapper extends MapBase } @override - dynamic operator [](Object key) { + dynamic operator [](Object? key) { var value = _dartMap[key]; if (value is Map) return YamlMapWrapper._(value, span); if (value is List) return YamlListWrapper._(value, span); @@ -75,9 +75,9 @@ class _YamlMapNodes extends MapBase _YamlMapNodes(this._dartMap, this._span); @override - YamlNode operator [](Object key) { + YamlNode? operator [](Object? key) { // Use "as" here because key being assigned to invalidates type propagation. - if (key is YamlScalar) key = (key as YamlScalar).value; + if (key is YamlScalar) key = key.value; if (!_dartMap.containsKey(key)) return null; return _nodeForValue(_dartMap[key], _span); } diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 31e50012d..2c3215f9c 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,19 +1,19 @@ name: yaml -version: 2.3.0-dev +version: 2.3.0-nullsafety description: A parser for YAML, a human-friendly data serialization standard homepage: https://github.com/dart-lang/yaml environment: - sdk: ">=2.4.0 <3.0.0" + sdk: '>=2.12.0-0 <3.0.0' dependencies: charcode: ^1.1.0 - collection: ">=1.1.0 <2.0.0" - string_scanner: ">=0.1.4 <2.0.0" - source_span: ">=1.0.0 <2.0.0" + collection: ^1.15.0-nullsafety + string_scanner: ^1.1.0-nullsafety + source_span: ^1.8.0-nullsafety dev_dependencies: - pedantic: ^1.0.0 - path: ">=1.2.0 <2.0.0" - test: ">=0.12.0 <2.0.0" + pedantic: ^1.10.0-nullsafety + path: ^1.8.0-nullsafety + test: ^1.16.0-nullsafety diff --git a/pkgs/yaml/test/span_test.dart b/pkgs/yaml/test/span_test.dart index 401786825..6c666dd77 100644 --- a/pkgs/yaml/test/span_test.dart +++ b/pkgs/yaml/test/span_test.dart @@ -8,15 +8,15 @@ import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; -void _expectSpan(SourceSpan source, String expected) { - final result = source.message('message'); +void _expectSpan(SourceSpan? source, String expected) { + final result = source!.message('message'); printOnFailure("r'''\n$result'''"); expect(result, expected); } void main() { - YamlMap yaml; + late YamlMap yaml; setUpAll(() { yaml = loadYaml(const JsonEncoder.withIndent(' ').convert({ @@ -31,7 +31,7 @@ void main() { test('first root key', () { _expectSpan( - yaml.nodes['num'].span, + yaml.nodes['num']!.span, r''' line 2, column 9: message ╷ @@ -43,7 +43,7 @@ line 2, column 9: message test('first root key', () { _expectSpan( - yaml.nodes['null'].span, + yaml.nodes['null']!.span, r''' line 7, column 10: message ╷ @@ -54,7 +54,7 @@ line 7, column 10: message }); group('nested', () { - YamlMap nestedMap; + late YamlMap nestedMap; setUpAll(() { nestedMap = yaml.nodes['nested'] as YamlMap; @@ -62,7 +62,7 @@ line 7, column 10: message test('first root key', () { _expectSpan( - nestedMap.nodes['null'].span, + nestedMap.nodes['null']!.span, r''' line 4, column 11: message ╷ @@ -74,7 +74,7 @@ line 4, column 11: message test('first root key', () { _expectSpan( - nestedMap.nodes['num'].span, + nestedMap.nodes['num']!.span, r''' line 5, column 10: message ╷ @@ -88,7 +88,7 @@ line 5, column 10: message }); group('block', () { - YamlList list, nestedList; + late YamlList list, nestedList; setUpAll(() { const yamlStr = ''' diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index c49afe2d3..ce0548142 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -16,7 +16,7 @@ Matcher deepEquals(expected) => predicate( (actual) => equality.deepEquals(actual, expected), 'equals $expected'); /// Constructs a new yaml.YamlMap, optionally from a normal Map. -Map deepEqualsMap([Map from]) { +Map deepEqualsMap([Map? from]) { var map = equality.deepEqualsMap(); if (from != null) map.addAll(from); return map; diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index d6da05205..e5d71cc54 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -61,8 +61,8 @@ void main() { expect(map['map']['nested'], TypeMatcher()); expect(map['map'].span, isNullSpan(isNull)); expect(map.nodes['scalar'], TypeMatcher()); - expect(map.nodes['scalar'].value, 'value'); - expect(map.nodes['scalar'].span, isNullSpan(isNull)); + expect(map.nodes['scalar']!.value, 'value'); + expect(map.nodes['scalar']!.span, isNullSpan(isNull)); expect(map['scalar'], 'value'); expect(map.keys, unorderedEquals(['list', 'map', 'scalar'])); expect(map.nodes.keys, everyElement(TypeMatcher())); @@ -88,7 +88,7 @@ void main() { expect(map.span, isNullSpan(source)); expect(map['list'].span, isNullSpan(source)); expect(map['map'].span, isNullSpan(source)); - expect(map.nodes['scalar'].span, isNullSpan(source)); + expect(map.nodes['scalar']!.span, isNullSpan(source)); }); test('YamlMap.wrap() with a sourceUrl and style', () { @@ -217,7 +217,7 @@ void main() { }); } -Matcher isNullSpan(sourceUrl) => predicate((span) { +Matcher isNullSpan(sourceUrl) => predicate((SourceSpan span) { expect(span, TypeMatcher()); expect(span.length, equals(0)); expect(span.text, isEmpty); diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index a0fb8f110..3633a5e18 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -68,16 +68,16 @@ void main() { - 123 ''') as YamlList; - expect(yaml.span.start.line, equals(0)); - expect(yaml.span.start.column, equals(0)); - expect(yaml.span.end.line, equals(3)); - expect(yaml.span.end.column, equals(0)); + expect(yaml.span!.start.line, equals(0)); + expect(yaml.span!.start.column, equals(0)); + expect(yaml.span!.end.line, equals(3)); + expect(yaml.span!.end.column, equals(0)); var map = yaml.nodes.first as YamlMap; - expect(map.span.start.line, equals(0)); - expect(map.span.start.column, equals(2)); - expect(map.span.end.line, equals(2)); - expect(map.span.end.column, equals(0)); + expect(map.span!.start.line, equals(0)); + expect(map.span!.start.column, equals(2)); + expect(map.span!.end.line, equals(2)); + expect(map.span!.end.column, equals(0)); var key = map.nodes.keys.first; expect(key.span.start.line, equals(0)); @@ -86,16 +86,16 @@ void main() { expect(key.span.end.column, equals(5)); var value = map.nodes.values.first; - expect(value.span.start.line, equals(1)); - expect(value.span.start.column, equals(4)); - expect(value.span.end.line, equals(1)); - expect(value.span.end.column, equals(7)); + expect(value.span!.start.line, equals(1)); + expect(value.span!.start.column, equals(4)); + expect(value.span!.end.line, equals(1)); + expect(value.span!.end.column, equals(7)); var scalar = yaml.nodes.last; - expect(scalar.span.start.line, equals(2)); - expect(scalar.span.start.column, equals(2)); - expect(scalar.span.end.line, equals(2)); - expect(scalar.span.end.column, equals(5)); + expect(scalar.span!.start.line, equals(2)); + expect(scalar.span!.start.column, equals(2)); + expect(scalar.span!.end.line, equals(2)); + expect(scalar.span!.end.column, equals(5)); }); // The following tests are all taken directly from the YAML spec From 50829264fcb5ca1c3f0cce6fffaac96127cc6cb7 Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 6 Nov 2020 22:09:55 -0800 Subject: [PATCH 107/179] unconstrain dart --- pkgs/yaml/.travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml index e982192b6..e0a5b905b 100644 --- a/pkgs/yaml/.travis.yml +++ b/pkgs/yaml/.travis.yml @@ -1,7 +1,6 @@ language: dart dart: - - 2.4.0 - dev dart_task: From 3b8f1a8d55b1d1a4862a7773d7c3cf6c3a1d5e7c Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 6 Nov 2020 22:12:40 -0800 Subject: [PATCH 108/179] updated charcode dep --- pkgs/yaml/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 2c3215f9c..b78a39bae 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -8,7 +8,7 @@ environment: sdk: '>=2.12.0-0 <3.0.0' dependencies: - charcode: ^1.1.0 + charcode: ^1.2.0-nullsafety collection: ^1.15.0-nullsafety string_scanner: ^1.1.0-nullsafety source_span: ^1.8.0-nullsafety From d56075c11306f8123489263952869aeb2f45bd93 Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 6 Nov 2020 22:16:12 -0800 Subject: [PATCH 109/179] sort --- pkgs/yaml/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index b78a39bae..435655e37 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -10,10 +10,10 @@ environment: dependencies: charcode: ^1.2.0-nullsafety collection: ^1.15.0-nullsafety - string_scanner: ^1.1.0-nullsafety source_span: ^1.8.0-nullsafety + string_scanner: ^1.1.0-nullsafety dev_dependencies: - pedantic: ^1.10.0-nullsafety path: ^1.8.0-nullsafety + pedantic: ^1.10.0-nullsafety test: ^1.16.0-nullsafety From a98171f6df559600645fdb6520fc2c6b52d7cea2 Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 9 Nov 2020 09:35:43 -0800 Subject: [PATCH 110/179] updated version --- pkgs/yaml/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 435655e37..9b5b56855 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.3.0-nullsafety +version: 2.3.0-nullsafety.0 description: A parser for YAML, a human-friendly data serialization standard homepage: https://github.com/dart-lang/yaml From de2ac82d40d66fc7328a962455b5b1fef72d514e Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 9 Nov 2020 09:54:12 -0800 Subject: [PATCH 111/179] fixed ws --- pkgs/yaml/lib/src/null_span.dart | 1 - pkgs/yaml/lib/src/token.dart | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index dd868b808..64b3551ed 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -12,7 +12,6 @@ import 'package:source_span/source_span.dart'; class NullSpan extends SourceSpanMixin { @override final SourceLocation start; - @override SourceLocation get end => start; @override diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 7dbfb3bde..4f4172f26 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -127,21 +127,26 @@ class ScalarToken implements Token { enum TokenType { streamStart, streamEnd, + versionDirective, tagDirective, documentStart, documentEnd, + blockSequenceStart, blockMappingStart, blockEnd, + flowSequenceStart, flowSequenceEnd, flowMappingStart, flowMappingEnd, + blockEntry, flowEntry, key, value, + alias, anchor, tag, From 2d4ef71b070b571741ff5e7fbdb81d027d0db32f Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 9 Nov 2020 09:59:06 -0800 Subject: [PATCH 112/179] made suffix nullable --- pkgs/yaml/lib/src/parser.dart | 2 +- pkgs/yaml/lib/src/token.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 267d7cadf..0f824be69 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -287,7 +287,7 @@ class Parser { throw YamlException('Undefined tag handle.', tagToken!.span); } - tag = tagDirective.prefix + tagToken!.suffix; + tag = tagDirective.prefix + (tagToken?.suffix ?? ''); } } diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 4f4172f26..447e979d7 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -96,7 +96,7 @@ class TagToken implements Token { final String? handle; /// The tag suffix, or `null`. - final String suffix; + final String? suffix; TagToken(this.span, this.handle, this.suffix); From 3f121a79406cd6898375efde7a933a558c90e4ab Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 9 Nov 2020 10:35:30 -0800 Subject: [PATCH 113/179] + notes --- pkgs/yaml/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 4f633990d..bf281c5e5 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,5 +1,5 @@ -## 2.3.0-dev - +## 2.3.0-nullsafety +* Updated to support 2.12.0 and null safety. * Allow `YamlNode`s to be wrapped with an optional `style` parameter. ## 2.2.1 From a369529f484953f0a9068d7557f726db0ef074cd Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 9 Nov 2020 14:33:59 -0800 Subject: [PATCH 114/179] bumped major version --- pkgs/yaml/CHANGELOG.md | 2 +- pkgs/yaml/pubspec.yaml | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index bf281c5e5..1cb12d6ad 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.3.0-nullsafety +## 3.0.0-nullsafety * Updated to support 2.12.0 and null safety. * Allow `YamlNode`s to be wrapped with an optional `style` parameter. diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 9b5b56855..10d100422 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 2.3.0-nullsafety.0 +version: 3.0.0-nullsafety.0 description: A parser for YAML, a human-friendly data serialization standard homepage: https://github.com/dart-lang/yaml @@ -17,3 +17,9 @@ dev_dependencies: path: ^1.8.0-nullsafety pedantic: ^1.10.0-nullsafety test: ^1.16.0-nullsafety + +dependency_overrides: + analyzer: ^0.40.0 + test: ^1.16.0-nullsafety + test_api: ^0.2.19-nullsafety + test_core: ^0.3.12-nullsafety From c4d667886b3cdfa8f39b0f0f4400419156c2a7ff Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 9 Nov 2020 14:39:12 -0800 Subject: [PATCH 115/179] fix suffix --- pkgs/yaml/lib/src/token.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 447e979d7..711950c57 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -95,8 +95,8 @@ class TagToken implements Token { /// The tag handle for named tags. final String? handle; - /// The tag suffix, or `null`. - final String? suffix; + /// The tag suffix. + final String suffix; TagToken(this.span, this.handle, this.suffix); From c6fe976bf076251e5a6d956437179f275179b58e Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 9 Nov 2020 14:42:53 -0800 Subject: [PATCH 116/179] fixed pair API --- pkgs/yaml/lib/src/parser.dart | 2 +- pkgs/yaml/lib/src/scanner.dart | 8 ++++---- pkgs/yaml/lib/src/utils.dart | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 0f824be69..625abe6b8 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -653,7 +653,7 @@ class Parser { ScalarEvent(location.pointSpan() as FileSpan, '', ScalarStyle.PLAIN); /// Parses directives. - Pair> _processDirectives() { + Pair> _processDirectives() { var token = _scanner.peek()!; VersionDirective? versionDirective; diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index fac955040..942e5782a 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -1146,8 +1146,8 @@ class Scanner { // Scan the leading line breaks to determine the indentation level if // needed. var pair = _scanBlockScalarBreaks(indent); - indent = pair.first!; - var trailingBreaks = pair.last!; + indent = pair.first; + var trailingBreaks = pair.last; // Scan the block scalar contents. var buffer = StringBuffer(); @@ -1198,8 +1198,8 @@ class Scanner { // Eat the following indentation and spaces. var pair = _scanBlockScalarBreaks(indent); - indent = pair.first!; - trailingBreaks = pair.last!; + indent = pair.first; + trailingBreaks = pair.last; } // Chomp the tail. diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 20210ef1a..2c69eade4 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -6,8 +6,8 @@ import 'package:source_span/source_span.dart'; /// A pair of values. class Pair { - final E? first; - final F? last; + final E first; + final F last; Pair(this.first, this.last); From a9345d237a22e05305a35d3ad5cea720bfca4abf Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 9 Nov 2020 14:50:54 -0800 Subject: [PATCH 117/179] make span non-nullable --- pkgs/yaml/lib/src/yaml_node.dart | 4 ++-- pkgs/yaml/test/yaml_test.dart | 32 ++++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index c8f294b4b..a02ea0f69 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -26,9 +26,9 @@ abstract class YamlNode { /// /// [SourceSpan.message] can be used to produce a human-friendly message about /// this node. - SourceSpan? get span => _span; + SourceSpan get span => _span; - SourceSpan? _span; + late SourceSpan _span; /// The inner value of this node. /// diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 3633a5e18..a0fb8f110 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -68,16 +68,16 @@ void main() { - 123 ''') as YamlList; - expect(yaml.span!.start.line, equals(0)); - expect(yaml.span!.start.column, equals(0)); - expect(yaml.span!.end.line, equals(3)); - expect(yaml.span!.end.column, equals(0)); + expect(yaml.span.start.line, equals(0)); + expect(yaml.span.start.column, equals(0)); + expect(yaml.span.end.line, equals(3)); + expect(yaml.span.end.column, equals(0)); var map = yaml.nodes.first as YamlMap; - expect(map.span!.start.line, equals(0)); - expect(map.span!.start.column, equals(2)); - expect(map.span!.end.line, equals(2)); - expect(map.span!.end.column, equals(0)); + expect(map.span.start.line, equals(0)); + expect(map.span.start.column, equals(2)); + expect(map.span.end.line, equals(2)); + expect(map.span.end.column, equals(0)); var key = map.nodes.keys.first; expect(key.span.start.line, equals(0)); @@ -86,16 +86,16 @@ void main() { expect(key.span.end.column, equals(5)); var value = map.nodes.values.first; - expect(value.span!.start.line, equals(1)); - expect(value.span!.start.column, equals(4)); - expect(value.span!.end.line, equals(1)); - expect(value.span!.end.column, equals(7)); + expect(value.span.start.line, equals(1)); + expect(value.span.start.column, equals(4)); + expect(value.span.end.line, equals(1)); + expect(value.span.end.column, equals(7)); var scalar = yaml.nodes.last; - expect(scalar.span!.start.line, equals(2)); - expect(scalar.span!.start.column, equals(2)); - expect(scalar.span!.end.line, equals(2)); - expect(scalar.span!.end.column, equals(5)); + expect(scalar.span.start.line, equals(2)); + expect(scalar.span.start.column, equals(2)); + expect(scalar.span.end.line, equals(2)); + expect(scalar.span.end.column, equals(5)); }); // The following tests are all taken directly from the YAML spec From e416b4b0568e0778bee0bb98b142e82e3a377e23 Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 9 Nov 2020 14:57:43 -0800 Subject: [PATCH 118/179] make sourcespan non-nullable --- pkgs/yaml/test/span_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/test/span_test.dart b/pkgs/yaml/test/span_test.dart index 6c666dd77..b8170e655 100644 --- a/pkgs/yaml/test/span_test.dart +++ b/pkgs/yaml/test/span_test.dart @@ -8,8 +8,8 @@ import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; -void _expectSpan(SourceSpan? source, String expected) { - final result = source!.message('message'); +void _expectSpan(SourceSpan source, String expected) { + final result = source.message('message'); printOnFailure("r'''\n$result'''"); expect(result, expected); From dffabd22c4a81ea5b1a3356c06bf1521c050a301 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 9 Nov 2020 15:16:32 -0800 Subject: [PATCH 119/179] Different pattern for _span so it doesn't need to be late Instead of marking the field nullable, or late, add a constructor in the abstract class and use it from the others. It was already impossible to correctly subclass `YamlNode` from outside the library, so the addition of a private constructor should not be breaking. --- pkgs/yaml/lib/src/yaml_node.dart | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index a02ea0f69..3e3ae8d1c 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -27,8 +27,9 @@ abstract class YamlNode { /// [SourceSpan.message] can be used to produce a human-friendly message about /// this node. SourceSpan get span => _span; + SourceSpan _span; - late SourceSpan _span; + YamlNode._(this._span); /// The inner value of this node. /// @@ -83,9 +84,8 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// Users of the library should not use this constructor. YamlMap.internal(Map nodes, SourceSpan span, this.style) - : nodes = UnmodifiableMapView(nodes) { - _span = span; - } + : nodes = UnmodifiableMapView(nodes), + super._(span); @override dynamic operator [](key) => nodes[key]?.value; @@ -134,9 +134,8 @@ class YamlList extends YamlNode with collection.ListMixin { /// Users of the library should not use this constructor. YamlList.internal(List nodes, SourceSpan span, this.style) - : nodes = UnmodifiableListView(nodes) { - _span = span; - } + : nodes = UnmodifiableListView(nodes), + super._(span); @override dynamic operator [](int index) => nodes[index].value; @@ -162,21 +161,20 @@ class YamlScalar extends YamlNode { /// [sourceUrl] is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - YamlScalar.wrap(this.value, {sourceUrl, this.style = ScalarStyle.ANY}) { + YamlScalar.wrap(this.value, {sourceUrl, this.style = ScalarStyle.ANY}) + : super._(NullSpan(sourceUrl)) { ArgumentError.checkNotNull(style, 'style'); - _span = NullSpan(sourceUrl); } /// Users of the library should not use this constructor. - YamlScalar.internal(this.value, ScalarEvent scalar) : style = scalar.style { - _span = scalar.span; - } + YamlScalar.internal(this.value, ScalarEvent scalar) + : style = scalar.style, + super._(scalar.span); /// Users of the library should not use this constructor. YamlScalar.internalWithSpan(this.value, SourceSpan span) - : style = ScalarStyle.ANY { - _span = span; - } + : style = ScalarStyle.ANY, + super._(span); @override String toString() => value.toString(); From 356f7a91566f5dfa6abbeffb7b703e29e5b5aa3a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 10 Nov 2020 11:19:31 -0800 Subject: [PATCH 120/179] Avoid a late FileSpan field Split a constructor into a factory and generative constructor to avoid a late field. --- pkgs/yaml/lib/src/loader.dart | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 370540609..c60e6736c 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -27,18 +27,20 @@ class Loader { /// The span of the entire stream emitted so far. FileSpan get span => _span; - late FileSpan _span; + FileSpan _span; /// Creates a loader that loads [source]. /// /// [sourceUrl] can be a String or a [Uri]. - Loader(String source, {sourceUrl}) - : _parser = Parser(source, sourceUrl: sourceUrl) { - var event = _parser.parse(); - _span = event.span; + factory Loader(String source, {sourceUrl}) { + var parser = Parser(source, sourceUrl: sourceUrl); + var event = parser.parse(); assert(event.type == EventType.streamStart); + return Loader._(parser, event.span); } + Loader._(this._parser, this._span); + /// Loads the next document from the stream. /// /// If there are no more documents, returns `null`. From 3c10f645f97d4b698c5f2151c348a951a2955bfd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 12 Nov 2020 17:44:01 -0800 Subject: [PATCH 121/179] Delete .test_config (dart-lang/yaml#99) --- pkgs/yaml/.test_config | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/yaml/.test_config diff --git a/pkgs/yaml/.test_config b/pkgs/yaml/.test_config deleted file mode 100644 index 412fc5c5c..000000000 --- a/pkgs/yaml/.test_config +++ /dev/null @@ -1,3 +0,0 @@ -{ - "test_package": true -} \ No newline at end of file From bcf372e809e8fb47dac5646fe62d38dd84a53c09 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 13 Nov 2020 17:08:16 -0800 Subject: [PATCH 122/179] Add static type to sourceUrl arguments (dart-lang/yaml#98) Closes dart-lang/yaml#97 --- pkgs/yaml/CHANGELOG.md | 5 ++++- pkgs/yaml/lib/src/loader.dart | 4 +--- pkgs/yaml/lib/src/parser.dart | 4 +--- pkgs/yaml/lib/src/scanner.dart | 4 +--- pkgs/yaml/lib/yaml.dart | 14 +++++++------- pkgs/yaml/pubspec.yaml | 7 ++++++- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 1cb12d6ad..5817dd0ae 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,6 +1,9 @@ -## 3.0.0-nullsafety +## 3.0.0-nullsafety.0 + * Updated to support 2.12.0 and null safety. * Allow `YamlNode`s to be wrapped with an optional `style` parameter. +* **BREAKING** The `sourceUrl` named argument is statically typed as `Uri` + instead of allowing `String` or `Uri`. ## 2.2.1 diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index c60e6736c..733322778 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -30,9 +30,7 @@ class Loader { FileSpan _span; /// Creates a loader that loads [source]. - /// - /// [sourceUrl] can be a String or a [Uri]. - factory Loader(String source, {sourceUrl}) { + factory Loader(String source, {Uri? sourceUrl}) { var parser = Parser(source, sourceUrl: sourceUrl); var event = parser.parse(); assert(event.type == EventType.streamStart); diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 625abe6b8..3443e2edd 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -35,9 +35,7 @@ class Parser { bool get isDone => _state == _State.END; /// Creates a parser that parses [source]. - /// - /// [sourceUrl] can be a String or a [Uri]. - Parser(String source, {sourceUrl}) + Parser(String source, {Uri? sourceUrl}) : _scanner = Scanner(source, sourceUrl: sourceUrl); /// Consumes and returns the next event. diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 942e5782a..a9f64be2f 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -288,9 +288,7 @@ class Scanner { } /// Creates a scanner that scans [source]. - /// - /// [sourceUrl] can be a String or a [Uri]. - Scanner(String source, {sourceUrl}) + Scanner(String source, {Uri? sourceUrl}) : _scanner = SpanScanner.eager(source, sourceUrl: sourceUrl); /// Consumes and returns the next token. diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 2ef65e7d7..f80489a54 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -29,8 +29,8 @@ export 'src/yaml_node.dart' hide setSpan; /// operation. /// /// If [sourceUrl] is passed, it's used as the URL from which the YAML -/// originated for error reporting. It can be a [String], a [Uri], or `null`. -dynamic loadYaml(String yaml, {sourceUrl}) => +/// originated for error reporting. +dynamic loadYaml(String yaml, {Uri? sourceUrl}) => loadYamlNode(yaml, sourceUrl: sourceUrl).value; /// Loads a single document from a YAML string as a [YamlNode]. @@ -38,7 +38,7 @@ dynamic loadYaml(String yaml, {sourceUrl}) => /// This is just like [loadYaml], except that where [loadYaml] would return a /// normal Dart value this returns a [YamlNode] instead. This allows the caller /// to be confident that the return value will always be a [YamlNode]. -YamlNode loadYamlNode(String yaml, {sourceUrl}) => +YamlNode loadYamlNode(String yaml, {Uri? sourceUrl}) => loadYamlDocument(yaml, sourceUrl: sourceUrl).contents; /// Loads a single document from a YAML string as a [YamlDocument]. @@ -46,7 +46,7 @@ YamlNode loadYamlNode(String yaml, {sourceUrl}) => /// This is just like [loadYaml], except that where [loadYaml] would return a /// normal Dart value this returns a [YamlDocument] instead. This allows the /// caller to access document metadata. -YamlDocument loadYamlDocument(String yaml, {sourceUrl}) { +YamlDocument loadYamlDocument(String yaml, {Uri? sourceUrl}) { var loader = Loader(yaml, sourceUrl: sourceUrl); var document = loader.load(); if (document == null) { @@ -74,8 +74,8 @@ YamlDocument loadYamlDocument(String yaml, {sourceUrl}) { /// operation. /// /// If [sourceUrl] is passed, it's used as the URL from which the YAML -/// originated for error reporting. It can be a [String], a [Uri], or `null`. -YamlList loadYamlStream(String yaml, {sourceUrl}) { +/// originated for error reporting. +YamlList loadYamlStream(String yaml, {Uri? sourceUrl}) { var loader = Loader(yaml, sourceUrl: sourceUrl); var documents = []; @@ -97,7 +97,7 @@ YamlList loadYamlStream(String yaml, {sourceUrl}) { /// /// This is like [loadYamlStream], except that it returns [YamlDocument]s with /// metadata wrapping the document contents. -List loadYamlDocuments(String yaml, {sourceUrl}) { +List loadYamlDocuments(String yaml, {Uri? sourceUrl}) { var loader = Loader(yaml, sourceUrl: sourceUrl); var documents = []; diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 10d100422..411765745 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -18,8 +18,13 @@ dev_dependencies: pedantic: ^1.10.0-nullsafety test: ^1.16.0-nullsafety + # Temporary deps to allow overrides + test_core: any + test_api: any + analyzer: any + dependency_overrides: - analyzer: ^0.40.0 + analyzer: ^0.41.0 test: ^1.16.0-nullsafety test_api: ^0.2.19-nullsafety test_core: ^0.3.12-nullsafety From 9324bd0d2cfcc35b4fa065570deab189076291db Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Thu, 14 Jan 2021 17:38:33 +0100 Subject: [PATCH 123/179] Migrate to GitHub Actions (dart-lang/yaml#104) * Delete .travis.yml --- pkgs/yaml/.github/workflows/test-package.yml | 64 ++++++++++++++++++++ pkgs/yaml/.travis.yml | 23 ------- pkgs/yaml/README.md | 2 +- 3 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 pkgs/yaml/.github/workflows/test-package.yml delete mode 100644 pkgs/yaml/.travis.yml diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml new file mode 100644 index 000000000..e55702c22 --- /dev/null +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -0,0 +1,64 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.1 + with: + channel: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.1 + with: + channel: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/yaml/.travis.yml b/pkgs/yaml/.travis.yml deleted file mode 100644 index e0a5b905b..000000000 --- a/pkgs/yaml/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: dart - -dart: - - dev - -dart_task: - - test: -p vm - xvfb: false - - test: -p chrome - - dartanalyzer: --fatal-warnings --fatal-infos . - -matrix: - include: - - dart: dev - dart_task: dartfmt - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index e6f7aa67e..dbf86070b 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -1,7 +1,7 @@ A parser for [YAML](https://yaml.org/). [![Pub Package](https://img.shields.io/pub/v/yaml.svg)](https://pub.dev/packages/yaml) -[![Build Status](https://travis-ci.org/dart-lang/yaml.svg?branch=master)](https://travis-ci.org/dart-lang/yaml) +[![Build Status](https://github.com/dart-lang/yaml/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/yaml/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) Use `loadYaml` to load a single document, or `loadYamlStream` to load a stream of documents. For example: From 3fcf0723c9110a3050341f259203e20e18ea0196 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 5 Feb 2021 11:06:51 -0800 Subject: [PATCH 124/179] stable null safety release (dart-lang/yaml#106) --- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/pubspec.yaml | 25 +++++++------------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 5817dd0ae..9d6fef455 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.0 + +* Stable null safety release. + ## 3.0.0-nullsafety.0 * Updated to support 2.12.0 and null safety. diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 411765745..069d3da79 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 3.0.0-nullsafety.0 +version: 3.0.0 description: A parser for YAML, a human-friendly data serialization standard homepage: https://github.com/dart-lang/yaml @@ -8,23 +8,12 @@ environment: sdk: '>=2.12.0-0 <3.0.0' dependencies: - charcode: ^1.2.0-nullsafety - collection: ^1.15.0-nullsafety - source_span: ^1.8.0-nullsafety - string_scanner: ^1.1.0-nullsafety + charcode: ^1.2.0 + collection: ^1.15.0 + source_span: ^1.8.0 + string_scanner: ^1.1.0 dev_dependencies: - path: ^1.8.0-nullsafety - pedantic: ^1.10.0-nullsafety + path: ^1.8.0 + pedantic: ^1.10.0 test: ^1.16.0-nullsafety - - # Temporary deps to allow overrides - test_core: any - test_api: any - analyzer: any - -dependency_overrides: - analyzer: ^0.41.0 - test: ^1.16.0-nullsafety - test_api: ^0.2.19-nullsafety - test_core: ^0.3.12-nullsafety From a316e3f30a92a8a9d8f968fe9e2e360d3c06b1b0 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Wed, 13 Jan 2021 14:40:27 +0000 Subject: [PATCH 125/179] Attempt to recover from invalid YAML --- pkgs/yaml/lib/src/loader.dart | 4 +-- pkgs/yaml/lib/src/parser.dart | 4 +-- pkgs/yaml/lib/src/scanner.dart | 15 ++++++-- pkgs/yaml/lib/yaml.dart | 16 +++++---- pkgs/yaml/test/yaml_test.dart | 63 ++++++++++++++++++++++++++++++++++ 5 files changed, 89 insertions(+), 13 deletions(-) diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 733322778..dafc59b9c 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -30,8 +30,8 @@ class Loader { FileSpan _span; /// Creates a loader that loads [source]. - factory Loader(String source, {Uri? sourceUrl}) { - var parser = Parser(source, sourceUrl: sourceUrl); + factory Loader(String source, {Uri? sourceUrl, bool recover = false}) { + var parser = Parser(source, sourceUrl: sourceUrl, recover: recover); var event = parser.parse(); assert(event.type == EventType.streamStart); return Loader._(parser, event.span); diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 3443e2edd..695c1d055 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -35,8 +35,8 @@ class Parser { bool get isDone => _state == _State.END; /// Creates a parser that parses [source]. - Parser(String source, {Uri? sourceUrl}) - : _scanner = Scanner(source, sourceUrl: sourceUrl); + Parser(String source, {Uri? sourceUrl, bool recover = false}) + : _scanner = Scanner(source, sourceUrl: sourceUrl, recover: recover); /// Consumes and returns the next event. Event parse() { diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index a9f64be2f..171364ca1 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -89,6 +89,9 @@ class Scanner { static const LETTER_CAP_X = 0x58; static const LETTER_CAP_Z = 0x5A; + /// Whether this scanner should attempt to recover when parsing invalid YAML. + final bool _recover; + /// The underlying [SpanScanner] used to read characters from the source text. /// /// This is also used to track line and column information and to generate @@ -288,8 +291,9 @@ class Scanner { } /// Creates a scanner that scans [source]. - Scanner(String source, {Uri? sourceUrl}) - : _scanner = SpanScanner.eager(source, sourceUrl: sourceUrl); + Scanner(String source, {Uri? sourceUrl, bool recover = false}) + : _recover = recover, + _scanner = SpanScanner.eager(source, sourceUrl: sourceUrl); /// Consumes and returns the next token. Token scan() { @@ -486,7 +490,12 @@ class Scanner { if (key.line == _scanner.line) continue; if (key.required) { - throw YamlException("Expected ':'.", _scanner.emptySpan); + if (_recover) { + _tokens.insert(key.tokenNumber - _tokensParsed, + Token(TokenType.key, key.location.pointSpan() as FileSpan)); + } else { + throw YamlException("Expected ':'.", _scanner.emptySpan); + } } _simpleKeys[i] = null; diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index f80489a54..988de2db8 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -30,24 +30,28 @@ export 'src/yaml_node.dart' hide setSpan; /// /// If [sourceUrl] is passed, it's used as the URL from which the YAML /// originated for error reporting. -dynamic loadYaml(String yaml, {Uri? sourceUrl}) => - loadYamlNode(yaml, sourceUrl: sourceUrl).value; +/// +/// If [recover] is true, will attempt to recover from parse errors and may return +/// invalid or synthetic nodes. +dynamic loadYaml(String yaml, {Uri? sourceUrl, bool recover = false}) => + loadYamlNode(yaml, sourceUrl: sourceUrl, recover: recover).value; /// Loads a single document from a YAML string as a [YamlNode]. /// /// This is just like [loadYaml], except that where [loadYaml] would return a /// normal Dart value this returns a [YamlNode] instead. This allows the caller /// to be confident that the return value will always be a [YamlNode]. -YamlNode loadYamlNode(String yaml, {Uri? sourceUrl}) => - loadYamlDocument(yaml, sourceUrl: sourceUrl).contents; +YamlNode loadYamlNode(String yaml, {Uri? sourceUrl, bool recover = false}) => + loadYamlDocument(yaml, sourceUrl: sourceUrl, recover: recover).contents; /// Loads a single document from a YAML string as a [YamlDocument]. /// /// This is just like [loadYaml], except that where [loadYaml] would return a /// normal Dart value this returns a [YamlDocument] instead. This allows the /// caller to access document metadata. -YamlDocument loadYamlDocument(String yaml, {Uri? sourceUrl}) { - var loader = Loader(yaml, sourceUrl: sourceUrl); +YamlDocument loadYamlDocument(String yaml, + {Uri? sourceUrl, bool recover = false}) { + var loader = Loader(yaml, sourceUrl: sourceUrl, recover: recover); var document = loader.load(); if (document == null) { return YamlDocument.internal(YamlScalar.internalWithSpan(null, loader.span), diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index a0fb8f110..014da9653 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -61,6 +61,69 @@ void main() { }); }); + group('recovers', () { + test('from incomplete leading keys', () { + final yaml = cleanUpLiteral(r''' + dependencies: + zero + one: any + '''); + var result = loadYaml(yaml, recover: true); + expect( + result, + deepEquals({ + 'dependencies': { + 'zero': null, + 'one': 'any', + } + })); + // Skipped because this case is not currently handled. If it's the first + // package without the colon, because the value is indented from the line + // above, the whole `zero\n one` is treated as a scalar value. + }, skip: true); + test('from incomplete keys', () { + final yaml = cleanUpLiteral(r''' + dependencies: + one: any + two + three: + four + five: + 1.2.3 + six: 5.4.3 + '''); + var result = loadYaml(yaml, recover: true); + expect( + result, + deepEquals({ + 'dependencies': { + 'one': 'any', + 'two': null, + 'three': null, + 'four': null, + 'five': '1.2.3', + 'six': '5.4.3', + } + })); + }); + test('from incomplete trailing keys', () { + final yaml = cleanUpLiteral(r''' + dependencies: + six: 5.4.3 + seven + '''); + var result = loadYaml(yaml, recover: true); + expect( + result, + deepEquals({ + 'dependencies': { + 'six': '5.4.3', + 'seven': null, + } + })); + }); + }); + test('includes source span information', () { var yaml = loadYamlNode(r''' - foo: From 28b90a90b868dbea41d3a13d63bf4283f1aff0f4 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Mon, 8 Feb 2021 12:11:41 +0000 Subject: [PATCH 126/179] Add an "ErrorListener" to collect errors during parsing --- pkgs/yaml/lib/src/error_listener.dart | 33 +++++++++++++++++++++++++++ pkgs/yaml/lib/src/loader.dart | 7 ++++-- pkgs/yaml/lib/src/parser.dart | 9 ++++++-- pkgs/yaml/lib/src/scanner.dart | 18 +++++++++++++-- pkgs/yaml/lib/yaml.dart | 28 ++++++++++++++++++----- pkgs/yaml/test/utils.dart | 8 +++++++ pkgs/yaml/test/yaml_test.dart | 20 ++++++++++++++-- 7 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 pkgs/yaml/lib/src/error_listener.dart diff --git a/pkgs/yaml/lib/src/error_listener.dart b/pkgs/yaml/lib/src/error_listener.dart new file mode 100644 index 000000000..d15665557 --- /dev/null +++ b/pkgs/yaml/lib/src/error_listener.dart @@ -0,0 +1,33 @@ +import 'package:source_span/source_span.dart'; + +import 'yaml_exception.dart'; + +/// A listener that is notified of [YamlError]s during scanning/parsing. +abstract class ErrorListener { + /// This method is invoked when an [error] has been found in the YAML. + void onError(YamlError error); +} + +/// An error found in the YAML. +class YamlError { + /// A message describing the exception. + final String message; + + /// The span associated with this exception. + final FileSpan span; + + YamlError(this.message, this.span); +} + +extension YamlErrorExtensions on YamlError { + /// Creates a [YamlException] from a [YamlError]. + YamlException toException() => YamlException(message, span); +} + +/// An [ErrorListener] that collects all errors into [errors]. +class ErrorCollector extends ErrorListener { + final List errors = []; + + @override + void onError(YamlError error) => errors.add(error); +} diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index dafc59b9c..0056a6457 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -4,6 +4,7 @@ import 'package:charcode/ascii.dart'; import 'package:source_span/source_span.dart'; +import 'package:yaml/src/error_listener.dart'; import 'equality.dart'; import 'event.dart'; @@ -30,8 +31,10 @@ class Loader { FileSpan _span; /// Creates a loader that loads [source]. - factory Loader(String source, {Uri? sourceUrl, bool recover = false}) { - var parser = Parser(source, sourceUrl: sourceUrl, recover: recover); + factory Loader(String source, + {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) { + var parser = Parser(source, + sourceUrl: sourceUrl, recover: recover, errorListener: errorListener); var event = parser.parse(); assert(event.type == EventType.streamStart); return Loader._(parser, event.span); diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 695c1d055..2f759e955 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -4,6 +4,7 @@ import 'package:source_span/source_span.dart'; import 'package:string_scanner/string_scanner.dart'; +import 'package:yaml/src/error_listener.dart'; import 'event.dart'; import 'scanner.dart'; @@ -35,8 +36,12 @@ class Parser { bool get isDone => _state == _State.END; /// Creates a parser that parses [source]. - Parser(String source, {Uri? sourceUrl, bool recover = false}) - : _scanner = Scanner(source, sourceUrl: sourceUrl, recover: recover); + Parser(String source, + {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) + : _scanner = Scanner(source, + sourceUrl: sourceUrl, + recover: recover, + errorListener: errorListener); /// Consumes and returns the next event. Event parse() { diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 171364ca1..260da1c98 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -5,6 +5,7 @@ import 'package:collection/collection.dart'; import 'package:source_span/source_span.dart'; import 'package:string_scanner/string_scanner.dart'; +import 'package:yaml/src/error_listener.dart'; import 'style.dart'; import 'token.dart'; @@ -92,6 +93,9 @@ class Scanner { /// Whether this scanner should attempt to recover when parsing invalid YAML. final bool _recover; + /// A listener to report YAML errors to. + final ErrorListener? _errorListener; + /// The underlying [SpanScanner] used to read characters from the source text. /// /// This is also used to track line and column information and to generate @@ -291,8 +295,10 @@ class Scanner { } /// Creates a scanner that scans [source]. - Scanner(String source, {Uri? sourceUrl, bool recover = false}) + Scanner(String source, + {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) : _recover = recover, + _errorListener = errorListener, _scanner = SpanScanner.eager(source, sourceUrl: sourceUrl); /// Consumes and returns the next token. @@ -490,11 +496,12 @@ class Scanner { if (key.line == _scanner.line) continue; if (key.required) { + final error = _reportError("Expected ':'.", _scanner.emptySpan); if (_recover) { _tokens.insert(key.tokenNumber - _tokensParsed, Token(TokenType.key, key.location.pointSpan() as FileSpan)); } else { - throw YamlException("Expected ':'.", _scanner.emptySpan); + throw error.toException(); } } @@ -1633,6 +1640,13 @@ class Scanner { _scanner.readChar(); } } + + /// Reports an error to [_errorListener] and returns the [YamlError]. + YamlError _reportError(String message, FileSpan span) { + final error = YamlError("Expected ':'.", _scanner.emptySpan); + _errorListener?.onError(error); + return error; + } } /// A record of the location of a potential simple key. diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 988de2db8..dec4bc094 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -2,6 +2,7 @@ // 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. +import 'src/error_listener.dart'; import 'src/loader.dart'; import 'src/style.dart'; import 'src/yaml_document.dart'; @@ -33,16 +34,30 @@ export 'src/yaml_node.dart' hide setSpan; /// /// If [recover] is true, will attempt to recover from parse errors and may return /// invalid or synthetic nodes. -dynamic loadYaml(String yaml, {Uri? sourceUrl, bool recover = false}) => - loadYamlNode(yaml, sourceUrl: sourceUrl, recover: recover).value; +/// +/// If [errorListener] is supplied, its onError method will be called for each +/// error. If [recover] is false, parsing will end early so only the first error +/// may be emitted. +dynamic loadYaml(String yaml, + {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) => + loadYamlNode(yaml, + sourceUrl: sourceUrl, + recover: recover, + errorListener: errorListener) + .value; /// Loads a single document from a YAML string as a [YamlNode]. /// /// This is just like [loadYaml], except that where [loadYaml] would return a /// normal Dart value this returns a [YamlNode] instead. This allows the caller /// to be confident that the return value will always be a [YamlNode]. -YamlNode loadYamlNode(String yaml, {Uri? sourceUrl, bool recover = false}) => - loadYamlDocument(yaml, sourceUrl: sourceUrl, recover: recover).contents; +YamlNode loadYamlNode(String yaml, + {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) => + loadYamlDocument(yaml, + sourceUrl: sourceUrl, + recover: recover, + errorListener: errorListener) + .contents; /// Loads a single document from a YAML string as a [YamlDocument]. /// @@ -50,8 +65,9 @@ YamlNode loadYamlNode(String yaml, {Uri? sourceUrl, bool recover = false}) => /// normal Dart value this returns a [YamlDocument] instead. This allows the /// caller to access document metadata. YamlDocument loadYamlDocument(String yaml, - {Uri? sourceUrl, bool recover = false}) { - var loader = Loader(yaml, sourceUrl: sourceUrl, recover: recover); + {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) { + var loader = Loader(yaml, + sourceUrl: sourceUrl, recover: recover, errorListener: errorListener); var document = loader.load(); if (document == null) { return YamlDocument.internal(YamlScalar.internalWithSpan(null, loader.span), diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index ce0548142..0904458bc 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -4,6 +4,7 @@ import 'package:test/test.dart'; import 'package:yaml/src/equality.dart' as equality; +import 'package:yaml/src/error_listener.dart' show YamlError; import 'package:yaml/yaml.dart'; /// A matcher that validates that a closure or Future throws a [YamlException]. @@ -22,6 +23,13 @@ Map deepEqualsMap([Map? from]) { return map; } +/// Asserts that an error has the given message and starts at the given line/col. +void expectErrorAtLineCol(YamlError error, String message, int line, int col) { + expect(error.message, equals(message)); + expect(error.span.start.line, equals(line)); + expect(error.span.start.column, equals(col)); +} + /// Asserts that a string containing a single YAML document produces a given /// value when loaded. void expectYamlLoads(expected, String source) { diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 014da9653..dffb9d5c4 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:test/test.dart'; +import 'package:yaml/src/error_listener.dart'; import 'package:yaml/yaml.dart'; import 'utils.dart'; @@ -62,13 +63,18 @@ void main() { }); group('recovers', () { + var collector = ErrorCollector(); + setUp(() { + collector = ErrorCollector(); + }); + test('from incomplete leading keys', () { final yaml = cleanUpLiteral(r''' dependencies: zero one: any '''); - var result = loadYaml(yaml, recover: true); + var result = loadYaml(yaml, recover: true, errorListener: collector); expect( result, deepEquals({ @@ -77,6 +83,10 @@ void main() { 'one': 'any', } })); + expect(collector.errors.length, equals(1)); + // These errors are reported at the start of the next token (after the + // whitespace/newlines). + expectErrorAtLineCol(collector.errors[0], "Expected ':'.", 2, 2); // Skipped because this case is not currently handled. If it's the first // package without the colon, because the value is indented from the line // above, the whole `zero\n one` is treated as a scalar value. @@ -92,7 +102,7 @@ void main() { 1.2.3 six: 5.4.3 '''); - var result = loadYaml(yaml, recover: true); + var result = loadYaml(yaml, recover: true, errorListener: collector); expect( result, deepEquals({ @@ -105,6 +115,12 @@ void main() { 'six': '5.4.3', } })); + + expect(collector.errors.length, equals(2)); + // These errors are reported at the start of the next token (after the + // whitespace/newlines). + expectErrorAtLineCol(collector.errors[0], "Expected ':'.", 3, 2); + expectErrorAtLineCol(collector.errors[1], "Expected ':'.", 5, 2); }); test('from incomplete trailing keys', () { final yaml = cleanUpLiteral(r''' From ddd50e0f3c45e51a98b91dd0df6b72a4afd415db Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Mon, 8 Feb 2021 18:18:27 +0000 Subject: [PATCH 127/179] Use YamlExceptions directly + tidy up error reporting --- pkgs/yaml/lib/src/error_listener.dart | 24 +++--------------------- pkgs/yaml/lib/src/scanner.dart | 22 ++++++++++------------ pkgs/yaml/test/utils.dart | 8 ++++---- 3 files changed, 17 insertions(+), 37 deletions(-) diff --git a/pkgs/yaml/lib/src/error_listener.dart b/pkgs/yaml/lib/src/error_listener.dart index d15665557..c302a4d5b 100644 --- a/pkgs/yaml/lib/src/error_listener.dart +++ b/pkgs/yaml/lib/src/error_listener.dart @@ -1,33 +1,15 @@ -import 'package:source_span/source_span.dart'; - import 'yaml_exception.dart'; /// A listener that is notified of [YamlError]s during scanning/parsing. abstract class ErrorListener { /// This method is invoked when an [error] has been found in the YAML. - void onError(YamlError error); -} - -/// An error found in the YAML. -class YamlError { - /// A message describing the exception. - final String message; - - /// The span associated with this exception. - final FileSpan span; - - YamlError(this.message, this.span); -} - -extension YamlErrorExtensions on YamlError { - /// Creates a [YamlException] from a [YamlError]. - YamlException toException() => YamlException(message, span); + void onError(YamlException error); } /// An [ErrorListener] that collects all errors into [errors]. class ErrorCollector extends ErrorListener { - final List errors = []; + final List errors = []; @override - void onError(YamlError error) => errors.add(error); + void onError(YamlException error) => errors.add(error); } diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 260da1c98..e6e2062cf 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -496,13 +496,9 @@ class Scanner { if (key.line == _scanner.line) continue; if (key.required) { - final error = _reportError("Expected ':'.", _scanner.emptySpan); - if (_recover) { - _tokens.insert(key.tokenNumber - _tokensParsed, - Token(TokenType.key, key.location.pointSpan() as FileSpan)); - } else { - throw error.toException(); - } + _reportError(YamlException("Expected ':'.", _scanner.emptySpan)); + _tokens.insert(key.tokenNumber - _tokensParsed, + Token(TokenType.key, key.location.pointSpan() as FileSpan)); } _simpleKeys[i] = null; @@ -1641,11 +1637,13 @@ class Scanner { } } - /// Reports an error to [_errorListener] and returns the [YamlError]. - YamlError _reportError(String message, FileSpan span) { - final error = YamlError("Expected ':'.", _scanner.emptySpan); - _errorListener?.onError(error); - return error; + /// Reports a [YamlException] to [_errorListener] and if [_recover] is false, + /// throw the exception. + void _reportError(YamlException exception) { + _errorListener?.onError(exception); + if (!_recover) { + throw exception; + } } } diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index 0904458bc..f90ac5b3d 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -4,7 +4,6 @@ import 'package:test/test.dart'; import 'package:yaml/src/equality.dart' as equality; -import 'package:yaml/src/error_listener.dart' show YamlError; import 'package:yaml/yaml.dart'; /// A matcher that validates that a closure or Future throws a [YamlException]. @@ -24,10 +23,11 @@ Map deepEqualsMap([Map? from]) { } /// Asserts that an error has the given message and starts at the given line/col. -void expectErrorAtLineCol(YamlError error, String message, int line, int col) { +void expectErrorAtLineCol( + YamlException error, String message, int line, int col) { expect(error.message, equals(message)); - expect(error.span.start.line, equals(line)); - expect(error.span.start.column, equals(col)); + expect(error.span!.start.line, equals(line)); + expect(error.span!.start.column, equals(col)); } /// Asserts that a string containing a single YAML document produces a given From d394b0460a9e434ae10b483df03fc58dc1f330c6 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Thu, 11 Feb 2021 17:15:40 +0000 Subject: [PATCH 128/179] Add missing copyright --- pkgs/yaml/lib/src/error_listener.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/yaml/lib/src/error_listener.dart b/pkgs/yaml/lib/src/error_listener.dart index c302a4d5b..dac7d6361 100644 --- a/pkgs/yaml/lib/src/error_listener.dart +++ b/pkgs/yaml/lib/src/error_listener.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2021, 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. + import 'yaml_exception.dart'; /// A listener that is notified of [YamlError]s during scanning/parsing. From 72f8b0220bf36ae167bc95bffbac48c67034c150 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Fri, 12 Feb 2021 11:13:50 +0000 Subject: [PATCH 129/179] Disallow errorListener when not recovering, and don't call error listener if throwing --- pkgs/yaml/lib/src/parser.dart | 8 +++++++- pkgs/yaml/lib/src/scanner.dart | 6 +++--- pkgs/yaml/lib/yaml.dart | 8 +++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 2f759e955..aeeda4eec 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -36,9 +36,15 @@ class Parser { bool get isDone => _state == _State.END; /// Creates a parser that parses [source]. + /// + /// If [recover] is true, will attempt to recover from parse errors and may return + /// invalid or synthetic nodes. If [errorListener] is also supplied, its onError + /// method will be called for each error recovered from. It is not valid to + /// provide [errorListener] if [recover] is false. Parser(String source, {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) - : _scanner = Scanner(source, + : assert(recover || errorListener == null), + _scanner = Scanner(source, sourceUrl: sourceUrl, recover: recover, errorListener: errorListener); diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index e6e2062cf..5cb329a10 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -1637,13 +1637,13 @@ class Scanner { } } - /// Reports a [YamlException] to [_errorListener] and if [_recover] is false, - /// throw the exception. + /// Reports a [YamlException] to [_errorListener] if [_recover] is true, + /// otherwise throws the exception. void _reportError(YamlException exception) { - _errorListener?.onError(exception); if (!_recover) { throw exception; } + _errorListener?.onError(exception); } } diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index dec4bc094..d1507253a 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -33,11 +33,9 @@ export 'src/yaml_node.dart' hide setSpan; /// originated for error reporting. /// /// If [recover] is true, will attempt to recover from parse errors and may return -/// invalid or synthetic nodes. -/// -/// If [errorListener] is supplied, its onError method will be called for each -/// error. If [recover] is false, parsing will end early so only the first error -/// may be emitted. +/// invalid or synthetic nodes. If [errorListener] is also supplied, its onError +/// method will be called for each error recovered from. It is not valid to +/// provide [errorListener] if [recover] is false. dynamic loadYaml(String yaml, {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) => loadYamlNode(yaml, From 11f5131af7046cea5c7d4b3f833fb1a24fec8378 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Sat, 13 Feb 2021 18:43:33 +0000 Subject: [PATCH 130/179] Add note about recovery to changelog/update version --- pkgs/yaml/CHANGELOG.md | 7 +++++++ pkgs/yaml/pubspec.yaml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 9d6fef455..eb225af7b 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,10 @@ +## 3.1.0-dev + +`loadYaml` and related functions now accept a `recover` flag instructing the parser + to attempt to recover from parse errors and may return invalid or synthetic nodes. + When recovering, an `ErrorListener` can also be supplied to listen for errors that + are recovered from. + ## 3.0.0 * Stable null safety release. diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 069d3da79..adb1758e1 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 3.0.0 +version: 3.1.0-dev description: A parser for YAML, a human-friendly data serialization standard homepage: https://github.com/dart-lang/yaml From 77c54f34c74d7da6ff0aa8b7f69328a6b8bbd555 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Thu, 25 Feb 2021 17:14:26 +0100 Subject: [PATCH 131/179] Drop dependency on `package:charcode`. (dart-lang/yaml#109) Co-authored-by: Jacob MacDonald --- pkgs/yaml/CHANGELOG.md | 5 ++-- pkgs/yaml/lib/src/charcodes.dart | 45 ++++++++++++++++++++++++++++++++ pkgs/yaml/lib/src/loader.dart | 2 +- pkgs/yaml/pubspec.yaml | 3 +-- 4 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 pkgs/yaml/lib/src/charcodes.dart diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index eb225af7b..5676b6a65 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,9 +1,10 @@ -## 3.1.0-dev +## 3.1.0 -`loadYaml` and related functions now accept a `recover` flag instructing the parser +* `loadYaml` and related functions now accept a `recover` flag instructing the parser to attempt to recover from parse errors and may return invalid or synthetic nodes. When recovering, an `ErrorListener` can also be supplied to listen for errors that are recovered from. +* Drop dependency on `package:charcode`. ## 3.0.0 diff --git a/pkgs/yaml/lib/src/charcodes.dart b/pkgs/yaml/lib/src/charcodes.dart new file mode 100644 index 000000000..705da627b --- /dev/null +++ b/pkgs/yaml/lib/src/charcodes.dart @@ -0,0 +1,45 @@ +// Copyright (c) 2021, 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. + +/// Character `+`. +const int $plus = 0x2b; + +/// Character `-`. +const int $minus = 0x2d; + +/// Character `.`. +const int $dot = 0x2e; + +/// Character `0`. +const int $0 = 0x30; + +/// Character `9`. +const int $9 = 0x39; + +/// Character `F`. +const int $F = 0x46; + +/// Character `N`. +const int $N = 0x4e; + +/// Character `T`. +const int $T = 0x54; + +/// Character `f`. +const int $f = 0x66; + +/// Character `n`. +const int $n = 0x6e; + +/// Character `o`. +const int $o = 0x6f; + +/// Character `t`. +const int $t = 0x74; + +/// Character `x`. +const int $x = 0x78; + +/// Character `~`. +const int $tilde = 0x7e; diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 0056a6457..07f5c8b34 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -2,10 +2,10 @@ // 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. -import 'package:charcode/ascii.dart'; import 'package:source_span/source_span.dart'; import 'package:yaml/src/error_listener.dart'; +import 'charcodes.dart'; import 'equality.dart'; import 'event.dart'; import 'parser.dart'; diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index adb1758e1..b9d836ad4 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 3.1.0-dev +version: 3.1.0 description: A parser for YAML, a human-friendly data serialization standard homepage: https://github.com/dart-lang/yaml @@ -8,7 +8,6 @@ environment: sdk: '>=2.12.0-0 <3.0.0' dependencies: - charcode: ^1.2.0 collection: ^1.15.0 source_span: ^1.8.0 string_scanner: ^1.1.0 From e750623b2b3ad6e27edec5e81b97ee50dfe8791d Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Thu, 25 Feb 2021 08:17:46 -0800 Subject: [PATCH 132/179] prep to release 3.1.0 (dart-lang/yaml#110) From 92696fa6ddde08c202fc74420b394df986950151 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 9 Mar 2021 12:31:09 -0800 Subject: [PATCH 133/179] Update test-package.yml (dart-lang/yaml#111) --- pkgs/yaml/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index e55702c22..8c20eeb6d 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -23,9 +23,9 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.1 + - uses: dart-lang/setup-dart@v1.0 with: - channel: ${{ matrix.sdk }} + sdk: ${{ matrix.sdk }} - id: install name: Install dependencies run: dart pub get @@ -50,9 +50,9 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.1 + - uses: dart-lang/setup-dart@v1.0 with: - channel: ${{ matrix.sdk }} + sdk: ${{ matrix.sdk }} - id: install name: Install dependencies run: dart pub get From 772489602a2768ce2bd4105edd8abcd6b19a4525 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Tue, 30 Mar 2021 17:30:50 -0700 Subject: [PATCH 134/179] Update LICENSE Changes to comply with open source review --- pkgs/yaml/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/LICENSE b/pkgs/yaml/LICENSE index 5c60afea3..162572a44 100644 --- a/pkgs/yaml/LICENSE +++ b/pkgs/yaml/LICENSE @@ -1,4 +1,5 @@ -Copyright 2014, the Dart project authors. All rights reserved. +Copyright 2014, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From cd11012ee9bb62c1151de971665b7cbc5c1df2e6 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Wed, 1 Sep 2021 08:22:05 -0700 Subject: [PATCH 135/179] Fix pre-existing HintCode.UNNECESSARY_TYPE_CHECK_TRUE --- pkgs/yaml/lib/src/scanner.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 5cb329a10..fdf927763 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -309,7 +309,7 @@ class Scanner { var token = _tokens.removeFirst(); _tokenAvailable = false; _tokensParsed++; - _streamEndProduced = token is Token && token.type == TokenType.streamEnd; + _streamEndProduced = token.type == TokenType.streamEnd; return token; } From ee84d22f94b78689700b507ab5954b24994dec28 Mon Sep 17 00:00:00 2001 From: Jonas Finnemann Jensen Date: Tue, 21 Sep 2021 17:20:03 +0200 Subject: [PATCH 136/179] Simplify licensing --- pkgs/yaml/LICENSE | 41 +++++++++------------- pkgs/yaml/benchmark/benchmark.dart | 9 +++-- pkgs/yaml/example/example.dart | 9 +++-- pkgs/yaml/lib/src/charcodes.dart | 9 +++-- pkgs/yaml/lib/src/equality.dart | 9 +++-- pkgs/yaml/lib/src/error_listener.dart | 9 +++-- pkgs/yaml/lib/src/event.dart | 9 +++-- pkgs/yaml/lib/src/loader.dart | 9 +++-- pkgs/yaml/lib/src/null_span.dart | 9 +++-- pkgs/yaml/lib/src/parser.dart | 9 +++-- pkgs/yaml/lib/src/scanner.dart | 9 +++-- pkgs/yaml/lib/src/style.dart | 9 +++-- pkgs/yaml/lib/src/token.dart | 9 +++-- pkgs/yaml/lib/src/utils.dart | 9 +++-- pkgs/yaml/lib/src/yaml_document.dart | 9 +++-- pkgs/yaml/lib/src/yaml_exception.dart | 9 +++-- pkgs/yaml/lib/src/yaml_node.dart | 9 +++-- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 9 +++-- pkgs/yaml/lib/yaml.dart | 9 +++-- pkgs/yaml/libyaml-license.txt | 19 ---------- pkgs/yaml/test/span_test.dart | 9 +++-- pkgs/yaml/test/utils.dart | 9 +++-- pkgs/yaml/test/yaml_node_wrapper_test.dart | 9 +++-- pkgs/yaml/test/yaml_test.dart | 9 +++-- 24 files changed, 149 insertions(+), 109 deletions(-) delete mode 100644 pkgs/yaml/libyaml-license.txt diff --git a/pkgs/yaml/LICENSE b/pkgs/yaml/LICENSE index 162572a44..e7589cbd1 100644 --- a/pkgs/yaml/LICENSE +++ b/pkgs/yaml/LICENSE @@ -1,27 +1,20 @@ -Copyright 2014, the Dart project authors. +Copyright (c) 2014, the Dart project authors. +Copyright (c) 2006, Kirill Simonov. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google LLC nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/pkgs/yaml/benchmark/benchmark.dart b/pkgs/yaml/benchmark/benchmark.dart index f5dc9e763..adde6f8a7 100644 --- a/pkgs/yaml/benchmark/benchmark.dart +++ b/pkgs/yaml/benchmark/benchmark.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2015, 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. +// Copyright (c) 2015, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. library yaml.benchmark.benchmark; diff --git a/pkgs/yaml/example/example.dart b/pkgs/yaml/example/example.dart index 102d5b193..672ead958 100644 --- a/pkgs/yaml/example/example.dart +++ b/pkgs/yaml/example/example.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2020, 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. +// Copyright (c) 2020, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:yaml/yaml.dart'; diff --git a/pkgs/yaml/lib/src/charcodes.dart b/pkgs/yaml/lib/src/charcodes.dart index 705da627b..602d597cb 100644 --- a/pkgs/yaml/lib/src/charcodes.dart +++ b/pkgs/yaml/lib/src/charcodes.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2021, 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. +// Copyright (c) 2021, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. /// Character `+`. const int $plus = 0x2b; diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index b232eb9f6..edaef89a5 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'dart:collection'; diff --git a/pkgs/yaml/lib/src/error_listener.dart b/pkgs/yaml/lib/src/error_listener.dart index dac7d6361..a0a0d956a 100644 --- a/pkgs/yaml/lib/src/error_listener.dart +++ b/pkgs/yaml/lib/src/error_listener.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2021, 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. +// Copyright (c) 2021, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'yaml_exception.dart'; diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart index e8879eefc..0cf19cd08 100644 --- a/pkgs/yaml/lib/src/event.dart +++ b/pkgs/yaml/lib/src/event.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:source_span/source_span.dart'; diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 07f5c8b34..4ec601733 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:source_span/source_span.dart'; import 'package:yaml/src/error_listener.dart'; diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index 64b3551ed..badb4958c 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:source_span/source_span.dart'; diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index aeeda4eec..8a559c88a 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:source_span/source_span.dart'; import 'package:string_scanner/string_scanner.dart'; diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index fdf927763..fcf6d27bf 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:collection/collection.dart'; import 'package:source_span/source_span.dart'; diff --git a/pkgs/yaml/lib/src/style.dart b/pkgs/yaml/lib/src/style.dart index 6ddaf3dba..e3415d857 100644 --- a/pkgs/yaml/lib/src/style.dart +++ b/pkgs/yaml/lib/src/style.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. /// An enum of source scalar styles. class ScalarStyle { diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 711950c57..282d77338 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:source_span/source_span.dart'; diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 2c69eade4..66ef3ed94 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2013, 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. +// Copyright (c) 2013, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:source_span/source_span.dart'; diff --git a/pkgs/yaml/lib/src/yaml_document.dart b/pkgs/yaml/lib/src/yaml_document.dart index 65b9548df..da6aa1ec3 100644 --- a/pkgs/yaml/lib/src/yaml_document.dart +++ b/pkgs/yaml/lib/src/yaml_document.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'dart:collection'; diff --git a/pkgs/yaml/lib/src/yaml_exception.dart b/pkgs/yaml/lib/src/yaml_exception.dart index 1941f0238..1e6fb2e49 100644 --- a/pkgs/yaml/lib/src/yaml_exception.dart +++ b/pkgs/yaml/lib/src/yaml_exception.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2013, 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. +// Copyright (c) 2013, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:source_span/source_span.dart'; diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 3e3ae8d1c..02c843998 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -1,6 +1,9 @@ -// 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. +// Copyright (c) 2012, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'dart:collection' as collection; diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index 87328ba1c..fa6923d4a 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'dart:collection'; diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index d1507253a..5c1e72908 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -1,6 +1,9 @@ -// 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. +// Copyright (c) 2012, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'src/error_listener.dart'; import 'src/loader.dart'; diff --git a/pkgs/yaml/libyaml-license.txt b/pkgs/yaml/libyaml-license.txt deleted file mode 100644 index 050ced23f..000000000 --- a/pkgs/yaml/libyaml-license.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006 Kirill Simonov - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/pkgs/yaml/test/span_test.dart b/pkgs/yaml/test/span_test.dart index b8170e655..03b7f9c47 100644 --- a/pkgs/yaml/test/span_test.dart +++ b/pkgs/yaml/test/span_test.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2019, 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. +// Copyright (c) 2019, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'dart:convert'; diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index f90ac5b3d..0aeaea515 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -1,6 +1,9 @@ -// Copyright (c) 2014, 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. +// Copyright (c) 2014, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:test/test.dart'; import 'package:yaml/src/equality.dart' as equality; diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index e5d71cc54..a64ab58da 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -1,6 +1,9 @@ -// 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. +// Copyright (c) 2012, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index dffb9d5c4..a0cb553da 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -1,6 +1,9 @@ -// 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. +// Copyright (c) 2012, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. import 'package:test/test.dart'; import 'package:yaml/src/error_listener.dart'; From edcb0a9855cd92a443621afd6d9db4b065e4f446 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 14 Oct 2021 16:21:23 -0700 Subject: [PATCH 137/179] Move to pkg:lints (dart-lang/yaml#120) Co-authored-by: Jacob MacDonald --- pkgs/yaml/analysis_options.yaml | 55 +++++++++------------- pkgs/yaml/benchmark/benchmark.dart | 26 ++++------ pkgs/yaml/example/example.dart | 2 +- pkgs/yaml/lib/src/equality.dart | 6 +-- pkgs/yaml/lib/src/loader.dart | 4 +- pkgs/yaml/lib/src/parser.dart | 16 ++++--- pkgs/yaml/lib/src/scanner.dart | 29 +++++++----- pkgs/yaml/lib/src/style.dart | 2 + pkgs/yaml/lib/src/utils.dart | 3 +- pkgs/yaml/lib/src/yaml_node.dart | 4 +- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 15 +++--- pkgs/yaml/lib/yaml.dart | 8 ++-- pkgs/yaml/pubspec.yaml | 8 ++-- pkgs/yaml/test/utils.dart | 4 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 2 +- 15 files changed, 86 insertions(+), 98 deletions(-) diff --git a/pkgs/yaml/analysis_options.yaml b/pkgs/yaml/analysis_options.yaml index 7f965d234..b14bfc63b 100644 --- a/pkgs/yaml/analysis_options.yaml +++ b/pkgs/yaml/analysis_options.yaml @@ -1,43 +1,34 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: implicit-casts: false linter: rules: - - avoid_empty_else - - avoid_init_to_null - - avoid_null_checks_in_equality_operators + - avoid_catching_errors + - avoid_private_typedef_functions + - avoid_redundant_argument_values - avoid_unused_constructor_parameters - - await_only_futures - - camel_case_types - cancel_subscriptions - #- constant_identifier_names - - control_flow_in_finally - directives_ordering - - empty_catches - - empty_constructor_bodies - - empty_statements - - hash_and_equals - - implementation_imports - - iterable_contains_unrelated_type - - library_names - - library_prefixes - - list_remove_unrelated_type - - non_constant_identifier_names - - overridden_fields + - join_return_with_assignment + - lines_longer_than_80_chars + - missing_whitespace_between_adjacent_strings + - no_runtimeType_toString + - only_throw_errors - package_api_docs - - package_names - - package_prefixed_library_names - - prefer_equal_for_default_values - - prefer_final_fields - - prefer_generic_function_type_aliases - - prefer_is_not_empty - - slash_for_doc_comments + - prefer_asserts_in_initializer_lists + - prefer_const_declarations + - prefer_expression_function_bodies + - prefer_interpolation_to_compose_strings + - prefer_relative_imports + - prefer_single_quotes + - sort_pub_dependencies - test_types_in_equals - throw_in_finally - - type_init_formals - - unnecessary_brace_in_string_interps - - unnecessary_const - - unnecessary_new - - unrelated_type_equality_checks - - valid_regexps + - type_annotate_public_apis + - unnecessary_lambdas + - unnecessary_null_aware_assignments + - unnecessary_parenthesis + - unnecessary_statements + - use_is_even_rather_than_modulo + - use_string_buffers diff --git a/pkgs/yaml/benchmark/benchmark.dart b/pkgs/yaml/benchmark/benchmark.dart index adde6f8a7..bdb21dbd2 100644 --- a/pkgs/yaml/benchmark/benchmark.dart +++ b/pkgs/yaml/benchmark/benchmark.dart @@ -11,14 +11,13 @@ import 'dart:convert'; import 'dart:io'; import 'package:path/path.dart' as p; - import 'package:yaml/yaml.dart'; const numTrials = 100; const runsPerTrial = 1000; -final source = loadFile('input.yaml'); -final expected = loadFile('output.json'); +final source = _loadFile('input.yaml'); +final expected = _loadFile('output.json'); void main(List args) { var best = double.infinity; @@ -29,7 +28,7 @@ void main(List args) { var start = DateTime.now(); // For a single benchmark, convert the source multiple times. - var result; + Object? result; for (var j = 0; j < runsPerTrial; j++) { result = loadYaml(source); } @@ -51,27 +50,18 @@ void main(List args) { // Don't print the first run. It's always terrible since the VM hasn't // warmed up yet. if (i == 0) continue; - printResult("Run ${padLeft('#$i', 3)}", elapsed); + _printResult("Run ${'#$i'.padLeft(3, '')}", elapsed); } - printResult('Best ', best); + _printResult('Best ', best); } -String loadFile(String name) { +String _loadFile(String name) { var path = p.join(p.dirname(p.fromUri(Platform.script)), name); return File(path).readAsStringSync(); } -void printResult(String label, double time) { - print('$label: ${padLeft(time.toStringAsFixed(3), 4)}ms ' +void _printResult(String label, double time) { + print('$label: ${time.toStringAsFixed(3).padLeft(4, '0')}ms ' "${'=' * ((time * 100).toInt())}"); } - -String padLeft(input, int length) { - var result = input.toString(); - if (result.length < length) { - result = ' ' * (length - result.length) + result; - } - - return result; -} diff --git a/pkgs/yaml/example/example.dart b/pkgs/yaml/example/example.dart index 672ead958..bb283a3bb 100644 --- a/pkgs/yaml/example/example.dart +++ b/pkgs/yaml/example/example.dart @@ -8,6 +8,6 @@ import 'package:yaml/yaml.dart'; void main() { - var doc = loadYaml("YAML: YAML Ain't Markup Language"); + var doc = loadYaml("YAML: YAML Ain't Markup Language") as Map; print(doc['YAML']); } diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index edaef89a5..f0755ca69 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -19,7 +19,7 @@ Map deepEqualsMap() => /// /// This considers `NaN` values to be equivalent, handles self-referential /// structures, and considers [YamlScalar]s to be equal to their values. -bool deepEquals(obj1, obj2) => _DeepEquals().equals(obj1, obj2); +bool deepEquals(Object? obj1, Object? obj2) => _DeepEquals().equals(obj1, obj2); /// A class that provides access to the list of parent objects used for loop /// detection. @@ -28,7 +28,7 @@ class _DeepEquals { final _parents2 = []; /// Returns whether [obj1] and [obj2] are structurally equivalent. - bool equals(obj1, obj2) { + bool equals(Object? obj1, Object? obj2) { if (obj1 is YamlScalar) obj1 = obj1.value; if (obj2 is YamlScalar) obj2 = obj2.value; @@ -100,7 +100,7 @@ class _DeepEquals { /// This supports deep equality for maps and lists, including those with /// self-referential structures, and returns the same hash code for /// [YamlScalar]s and their values. -int deepHashCode(obj) { +int deepHashCode(Object? obj) { var parents = []; int _deepHashCode(value) { diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 4ec601733..f7cd6c9d7 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -6,10 +6,10 @@ // https://opensource.org/licenses/MIT. import 'package:source_span/source_span.dart'; -import 'package:yaml/src/error_listener.dart'; import 'charcodes.dart'; import 'equality.dart'; +import 'error_listener.dart'; import 'event.dart'; import 'parser.dart'; import 'yaml_document.dart'; @@ -91,7 +91,7 @@ class Loader { case EventType.mappingStart: return _loadMapping(firstEvent as MappingStartEvent); default: - throw 'Unreachable'; + throw StateError('Unreachable'); } } diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 8a559c88a..ddbfd4e60 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -5,10 +5,12 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. +// ignore_for_file: constant_identifier_names + import 'package:source_span/source_span.dart'; import 'package:string_scanner/string_scanner.dart'; -import 'package:yaml/src/error_listener.dart'; +import 'error_listener.dart'; import 'event.dart'; import 'scanner.dart'; import 'style.dart'; @@ -40,10 +42,10 @@ class Parser { /// Creates a parser that parses [source]. /// - /// If [recover] is true, will attempt to recover from parse errors and may return - /// invalid or synthetic nodes. If [errorListener] is also supplied, its onError - /// method will be called for each error recovered from. It is not valid to - /// provide [errorListener] if [recover] is false. + /// If [recover] is true, will attempt to recover from parse errors and may + /// return invalid or synthetic nodes. If [errorListener] is also supplied, + /// its onError method will be called for each error recovered from. It is not + /// valid to provide [errorListener] if [recover] is false. Parser(String source, {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) : assert(recover || errorListener == null), @@ -117,7 +119,7 @@ class Parser { case _State.FLOW_MAPPING_EMPTY_VALUE: return _parseFlowMappingValue(empty: true); default: - throw 'Unreachable'; + throw StateError('Unreachable'); } } @@ -226,7 +228,7 @@ class Parser { _scanner.scan(); return DocumentEndEvent(token.span, isImplicit: false); } else { - return DocumentEndEvent(token.span.start.pointSpan(), isImplicit: true); + return DocumentEndEvent(token.span.start.pointSpan()); } } diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index fcf6d27bf..e1c584f46 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -5,11 +5,13 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. +// ignore_for_file: constant_identifier_names + import 'package:collection/collection.dart'; import 'package:source_span/source_span.dart'; import 'package:string_scanner/string_scanner.dart'; -import 'package:yaml/src/error_listener.dart'; +import 'error_listener.dart'; import 'style.dart'; import 'token.dart'; import 'utils.dart'; @@ -291,11 +293,10 @@ class Scanner { /// indicator. /// /// If so, this sets the scanner's last match to that indicator. - bool get _isDocumentIndicator { - return _scanner.column == 0 && - _isBlankOrEndAt(3) && - (_scanner.matches('---') || _scanner.matches('...')); - } + bool get _isDocumentIndicator => + _scanner.column == 0 && + _isBlankOrEndAt(3) && + (_scanner.matches('---') || _scanner.matches('...')); /// Creates a scanner that scans [source]. Scanner(String source, @@ -407,7 +408,7 @@ class Scanner { _fetchAnchor(anchor: false); return; case AMPERSAND: - _fetchAnchor(anchor: true); + _fetchAnchor(); return; case EXCLAMATION: _fetchTag(); @@ -416,7 +417,7 @@ class Scanner { _fetchFlowScalar(singleQuote: true); return; case DOUBLE_QUOTE: - _fetchFlowScalar(singleQuote: false); + _fetchFlowScalar(); return; case VERTICAL_BAR: if (!_inBlockContext) _invalidScalarCharacter(); @@ -424,7 +425,7 @@ class Scanner { return; case RIGHT_ANGLE: if (!_inBlockContext) _invalidScalarCharacter(); - _fetchBlockScalar(literal: false); + _fetchBlockScalar(); return; case PERCENT: case AT: @@ -1679,9 +1680,13 @@ class _SimpleKey { /// Whether this key must exist for the document to be scanned. final bool required; - _SimpleKey(this.tokenNumber, this.line, this.column, this.location, - {required bool required}) - : required = required; + _SimpleKey( + this.tokenNumber, + this.line, + this.column, + this.location, { + required this.required, + }); } /// The ways to handle trailing whitespace for a block scalar. diff --git a/pkgs/yaml/lib/src/style.dart b/pkgs/yaml/lib/src/style.dart index e3415d857..4121f0978 100644 --- a/pkgs/yaml/lib/src/style.dart +++ b/pkgs/yaml/lib/src/style.dart @@ -5,6 +5,8 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. +// ignore_for_file: constant_identifier_names + /// An enum of source scalar styles. class ScalarStyle { /// No source style was specified. diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index 66ef3ed94..db4612c83 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -29,13 +29,14 @@ void warn(String message, [SourceSpan? span]) => /// [message] is the text of the warning. If [span] is passed, it's the portion /// of the document that the warning is associated with and should be included /// in the printed warning. -typedef YamlWarningCallback = Function(String message, [SourceSpan? span]); +typedef YamlWarningCallback = void Function(String message, [SourceSpan? span]); /// A callback for emitting a warning. /// /// In a very few cases, the YAML spec indicates that an implementation should /// emit a warning. To do so, it calls this callback. The default implementation /// prints a message using [print]. +// ignore: prefer_function_declarations_over_variables YamlWarningCallback yamlWarningCallback = (message, [SourceSpan? span]) { // TODO(nweiz): Print to stderr with color when issue 6943 is fixed and // dart:io is available. diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 02c843998..458a61f3b 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -91,7 +91,7 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { super._(span); @override - dynamic operator [](key) => nodes[key]?.value; + dynamic operator [](Object? key) => nodes[key]?.value; } // TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed. @@ -144,7 +144,7 @@ class YamlList extends YamlNode with collection.ListMixin { dynamic operator [](int index) => nodes[index].value; @override - operator []=(int index, value) { + void operator []=(int index, Object? value) { throw UnsupportedError('Cannot modify an unmodifiable List'); } } diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index fa6923d4a..5dbf486f7 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -19,7 +19,7 @@ class YamlMapWrapper extends MapBase with pkg_collection.UnmodifiableMapMixin implements YamlMap { @override - final style; + final CollectionStyle style; final Map _dartMap; @@ -39,10 +39,8 @@ class YamlMapWrapper extends MapBase {CollectionStyle style = CollectionStyle.ANY}) : this._(dartMap, NullSpan(sourceUrl), style: style); - YamlMapWrapper._(Map dartMap, SourceSpan span, - {this.style = CollectionStyle.ANY}) + YamlMapWrapper._(Map dartMap, this.span, {this.style = CollectionStyle.ANY}) : _dartMap = dartMap, - span = span, nodes = _YamlMapNodes(dartMap, span) { ArgumentError.checkNotNull(style, 'style'); } @@ -97,7 +95,7 @@ class _YamlMapNodes extends MapBase /// A wrapper that makes a normal Dart list behave like a [YamlList]. class YamlListWrapper extends ListBase implements YamlList { @override - final style; + final CollectionStyle style; final List _dartList; @@ -122,10 +120,9 @@ class YamlListWrapper extends ListBase implements YamlList { {CollectionStyle style = CollectionStyle.ANY}) : this._(dartList, NullSpan(sourceUrl), style: style); - YamlListWrapper._(List dartList, SourceSpan span, + YamlListWrapper._(List dartList, this.span, {this.style = CollectionStyle.ANY}) : _dartList = dartList, - span = span, nodes = _YamlListNodes(dartList, span) { ArgumentError.checkNotNull(style, 'style'); } @@ -139,7 +136,7 @@ class YamlListWrapper extends ListBase implements YamlList { } @override - operator []=(int index, value) { + void operator []=(int index, Object? value) { throw UnsupportedError('Cannot modify an unmodifiable List.'); } @@ -173,7 +170,7 @@ class _YamlListNodes extends ListBase { YamlNode operator [](int index) => _nodeForValue(_dartList[index], _span); @override - operator []=(int index, value) { + void operator []=(int index, Object? value) { throw UnsupportedError('Cannot modify an unmodifiable List.'); } diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 5c1e72908..96869d364 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -35,10 +35,10 @@ export 'src/yaml_node.dart' hide setSpan; /// If [sourceUrl] is passed, it's used as the URL from which the YAML /// originated for error reporting. /// -/// If [recover] is true, will attempt to recover from parse errors and may return -/// invalid or synthetic nodes. If [errorListener] is also supplied, its onError -/// method will be called for each error recovered from. It is not valid to -/// provide [errorListener] if [recover] is false. +/// If [recover] is true, will attempt to recover from parse errors and may +/// return invalid or synthetic nodes. If [errorListener] is also supplied, its +/// onError method will be called for each error recovered from. It is not valid +/// to provide [errorListener] if [recover] is false. dynamic loadYaml(String yaml, {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) => loadYamlNode(yaml, diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index b9d836ad4..ace14a411 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,11 +1,11 @@ name: yaml -version: 3.1.0 +version: 3.1.1-dev description: A parser for YAML, a human-friendly data serialization standard homepage: https://github.com/dart-lang/yaml environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: collection: ^1.15.0 @@ -13,6 +13,6 @@ dependencies: string_scanner: ^1.1.0 dev_dependencies: + lints: ^1.0.0 path: ^1.8.0 - pedantic: ^1.10.0 - test: ^1.16.0-nullsafety + test: ^1.16.0 diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index 0aeaea515..5b852340d 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -15,7 +15,7 @@ final Matcher throwsYamlException = throwsA(TypeMatcher()); /// Returns a matcher that asserts that the value equals [expected]. /// /// This handles recursive loops and considers `NaN` to equal itself. -Matcher deepEquals(expected) => predicate( +Matcher deepEquals(Object? expected) => predicate( (actual) => equality.deepEquals(actual, expected), 'equals $expected'); /// Constructs a new yaml.YamlMap, optionally from a normal Map. @@ -35,7 +35,7 @@ void expectErrorAtLineCol( /// Asserts that a string containing a single YAML document produces a given /// value when loaded. -void expectYamlLoads(expected, String source) { +void expectYamlLoads(Object? expected, String source) { var actual = loadYaml(cleanUpLiteral(source)); expect(actual, deepEquals(expected)); } diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index a64ab58da..a7bf6b16f 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -220,7 +220,7 @@ void main() { }); } -Matcher isNullSpan(sourceUrl) => predicate((SourceSpan span) { +Matcher isNullSpan(Object sourceUrl) => predicate((SourceSpan span) { expect(span, TypeMatcher()); expect(span.length, equals(0)); expect(span.text, isEmpty); From aab43c50af62e6d9c8153d6ba177c3da34a7063f Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 22 Apr 2022 08:34:27 -0700 Subject: [PATCH 138/179] Update pubspec.yaml --- pkgs/yaml/pubspec.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index ace14a411..270fc9b0f 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,8 +1,7 @@ name: yaml version: 3.1.1-dev - description: A parser for YAML, a human-friendly data serialization standard -homepage: https://github.com/dart-lang/yaml +repository: https://github.com/dart-lang/yaml environment: sdk: '>=2.12.0 <3.0.0' From b1d2dd028992af466314b43278332a414c7b424f Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 11 May 2022 10:02:20 -0700 Subject: [PATCH 139/179] prep for publishing 3.1.1 --- pkgs/yaml/CHANGELOG.md | 5 +++++ pkgs/yaml/README.md | 7 +++++-- pkgs/yaml/analysis_options.yaml | 2 ++ pkgs/yaml/pubspec.yaml | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 5676b6a65..d0623cd0b 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,8 @@ +## 3.1.1 + +* Switch to using package:lints. +* Populate the pubspec `repository` field. + ## 3.1.0 * `loadYaml` and related functions now accept a `recover` flag instructing the parser diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index dbf86070b..6f5be2882 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -1,7 +1,10 @@ +[![Build Status](https://github.com/dart-lang/yaml/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/yaml/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) +[![Pub Package](https://img.shields.io/pub/v/yaml.svg)](https://pub.dev/packages/yaml) +[![package publisher](https://img.shields.io/pub/publisher/yaml.svg)](https://pub.dev/packages/yaml/publisher) + A parser for [YAML](https://yaml.org/). -[![Pub Package](https://img.shields.io/pub/v/yaml.svg)](https://pub.dev/packages/yaml) -[![Build Status](https://github.com/dart-lang/yaml/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/yaml/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) +## Usage Use `loadYaml` to load a single document, or `loadYamlStream` to load a stream of documents. For example: diff --git a/pkgs/yaml/analysis_options.yaml b/pkgs/yaml/analysis_options.yaml index b14bfc63b..4137066d0 100644 --- a/pkgs/yaml/analysis_options.yaml +++ b/pkgs/yaml/analysis_options.yaml @@ -1,7 +1,9 @@ include: package:lints/recommended.yaml + analyzer: strong-mode: implicit-casts: false + linter: rules: - avoid_catching_errors diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 270fc9b0f..c97d33fe5 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 3.1.1-dev +version: 3.1.1 description: A parser for YAML, a human-friendly data serialization standard repository: https://github.com/dart-lang/yaml From 225d840335c651cb5f2e406c580db80cc035d163 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 15 Nov 2022 12:23:07 -0800 Subject: [PATCH 140/179] blast_repo fixes Dependabot GitHub Action --- pkgs/yaml/.github/dependabot.yml | 9 +++++++++ pkgs/yaml/.github/workflows/test-package.yml | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 pkgs/yaml/.github/dependabot.yml diff --git a/pkgs/yaml/.github/dependabot.yml b/pkgs/yaml/.github/dependabot.yml new file mode 100644 index 000000000..1603cdd9e --- /dev/null +++ b/pkgs/yaml/.github/dependabot.yml @@ -0,0 +1,9 @@ +# Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 8c20eeb6d..77b8b45e0 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From fbc32952b76a4355834360159181aa8be3b8a2bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 11:04:24 -0800 Subject: [PATCH 141/179] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/yaml#133) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 77b8b45e0..17a388968 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 5d7e342967f830a359cd3e19c2291d6a81f78a1d Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 10 Jan 2023 12:55:59 -0800 Subject: [PATCH 142/179] Migrate from no-implicit-casts to strict-casts (dart-lang/yaml#134) --- pkgs/yaml/analysis_options.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/analysis_options.yaml b/pkgs/yaml/analysis_options.yaml index 4137066d0..6307140ed 100644 --- a/pkgs/yaml/analysis_options.yaml +++ b/pkgs/yaml/analysis_options.yaml @@ -1,8 +1,8 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true linter: rules: From 684dfb205765393068c5afe7d09605cda1210747 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:32:30 -0800 Subject: [PATCH 143/179] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/yaml#136) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 17a388968..9bb619b3a 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 553fd0277bc8d6b8612abf4e75aaf5077a6b64fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:36:28 -0800 Subject: [PATCH 144/179] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/yaml#135) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 9bb619b3a..908a67ffd 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From 413ac98ce842b669dd7e7b91da92fe34d2df3c7d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 1 Mar 2023 10:54:27 -0800 Subject: [PATCH 145/179] benchmark: fix output.json (dart-lang/yaml#137) --- pkgs/yaml/benchmark/output.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/yaml/benchmark/output.json b/pkgs/yaml/benchmark/output.json index 054cef7cf..9e6cb8400 100644 --- a/pkgs/yaml/benchmark/output.json +++ b/pkgs/yaml/benchmark/output.json @@ -1 +1 @@ -{"verb":"RecommendCafes","recipe":[{"outputs":["Cafe[]"],"verb":"List"},{"outputs":["CafeWithMenu[]"],"verb":"Fetch","inputs":["Cafe[]"]},{"outputs":["DishOffering[]"],"verb":"Flatten","inputs":["CafeWithMenu[]"]},{"outputs":["DishOffering[]/Scored"],"verb":"Score","inputs":["DishOffering[]"]},{"verb":"Display","inputs":["DishOffering[]/Scored"]}],"tags":{"numbers":[{"int":12345},{"negative":-345},{"floating-point":345.678},{"hexidecimal":1194684},{"exponential":1230.15},{"octal":12}],"dates":[{"canonical":"2001-12-15T02:59:43.1Z"},{"iso8601":"2001-12-14t21:59:43.10-05:00"},{"spaced":"2001-12-14 21:59:43.10 -5"},{"date":"2002-12-14"}],"strings":[{"unicode":"Sosa did fine.☺"},{"control":"\b1998\t1999\t2000\n"},{"hex esc":"\r\n is \r\n"},{"single":"\"Howdy!\" he cried."},{"quoted":" # Not a 'comment'."},{"tie-fighter":"|\\-*-/|"},{"plain":"This unquoted scalar spans many lines."},{"quoted":"So does this quoted scalar.\n"},{"accomplishment":"Mark set a major league home run record in 1998.\n"},{"stats":"65 Home Runs\n0.278 Batting Average\n"}],"booleans":[true,false]}} \ No newline at end of file +{"verb":"RecommendCafes","recipe":[{"verb":"List","outputs":["Cafe[]"]},{"verb":"Fetch","inputs":["Cafe[]"],"outputs":["CafeWithMenu[]"]},{"verb":"Flatten","inputs":["CafeWithMenu[]"],"outputs":["DishOffering[]"]},{"verb":"Score","inputs":["DishOffering[]"],"outputs":["DishOffering[]/Scored"]},{"verb":"Display","inputs":["DishOffering[]/Scored"]}],"tags":{"booleans":[true,false],"dates":[{"canonical":"2001-12-15T02:59:43.1Z"},{"iso8601":"2001-12-14t21:59:43.10-05:00"},{"spaced":"2001-12-14 21:59:43.10 -5"},{"date":"2002-12-14"}],"numbers":[{"int":12345},{"negative":-345},{"floating-point":345.678},{"hexidecimal":1194684},{"exponential":1230.15},{"octal":12}],"strings":[{"unicode":"Sosa did fine.☺"},{"control":"\b1998\t1999\t2000\n"},{"hex esc":"\r\n is \r\n"},{"single":"\"Howdy!\" he cried."},{"quoted":" # Not a 'comment'."},{"tie-fighter":"|\\-*-/|"},{"plain":"This unquoted scalar spans many lines."},{"quoted":"So does this quoted scalar.\n"},{"accomplishment":"Mark set a major league home run record in 1998.\n"},{"stats":"65 Home Runs\n0.278 Batting Average\n"}]}} \ No newline at end of file From cdfe46eb4492e2bf224ab84bc8daff8f27144f46 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 1 Mar 2023 10:56:49 -0800 Subject: [PATCH 146/179] Require Dart 2.19, migrate to dart_flutter_team_lints, make associated fixes (dart-lang/yaml#138) --- pkgs/yaml/.github/workflows/test-package.yml | 2 +- pkgs/yaml/CHANGELOG.md | 4 ++++ pkgs/yaml/analysis_options.yaml | 18 ++---------------- pkgs/yaml/benchmark/benchmark.dart | 2 -- pkgs/yaml/lib/src/equality.dart | 8 ++++---- pkgs/yaml/lib/src/yaml_exception.dart | 2 +- pkgs/yaml/lib/src/yaml_node.dart | 12 ++++++------ pkgs/yaml/pubspec.yaml | 6 +++--- pkgs/yaml/test/yaml_node_wrapper_test.dart | 2 ++ pkgs/yaml/test/yaml_test.dart | 2 ++ 10 files changed, 25 insertions(+), 33 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 908a67ffd..20b28dece 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.19.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index d0623cd0b..2a4cc1687 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.1.2-dev + +* Require Dart 2.19 + ## 3.1.1 * Switch to using package:lints. diff --git a/pkgs/yaml/analysis_options.yaml b/pkgs/yaml/analysis_options.yaml index 6307140ed..6c0172bd9 100644 --- a/pkgs/yaml/analysis_options.yaml +++ b/pkgs/yaml/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: @@ -6,31 +6,17 @@ analyzer: linter: rules: - - avoid_catching_errors - avoid_private_typedef_functions - avoid_redundant_argument_values - avoid_unused_constructor_parameters - cancel_subscriptions - - directives_ordering - join_return_with_assignment - - lines_longer_than_80_chars - missing_whitespace_between_adjacent_strings - no_runtimeType_toString - - only_throw_errors - package_api_docs - - prefer_asserts_in_initializer_lists - prefer_const_declarations - prefer_expression_function_bodies - - prefer_interpolation_to_compose_strings - prefer_relative_imports - - prefer_single_quotes - - sort_pub_dependencies - test_types_in_equals - - throw_in_finally - - type_annotate_public_apis - - unnecessary_lambdas - - unnecessary_null_aware_assignments - - unnecessary_parenthesis - - unnecessary_statements - - use_is_even_rather_than_modulo - use_string_buffers + - use_super_parameters diff --git a/pkgs/yaml/benchmark/benchmark.dart b/pkgs/yaml/benchmark/benchmark.dart index bdb21dbd2..afc3c97ce 100644 --- a/pkgs/yaml/benchmark/benchmark.dart +++ b/pkgs/yaml/benchmark/benchmark.dart @@ -5,8 +5,6 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. -library yaml.benchmark.benchmark; - import 'dart:convert'; import 'dart:io'; diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index f0755ca69..77cf8e053 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -103,15 +103,15 @@ class _DeepEquals { int deepHashCode(Object? obj) { var parents = []; - int _deepHashCode(value) { + int deepHashCodeInner(value) { if (parents.any((parent) => identical(parent, value))) return -1; parents.add(value); try { if (value is Map) { var equality = const UnorderedIterableEquality(); - return equality.hash(value.keys.map(_deepHashCode)) ^ - equality.hash(value.values.map(_deepHashCode)); + return equality.hash(value.keys.map(deepHashCodeInner)) ^ + equality.hash(value.values.map(deepHashCodeInner)); } else if (value is Iterable) { return const IterableEquality().hash(value.map(deepHashCode)); } else if (value is YamlScalar) { @@ -124,5 +124,5 @@ int deepHashCode(Object? obj) { } } - return _deepHashCode(obj); + return deepHashCodeInner(obj); } diff --git a/pkgs/yaml/lib/src/yaml_exception.dart b/pkgs/yaml/lib/src/yaml_exception.dart index 1e6fb2e49..7aa5389fc 100644 --- a/pkgs/yaml/lib/src/yaml_exception.dart +++ b/pkgs/yaml/lib/src/yaml_exception.dart @@ -9,5 +9,5 @@ import 'package:source_span/source_span.dart'; /// An error thrown by the YAML processor. class YamlException extends SourceSpanFormatException { - YamlException(String message, SourceSpan? span) : super(message, span); + YamlException(super.message, super.span); } diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index 458a61f3b..fb10de3ec 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -61,7 +61,7 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { Map get value => this; @override - Iterable get keys => nodes.keys.map((node) => node.value); + Iterable get keys => nodes.keys.map((node) => (node as YamlNode).value); /// Creates an empty YamlMap. /// @@ -86,9 +86,9 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { YamlMapWrapper(dartMap, sourceUrl, style: style); /// Users of the library should not use this constructor. - YamlMap.internal(Map nodes, SourceSpan span, this.style) + YamlMap.internal(Map nodes, super.span, this.style) : nodes = UnmodifiableMapView(nodes), - super._(span); + super._(); @override dynamic operator [](Object? key) => nodes[key]?.value; @@ -136,9 +136,9 @@ class YamlList extends YamlNode with collection.ListMixin { YamlListWrapper(dartList, sourceUrl, style: style); /// Users of the library should not use this constructor. - YamlList.internal(List nodes, SourceSpan span, this.style) + YamlList.internal(List nodes, super.span, this.style) : nodes = UnmodifiableListView(nodes), - super._(span); + super._(); @override dynamic operator [](int index) => nodes[index].value; @@ -152,7 +152,7 @@ class YamlList extends YamlNode with collection.ListMixin { /// A wrapped scalar value parsed from YAML. class YamlScalar extends YamlNode { @override - final dynamic value; + final Object? value; /// The style used for the scalar in the original document. final ScalarStyle style; diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index c97d33fe5..899ed0fd1 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,10 +1,10 @@ name: yaml -version: 3.1.1 +version: 3.1.2-dev description: A parser for YAML, a human-friendly data serialization standard repository: https://github.com/dart-lang/yaml environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.19.0 <3.0.0' dependencies: collection: ^1.15.0 @@ -12,6 +12,6 @@ dependencies: string_scanner: ^1.1.0 dev_dependencies: - lints: ^1.0.0 + dart_flutter_team_lints: ^1.0.0 path: ^1.8.0 test: ^1.16.0 diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index a7bf6b16f..699066e7a 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -5,6 +5,8 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. +// ignore_for_file: avoid_dynamic_calls + import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index a0cb553da..d226924da 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -5,6 +5,8 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. +// ignore_for_file: avoid_dynamic_calls + import 'package:test/test.dart'; import 'package:yaml/src/error_listener.dart'; import 'package:yaml/yaml.dart'; From 4d64b66ce0020f4395d2bdde728297f04484af40 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 9 Mar 2023 09:22:07 -0800 Subject: [PATCH 147/179] revert updating the type for YamlScalar.value (dart-lang/yaml#139) --- pkgs/yaml/lib/src/equality.dart | 4 ++-- pkgs/yaml/lib/src/yaml_node.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index 77cf8e053..5492c4969 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -103,7 +103,7 @@ class _DeepEquals { int deepHashCode(Object? obj) { var parents = []; - int deepHashCodeInner(value) { + int deepHashCodeInner(Object? value) { if (parents.any((parent) => identical(parent, value))) return -1; parents.add(value); @@ -115,7 +115,7 @@ int deepHashCode(Object? obj) { } else if (value is Iterable) { return const IterableEquality().hash(value.map(deepHashCode)); } else if (value is YamlScalar) { - return value.value.hashCode; + return (value.value as Object?).hashCode; } else { return value.hashCode; } diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index fb10de3ec..c8f1e2304 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -152,7 +152,7 @@ class YamlList extends YamlNode with collection.ListMixin { /// A wrapped scalar value parsed from YAML. class YamlScalar extends YamlNode { @override - final Object? value; + final dynamic value; /// The style used for the scalar in the original document. final ScalarStyle style; From 4901d1c0e99d81834b26f88030e328fb3dfd7dec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:36:39 -0700 Subject: [PATCH 148/179] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/yaml#141) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 20b28dece..772d53beb 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 93826f1df351f96c15ebcac1342355715624c1bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:57:37 -0700 Subject: [PATCH 149/179] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/yaml#140) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 772d53beb..763267350 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 6dd79afabf3c39f3eb83b0f3b7447ad5dd9b282c Mon Sep 17 00:00:00 2001 From: Jonas Finnemann Jensen Date: Thu, 4 May 2023 14:33:11 +0200 Subject: [PATCH 150/179] Prepare release with topics (dart-lang/yaml#144) --- pkgs/yaml/CHANGELOG.md | 3 ++- pkgs/yaml/pubspec.yaml | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 2a4cc1687..2a78ef900 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,6 +1,7 @@ -## 3.1.2-dev +## 3.1.2 * Require Dart 2.19 +* Added `topics` in `pubspec.yaml`. ## 3.1.1 diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 899ed0fd1..a3290e1ba 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,7 +1,10 @@ name: yaml -version: 3.1.2-dev +version: 3.1.2 description: A parser for YAML, a human-friendly data serialization standard repository: https://github.com/dart-lang/yaml +topics: + - yaml + - config-format environment: sdk: '>=2.19.0 <3.0.0' From 69de2700f9a05977dbf139fb8698811b5e315b6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:27:29 -0700 Subject: [PATCH 151/179] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/yaml#142) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 763267350..0874bdd38 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From bace8a73eeecb486b638ed61dfc7028882f4c898 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 10 May 2023 02:46:24 -0700 Subject: [PATCH 152/179] Uncomment some tests (dart-lang/yaml#145) These tests had been commented out since the original commit in this repo even though most of them would pass. With these tests commented out the suite has an empty `group` which may become disallowed. https://github.com/dart-lang/test/issues/1961 Change double quotes to single quotes. Skip a test which is currently failing due to an error parsing a float value with a single digit. --- pkgs/yaml/CHANGELOG.md | 2 + pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/yaml_test.dart | 118 ++++++++++++++++------------------ 3 files changed, 60 insertions(+), 62 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 2a78ef900..69a6c9fe8 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,3 +1,5 @@ +## 3.1.3-wip + ## 3.1.2 * Require Dart 2.19 diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index a3290e1ba..1671b26a4 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 3.1.2 +version: 3.1.3-wip description: A parser for YAML, a human-friendly data serialization standard repository: https://github.com/dart-lang/yaml topics: diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index d226924da..bb35ba4b5 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -1804,70 +1804,66 @@ void main() { }); group('10.2: JSON Schema', () { - // test('[Example 10.4]', () { - // var doc = deepEqualsMap({"key with null value": null}); - // doc[null] = "value for null key"; - // expectYamlStreamLoads(doc, - // """ - // !!null null: value for null key - // key with null value: !!null null"""); - // }); - - // test('[Example 10.5]', () { - // expectYamlStreamLoads({ - // "YAML is a superset of JSON": true, - // "Pluto is a planet": false - // }, - // """ - // YAML is a superset of JSON: !!bool true - // Pluto is a planet: !!bool false"""); - // }); + test('[Example 10.4]', () { + var doc = deepEqualsMap({'key with null value': null}); + doc[null] = 'value for null key'; + expectYamlStreamLoads([doc], ''' + !!null null: value for null key + key with null value: !!null null'''); + }); - // test('[Example 10.6]', () { - // expectYamlStreamLoads({ - // "negative": -12, - // "zero": 0, - // "positive": 34 - // }, - // """ - // negative: !!int -12 - // zero: !!int 0 - // positive: !!int 34"""); - // }); + test('[Example 10.5]', () { + expectYamlStreamLoads([ + {'YAML is a superset of JSON': true, 'Pluto is a planet': false} + ], ''' + YAML is a superset of JSON: !!bool true + Pluto is a planet: !!bool false'''); + }); - // test('[Example 10.7]', () { - // expectYamlStreamLoads({ - // "negative": -1, - // "zero": 0, - // "positive": 23000, - // "infinity": infinity, - // "not a number": nan - // }, - // """ - // negative: !!float -1 - // zero: !!float 0 - // positive: !!float 2.3e4 - // infinity: !!float .inf - // not a number: !!float .nan"""); - // }); + test('[Example 10.6]', () { + expectYamlStreamLoads([ + {'negative': -12, 'zero': 0, 'positive': 34} + ], ''' + negative: !!int -12 + zero: !!int 0 + positive: !!int 34'''); + }); - // test('[Example 10.8]', () { - // expectYamlStreamLoads({ - // "A null": null, - // "Booleans": [true, false], - // "Integers": [0, -0, 3, -19], - // "Floats": [0, 0, 12000, -200000], - // // Despite being invalid in the JSON schema, these values are valid in - // // the core schema which this implementation supports. - // "Invalid": [ true, null, 7, 0x3A, 12.3] - // }, - // """ - // A null: null - // Booleans: [ true, false ] - // Integers: [ 0, -0, 3, -19 ] - // Floats: [ 0., -0.0, 12e03, -2E+05 ] - // Invalid: [ True, Null, 0o7, 0x3A, +12.3 ]"""); - // }); + test('[Example 10.7]', () { + expectYamlStreamLoads([ + { + 'negative': -1, + 'zero': 0, + 'positive': 23000, + 'infinity': infinity, + 'not a number': nan + } + ], ''' + negative: !!float -1 + zero: !!float 0 + positive: !!float 2.3e4 + infinity: !!float .inf + not a number: !!float .nan'''); + }, skip: 'Fails for single digit float'); + + test('[Example 10.8]', () { + expectYamlStreamLoads([ + { + 'A null': null, + 'Booleans': [true, false], + 'Integers': [0, -0, 3, -19], + 'Floats': [0, 0, 12000, -200000], + // Despite being invalid in the JSON schema, these values are valid in + // the core schema which this implementation supports. + 'Invalid': [true, null, 7, 0x3A, 12.3] + } + ], ''' + A null: null + Booleans: [ true, false ] + Integers: [ 0, -0, 3, -19 ] + Floats: [ 0., -0.0, 12e03, -2E+05 ] + Invalid: [ True, Null, 0o7, 0x3A, +12.3 ]'''); + }); }); group('10.3: Core Schema', () { From f7acbf3c5778aabd2ca5ef27bac4fa1d7167e1fb Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 23 May 2023 10:10:21 -0700 Subject: [PATCH 153/179] blast_repo fixes (dart-lang/yaml#146) dependabot --- pkgs/yaml/.github/dependabot.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/yaml/.github/dependabot.yml b/pkgs/yaml/.github/dependabot.yml index 1603cdd9e..725f03af2 100644 --- a/pkgs/yaml/.github/dependabot.yml +++ b/pkgs/yaml/.github/dependabot.yml @@ -3,7 +3,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From dfb433b9a18294c038f62dc0d2c12ee5ae3f0d3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 11:46:20 +0000 Subject: [PATCH 154/179] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/yaml#148) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 0874bdd38..4c8399a81 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 7b65a9e3d6148d5a167156c5a5c384ddfd63959d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:06:18 +0000 Subject: [PATCH 155/179] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/yaml#150) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 4c8399a81..8b1f4d4fb 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From ca725bf1a083a4ef23cb6c2c7ffe3e96d5790439 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:38:12 +0000 Subject: [PATCH 156/179] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/yaml#152) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 8b1f4d4fb..282ba5006 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 4c57dc38a9a04f29cea5d4d65850ebb69f8149e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:41:03 +0000 Subject: [PATCH 157/179] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/yaml#153) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚠️ **Dependabot is rebasing this PR** ⚠️ Rebasing might not happen immediately, so don't worry if this takes some time. Note: if you make any changes to this PR yourself, they will take precedence over the rebase. --- Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/yaml#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/yaml#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.0&new-version=1.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 282ba5006..367d5dea3 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From 476ea4ac4a50b2d001989eba53714f3cc984db73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 11:14:54 +0000 Subject: [PATCH 158/179] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/yaml#155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 367d5dea3..e0d4f73af 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From de85a1a40090406570650f045a3177153e69702e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 11:18:52 +0000 Subject: [PATCH 159/179] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/yaml#154) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/yaml#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/yaml#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index e0d4f73af..02786315a 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From 33fe339961fd62ae3216085cdd0af2bb383cbc63 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 11 Dec 2023 16:37:13 -0800 Subject: [PATCH 160/179] update lints, require Dart 3.0 (dart-lang/yaml#156) * switch expressions * dry up logic --- pkgs/yaml/.github/workflows/test-package.yml | 2 +- pkgs/yaml/CHANGELOG.md | 2 + pkgs/yaml/analysis_options.yaml | 3 - pkgs/yaml/lib/src/equality.dart | 10 +-- pkgs/yaml/lib/src/error_listener.dart | 2 +- pkgs/yaml/lib/src/event.dart | 1 + pkgs/yaml/lib/src/loader.dart | 90 +++++++------------- pkgs/yaml/lib/src/null_span.dart | 4 +- pkgs/yaml/lib/src/scanner.dart | 88 +++++++------------ pkgs/yaml/lib/src/style.dart | 2 + pkgs/yaml/lib/src/token.dart | 1 + pkgs/yaml/lib/src/yaml_node.dart | 18 ++-- pkgs/yaml/lib/src/yaml_node_wrapper.dart | 6 +- pkgs/yaml/lib/yaml.dart | 6 -- pkgs/yaml/pubspec.yaml | 4 +- pkgs/yaml/test/utils.dart | 4 +- pkgs/yaml/test/yaml_node_wrapper_test.dart | 28 +++--- 17 files changed, 109 insertions(+), 162 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 02786315a..4cb7d3a73 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.19.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 69a6c9fe8..c246967f5 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,5 +1,7 @@ ## 3.1.3-wip +* Require Dart 3.0 + ## 3.1.2 * Require Dart 2.19 diff --git a/pkgs/yaml/analysis_options.yaml b/pkgs/yaml/analysis_options.yaml index 6c0172bd9..369e38633 100644 --- a/pkgs/yaml/analysis_options.yaml +++ b/pkgs/yaml/analysis_options.yaml @@ -16,7 +16,4 @@ linter: - package_api_docs - prefer_const_declarations - prefer_expression_function_bodies - - prefer_relative_imports - - test_types_in_equals - use_string_buffers - - use_super_parameters diff --git a/pkgs/yaml/lib/src/equality.dart b/pkgs/yaml/lib/src/equality.dart index 5492c4969..c833dc608 100644 --- a/pkgs/yaml/lib/src/equality.dart +++ b/pkgs/yaml/lib/src/equality.dart @@ -24,8 +24,8 @@ bool deepEquals(Object? obj1, Object? obj2) => _DeepEquals().equals(obj1, obj2); /// A class that provides access to the list of parent objects used for loop /// detection. class _DeepEquals { - final _parents1 = []; - final _parents2 = []; + final _parents1 = []; + final _parents2 = []; /// Returns whether [obj1] and [obj2] are structurally equivalent. bool equals(Object? obj1, Object? obj2) { @@ -101,7 +101,7 @@ class _DeepEquals { /// self-referential structures, and returns the same hash code for /// [YamlScalar]s and their values. int deepHashCode(Object? obj) { - var parents = []; + var parents = []; int deepHashCodeInner(Object? value) { if (parents.any((parent) => identical(parent, value))) return -1; @@ -109,11 +109,11 @@ int deepHashCode(Object? obj) { parents.add(value); try { if (value is Map) { - var equality = const UnorderedIterableEquality(); + var equality = const UnorderedIterableEquality(); return equality.hash(value.keys.map(deepHashCodeInner)) ^ equality.hash(value.values.map(deepHashCodeInner)); } else if (value is Iterable) { - return const IterableEquality().hash(value.map(deepHashCode)); + return const IterableEquality().hash(value.map(deepHashCode)); } else if (value is YamlScalar) { return (value.value as Object?).hashCode; } else { diff --git a/pkgs/yaml/lib/src/error_listener.dart b/pkgs/yaml/lib/src/error_listener.dart index a0a0d956a..0498d6818 100644 --- a/pkgs/yaml/lib/src/error_listener.dart +++ b/pkgs/yaml/lib/src/error_listener.dart @@ -7,7 +7,7 @@ import 'yaml_exception.dart'; -/// A listener that is notified of [YamlError]s during scanning/parsing. +/// A listener that is notified of [YamlException]s during scanning/parsing. abstract class ErrorListener { /// This method is invoked when an [error] has been found in the YAML. void onError(YamlException error); diff --git a/pkgs/yaml/lib/src/event.dart b/pkgs/yaml/lib/src/event.dart index 0cf19cd08..1476311aa 100644 --- a/pkgs/yaml/lib/src/event.dart +++ b/pkgs/yaml/lib/src/event.dart @@ -7,6 +7,7 @@ import 'package:source_span/source_span.dart'; +import 'parser.dart'; import 'style.dart'; import 'yaml_document.dart'; diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index f7cd6c9d7..7cdf45a7e 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart @@ -80,20 +80,14 @@ class Loader { } /// Composes a node. - YamlNode _loadNode(Event firstEvent) { - switch (firstEvent.type) { - case EventType.alias: - return _loadAlias(firstEvent as AliasEvent); - case EventType.scalar: - return _loadScalar(firstEvent as ScalarEvent); - case EventType.sequenceStart: - return _loadSequence(firstEvent as SequenceStartEvent); - case EventType.mappingStart: - return _loadMapping(firstEvent as MappingStartEvent); - default: - throw StateError('Unreachable'); - } - } + YamlNode _loadNode(Event firstEvent) => switch (firstEvent.type) { + EventType.alias => _loadAlias(firstEvent as AliasEvent), + EventType.scalar => _loadScalar(firstEvent as ScalarEvent), + EventType.sequenceStart => + _loadSequence(firstEvent as SequenceStartEvent), + EventType.mappingStart => _loadMapping(firstEvent as MappingStartEvent), + _ => throw StateError('Unreachable') + }; /// Registers an anchor. void _registerAnchor(String? anchor, YamlNode node) { @@ -220,61 +214,37 @@ class Loader { // Dispatch on the first character. var firstChar = scalar.value.codeUnitAt(0); - switch (firstChar) { - case $dot: - case $plus: - case $minus: - return _parseNumber(scalar); - case $n: - case $N: - return length == 4 ? _parseNull(scalar) : null; - case $t: - case $T: - return length == 4 ? _parseBool(scalar) : null; - case $f: - case $F: - return length == 5 ? _parseBool(scalar) : null; - case $tilde: - return length == 1 ? YamlScalar.internal(null, scalar) : null; - default: - if (firstChar >= $0 && firstChar <= $9) return _parseNumber(scalar); - return null; - } + return switch (firstChar) { + $dot || $plus || $minus => _parseNumber(scalar), + $n || $N => length == 4 ? _parseNull(scalar) : null, + $t || $T => length == 4 ? _parseBool(scalar) : null, + $f || $F => length == 5 ? _parseBool(scalar) : null, + $tilde => length == 1 ? YamlScalar.internal(null, scalar) : null, + _ => (firstChar >= $0 && firstChar <= $9) ? _parseNumber(scalar) : null + }; } /// Parse a null scalar. /// /// Returns a Dart `null` if parsing fails. - YamlScalar? _parseNull(ScalarEvent scalar) { - switch (scalar.value) { - case '': - case 'null': - case 'Null': - case 'NULL': - case '~': - return YamlScalar.internal(null, scalar); - default: - return null; - } - } + YamlScalar? _parseNull(ScalarEvent scalar) => switch (scalar.value) { + '' || + 'null' || + 'Null' || + 'NULL' || + '~' => + YamlScalar.internal(null, scalar), + _ => null + }; /// Parse a boolean scalar. /// /// Returns `null` if parsing fails. - YamlScalar? _parseBool(ScalarEvent scalar) { - switch (scalar.value) { - case 'true': - case 'True': - case 'TRUE': - return YamlScalar.internal(true, scalar); - case 'false': - case 'False': - case 'FALSE': - return YamlScalar.internal(false, scalar); - default: - return null; - } - } + YamlScalar? _parseBool(ScalarEvent scalar) => switch (scalar.value) { + 'true' || 'True' || 'TRUE' => YamlScalar.internal(true, scalar), + 'false' || 'False' || 'FALSE' => YamlScalar.internal(false, scalar), + _ => null + }; /// Parses a numeric scalar. /// diff --git a/pkgs/yaml/lib/src/null_span.dart b/pkgs/yaml/lib/src/null_span.dart index badb4958c..49e1a1c90 100644 --- a/pkgs/yaml/lib/src/null_span.dart +++ b/pkgs/yaml/lib/src/null_span.dart @@ -7,6 +7,8 @@ import 'package:source_span/source_span.dart'; +import 'yaml_node.dart'; + /// A [SourceSpan] with no location information. /// /// This is used with [YamlMap.wrap] and [YamlList.wrap] to provide means of @@ -20,5 +22,5 @@ class NullSpan extends SourceSpanMixin { @override final text = ''; - NullSpan(sourceUrl) : start = SourceLocation(0, sourceUrl: sourceUrl); + NullSpan(Object? sourceUrl) : start = SourceLocation(0, sourceUrl: sourceUrl); } diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index e1c584f46..4bf0b9306 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -124,7 +124,7 @@ class Scanner { /// The number of tokens that have been emitted. /// - /// This doesn't count tokens in [tokens]. + /// This doesn't count tokens in [_tokens]. var _tokensParsed = 0; /// Whether the next token in [_tokens] is ready to be returned. @@ -249,21 +249,12 @@ class Scanner { /// See http://yaml.org/spec/1.2/spec.html#nb-char. bool get _isNonBreak { var char = _scanner.peekChar(); - if (char == null) return false; - switch (char) { - case LF: - case CR: - case BOM: - return false; - case TAB: - case NEL: - return true; - default: - return (char >= 0x00020 && char <= 0x00007E) || - (char >= 0x000A0 && char <= 0x00D7FF) || - (char >= 0x0E000 && char <= 0x00FFFD) || - (char >= 0x10000 && char <= 0x10FFFF); - } + return switch (char) { + null => false, + LF || CR || BOM => false, + TAB || NEL => true, + _ => _isStandardCharacter(char), + }; } /// Whether the character at the current position is a printable character @@ -272,21 +263,12 @@ class Scanner { /// See http://yaml.org/spec/1.2/spec.html#nb-char. bool get _isNonSpace { var char = _scanner.peekChar(); - if (char == null) return false; - switch (char) { - case LF: - case CR: - case BOM: - case SP: - return false; - case NEL: - return true; - default: - return (char >= 0x00020 && char <= 0x00007E) || - (char >= 0x000A0 && char <= 0x00D7FF) || - (char >= 0x0E000 && char <= 0x00FFFD) || - (char >= 0x10000 && char <= 0x10FFFF); - } + return switch (char) { + null => false, + LF || CR || BOM || SP => false, + NEL => true, + _ => _isStandardCharacter(char), + }; } /// Returns Whether or not the current character begins a documentation @@ -830,7 +812,7 @@ class Scanner { } } - /// Scans a [TokenType.YAML_DIRECTIVE] or [TokenType.tagDirective] token. + /// Scans a [TokenType.versionDirective] or [TokenType.tagDirective] token. /// /// %YAML 1.2 # a comment \n /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1593,32 +1575,28 @@ class Scanner { /// See http://yaml.org/spec/1.2/spec.html#ns-plain-safe(c). bool _isPlainSafeAt(int offset) { var char = _scanner.peekChar(offset); - switch (char) { - case COMMA: - case LEFT_SQUARE: - case RIGHT_SQUARE: - case LEFT_CURLY: - case RIGHT_CURLY: + return switch (char) { + null => false, + COMMA || + LEFT_SQUARE || + RIGHT_SQUARE || + LEFT_CURLY || + RIGHT_CURLY => // These characters are delimiters in a flow context and thus are only // safe in a block context. - return _inBlockContext; - case SP: - case TAB: - case LF: - case CR: - case BOM: - return false; - case NEL: - return true; - default: - return char != null && - ((char >= 0x00020 && char <= 0x00007E) || - (char >= 0x000A0 && char <= 0x00D7FF) || - (char >= 0x0E000 && char <= 0x00FFFD) || - (char >= 0x10000 && char <= 0x10FFFF)); - } + _inBlockContext, + SP || TAB || LF || CR || BOM => false, + NEL => true, + _ => _isStandardCharacter(char) + }; } + bool _isStandardCharacter(int char) => + (char >= 0x00020 && char <= 0x00007E) || + (char >= 0x000A0 && char <= 0x00D7FF) || + (char >= 0x0E000 && char <= 0x00FFFD) || + (char >= 0x10000 && char <= 0x10FFFF); + /// Returns the hexidecimal value of [char]. int _asHex(int char) { if (char <= NUMBER_9) return char - NUMBER_0; @@ -1656,7 +1634,7 @@ class _SimpleKey { /// The index of the token that begins the simple key. /// /// This is the index relative to all tokens emitted, rather than relative to - /// [_tokens]. + /// [location]. final int tokenNumber; /// The source location of the beginning of the simple key. diff --git a/pkgs/yaml/lib/src/style.dart b/pkgs/yaml/lib/src/style.dart index 4121f0978..96c3b94d8 100644 --- a/pkgs/yaml/lib/src/style.dart +++ b/pkgs/yaml/lib/src/style.dart @@ -7,6 +7,8 @@ // ignore_for_file: constant_identifier_names +import 'yaml_node.dart'; + /// An enum of source scalar styles. class ScalarStyle { /// No source style was specified. diff --git a/pkgs/yaml/lib/src/token.dart b/pkgs/yaml/lib/src/token.dart index 282d77338..7d5d6bc9a 100644 --- a/pkgs/yaml/lib/src/token.dart +++ b/pkgs/yaml/lib/src/token.dart @@ -7,6 +7,7 @@ import 'package:source_span/source_span.dart'; +import 'scanner.dart'; import 'style.dart'; /// A token emitted by a [Scanner]. diff --git a/pkgs/yaml/lib/src/yaml_node.dart b/pkgs/yaml/lib/src/yaml_node.dart index c8f1e2304..bd17b6cb9 100644 --- a/pkgs/yaml/lib/src/yaml_node.dart +++ b/pkgs/yaml/lib/src/yaml_node.dart @@ -37,14 +37,14 @@ abstract class YamlNode { /// The inner value of this node. /// /// For [YamlScalar]s, this will return the wrapped value. For [YamlMap] and - /// [YamlList], it will return [this], since they already implement [Map] and + /// [YamlList], it will return `this`, since they already implement [Map] and /// [List], respectively. dynamic get value; } /// A read-only [Map] parsed from YAML. class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { - /// A view of [this] where the keys and values are guaranteed to be + /// A view of `this` where the keys and values are guaranteed to be /// [YamlNode]s. /// /// The key type is `dynamic` to allow values to be accessed using @@ -70,19 +70,19 @@ class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin { /// is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - factory YamlMap({sourceUrl}) => YamlMapWrapper(const {}, sourceUrl); + factory YamlMap({Object? sourceUrl}) => YamlMapWrapper(const {}, sourceUrl); /// Wraps a Dart map so that it can be accessed (recursively) like a /// [YamlMap]. /// /// Any [SourceSpan]s returned by this map or its children will be dummies /// without useful location information. However, they will have a reasonable - /// implementation of [SourceSpan.getLocationMessage]. If [sourceUrl] is + /// implementation of [SourceSpan.message]. If [sourceUrl] is /// passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. factory YamlMap.wrap(Map dartMap, - {sourceUrl, CollectionStyle style = CollectionStyle.ANY}) => + {Object? sourceUrl, CollectionStyle style = CollectionStyle.ANY}) => YamlMapWrapper(dartMap, sourceUrl, style: style); /// Users of the library should not use this constructor. @@ -120,19 +120,19 @@ class YamlList extends YamlNode with collection.ListMixin { /// [sourceUrl] is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - factory YamlList({sourceUrl}) => YamlListWrapper(const [], sourceUrl); + factory YamlList({Object? sourceUrl}) => YamlListWrapper(const [], sourceUrl); /// Wraps a Dart list so that it can be accessed (recursively) like a /// [YamlList]. /// /// Any [SourceSpan]s returned by this list or its children will be dummies /// without useful location information. However, they will have a reasonable - /// implementation of [SourceSpan.getLocationMessage]. If [sourceUrl] is + /// implementation of [SourceSpan.message]. If [sourceUrl] is /// passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. factory YamlList.wrap(List dartList, - {sourceUrl, CollectionStyle style = CollectionStyle.ANY}) => + {Object? sourceUrl, CollectionStyle style = CollectionStyle.ANY}) => YamlListWrapper(dartList, sourceUrl, style: style); /// Users of the library should not use this constructor. @@ -164,7 +164,7 @@ class YamlScalar extends YamlNode { /// [sourceUrl] is passed, it's used as the [SourceSpan.sourceUrl]. /// /// [sourceUrl] may be either a [String], a [Uri], or `null`. - YamlScalar.wrap(this.value, {sourceUrl, this.style = ScalarStyle.ANY}) + YamlScalar.wrap(this.value, {Object? sourceUrl, this.style = ScalarStyle.ANY}) : super._(NullSpan(sourceUrl)) { ArgumentError.checkNotNull(style, 'style'); } diff --git a/pkgs/yaml/lib/src/yaml_node_wrapper.dart b/pkgs/yaml/lib/src/yaml_node_wrapper.dart index 5dbf486f7..525084474 100644 --- a/pkgs/yaml/lib/src/yaml_node_wrapper.dart +++ b/pkgs/yaml/lib/src/yaml_node_wrapper.dart @@ -35,7 +35,7 @@ class YamlMapWrapper extends MapBase @override Iterable get keys => _dartMap.keys; - YamlMapWrapper(Map dartMap, sourceUrl, + YamlMapWrapper(Map dartMap, Object? sourceUrl, {CollectionStyle style = CollectionStyle.ANY}) : this._(dartMap, NullSpan(sourceUrl), style: style); @@ -116,7 +116,7 @@ class YamlListWrapper extends ListBase implements YamlList { throw UnsupportedError('Cannot modify an unmodifiable List.'); } - YamlListWrapper(List dartList, sourceUrl, + YamlListWrapper(List dartList, Object? sourceUrl, {CollectionStyle style = CollectionStyle.ANY}) : this._(dartList, NullSpan(sourceUrl), style: style); @@ -182,7 +182,7 @@ class _YamlListNodes extends ListBase { other is _YamlListNodes && other._dartList == _dartList; } -YamlNode _nodeForValue(value, SourceSpan span) { +YamlNode _nodeForValue(Object? value, SourceSpan span) { if (value is Map) return YamlMapWrapper._(value, span); if (value is List) return YamlListWrapper._(value, span); return YamlScalar.internalWithSpan(value, span); diff --git a/pkgs/yaml/lib/yaml.dart b/pkgs/yaml/lib/yaml.dart index 96869d364..26cc9b86f 100644 --- a/pkgs/yaml/lib/yaml.dart +++ b/pkgs/yaml/lib/yaml.dart @@ -29,9 +29,6 @@ export 'src/yaml_node.dart' hide setSpan; /// These have a few small behavioral differences from the default Map /// implementation; for details, see the [YamlMap] class. /// -/// In future versions, maps will instead be [HashMap]s with a custom equality -/// operation. -/// /// If [sourceUrl] is passed, it's used as the URL from which the YAML /// originated for error reporting. /// @@ -91,9 +88,6 @@ YamlDocument loadYamlDocument(String yaml, /// These have a few small behavioral differences from the default Map /// implementation; for details, see the [YamlMap] class. /// -/// In future versions, maps will instead be [HashMap]s with a custom equality -/// operation. -/// /// If [sourceUrl] is passed, it's used as the URL from which the YAML /// originated for error reporting. YamlList loadYamlStream(String yaml, {Uri? sourceUrl}) { diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 1671b26a4..e6b6f1580 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -7,7 +7,7 @@ topics: - config-format environment: - sdk: '>=2.19.0 <3.0.0' + sdk: ^3.0.0 dependencies: collection: ^1.15.0 @@ -15,6 +15,6 @@ dependencies: string_scanner: ^1.1.0 dev_dependencies: - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 path: ^1.8.0 test: ^1.16.0 diff --git a/pkgs/yaml/test/utils.dart b/pkgs/yaml/test/utils.dart index 5b852340d..372440ae9 100644 --- a/pkgs/yaml/test/utils.dart +++ b/pkgs/yaml/test/utils.dart @@ -10,7 +10,7 @@ import 'package:yaml/src/equality.dart' as equality; import 'package:yaml/yaml.dart'; /// A matcher that validates that a closure or Future throws a [YamlException]. -final Matcher throwsYamlException = throwsA(TypeMatcher()); +final Matcher throwsYamlException = throwsA(isA()); /// Returns a matcher that asserts that the value equals [expected]. /// @@ -20,7 +20,7 @@ Matcher deepEquals(Object? expected) => predicate( /// Constructs a new yaml.YamlMap, optionally from a normal Map. Map deepEqualsMap([Map? from]) { - var map = equality.deepEqualsMap(); + var map = equality.deepEqualsMap(); if (from != null) map.addAll(from); return map; } diff --git a/pkgs/yaml/test/yaml_node_wrapper_test.dart b/pkgs/yaml/test/yaml_node_wrapper_test.dart index 699066e7a..637b77832 100644 --- a/pkgs/yaml/test/yaml_node_wrapper_test.dart +++ b/pkgs/yaml/test/yaml_node_wrapper_test.dart @@ -58,19 +58,19 @@ void main() { })); expect(map.span, isNullSpan(isNull)); - expect(map['list'], TypeMatcher()); - expect(map['list'].nodes[0], TypeMatcher()); + expect(map['list'], isA()); + expect(map['list'].nodes[0], isA()); expect(map['list'].span, isNullSpan(isNull)); - expect(map['map'], TypeMatcher()); - expect(map['map'].nodes['foo'], TypeMatcher()); - expect(map['map']['nested'], TypeMatcher()); + expect(map['map'], isA()); + expect(map['map'].nodes['foo'], isA()); + expect(map['map']['nested'], isA()); expect(map['map'].span, isNullSpan(isNull)); - expect(map.nodes['scalar'], TypeMatcher()); + expect(map.nodes['scalar'], isA()); expect(map.nodes['scalar']!.value, 'value'); expect(map.nodes['scalar']!.span, isNullSpan(isNull)); expect(map['scalar'], 'value'); expect(map.keys, unorderedEquals(['list', 'map', 'scalar'])); - expect(map.nodes.keys, everyElement(TypeMatcher())); + expect(map.nodes.keys, everyElement(isA())); expect(map.nodes[YamlScalar.wrap('list')], equals([1, 2, 3])); expect(map.style, equals(CollectionStyle.ANY)); expect((map.nodes['list'] as YamlList).style, equals(CollectionStyle.ANY)); @@ -135,14 +135,14 @@ void main() { ])); expect(list.span, isNullSpan(isNull)); - expect(list[0], TypeMatcher()); - expect(list[0].nodes[0], TypeMatcher()); + expect(list[0], isA()); + expect(list[0].nodes[0], isA()); expect(list[0].span, isNullSpan(isNull)); - expect(list[1], TypeMatcher()); - expect(list[1].nodes['foo'], TypeMatcher()); - expect(list[1]['nested'], TypeMatcher()); + expect(list[1], isA()); + expect(list[1].nodes['foo'], isA()); + expect(list[1]['nested'], isA()); expect(list[1].span, isNullSpan(isNull)); - expect(list.nodes[2], TypeMatcher()); + expect(list.nodes[2], isA()); expect(list.nodes[2].value, 'value'); expect(list.nodes[2].span, isNullSpan(isNull)); expect(list[2], 'value'); @@ -223,7 +223,7 @@ void main() { } Matcher isNullSpan(Object sourceUrl) => predicate((SourceSpan span) { - expect(span, TypeMatcher()); + expect(span, isA()); expect(span.length, equals(0)); expect(span.text, isEmpty); expect(span.start, equals(span.end)); From 64fb9cb775931e70e428554e2894f501f78ef7e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:47:06 +0000 Subject: [PATCH 161/179] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/yaml#157) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/yaml#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/yaml#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 4cb7d3a73..4e4e97d8d 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 8d9c359f3b325341f2b4ef9c0e1b35810b0438c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 11:36:20 +0000 Subject: [PATCH 162/179] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/yaml#160) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 4e4e97d8d..8f1b1a691 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From cafc337e74a50c4d137c2ff0393a4f08488d9393 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 11:49:52 +0000 Subject: [PATCH 163/179] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/yaml#162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 8f1b1a691..b14a4082a 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 1cba07a3d5eddd5b1565d588f39ea3da8fd504f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:17:54 +0000 Subject: [PATCH 164/179] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/yaml#161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index b14a4082a..97fdf914e 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 4e544f66255a9006537f22889303a6b989605f92 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 13 May 2024 10:36:52 -0700 Subject: [PATCH 165/179] blast_repo fixes (dart-lang/yaml#163) dependabot --- pkgs/yaml/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/yaml/.github/dependabot.yml b/pkgs/yaml/.github/dependabot.yml index 725f03af2..cde02ad6a 100644 --- a/pkgs/yaml/.github/dependabot.yml +++ b/pkgs/yaml/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From 6dfb2d54d2de005c59b9b82add1ef0cb7ad43dfd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 17:40:21 +0000 Subject: [PATCH 166/179] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/yaml#164) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 97fdf914e..05335028c 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 01043b9c33cb8a65bde4a276181ed5123eb3a20b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 11:23:28 +0000 Subject: [PATCH 167/179] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/yaml#165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 05335028c..58a2061ed 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 33f58f97cfd98c89712e1a3f8ce96099c3fda8b0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 20 Jun 2024 11:10:42 -0700 Subject: [PATCH 168/179] blast_repo fixes (dart-lang/yaml#166) auto-publish, github-actions, no-response --- pkgs/yaml/.github/workflows/no-response.yml | 37 ++++++++++++++++++++ pkgs/yaml/.github/workflows/publish.yaml | 17 +++++++++ pkgs/yaml/.github/workflows/test-package.yml | 4 +-- 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 pkgs/yaml/.github/workflows/no-response.yml create mode 100644 pkgs/yaml/.github/workflows/publish.yaml diff --git a/pkgs/yaml/.github/workflows/no-response.yml b/pkgs/yaml/.github/workflows/no-response.yml new file mode 100644 index 000000000..ab1ac4984 --- /dev/null +++ b/pkgs/yaml/.github/workflows/no-response.yml @@ -0,0 +1,37 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/actions/stale. + +name: No Response + +# Run as a daily cron. +on: + schedule: + # Every day at 8am + - cron: '0 8 * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + pull-requests: write + +jobs: + no-response: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e + with: + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution! diff --git a/pkgs/yaml/.github/workflows/publish.yaml b/pkgs/yaml/.github/workflows/publish.yaml new file mode 100644 index 000000000..27157a046 --- /dev/null +++ b/pkgs/yaml/.github/workflows/publish.yaml @@ -0,0 +1,17 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + permissions: + id-token: write # Required for authentication using OIDC + pull-requests: write # Required for writing the pull request note diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 58a2061ed..c80712a91 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 4b465ee253b6de69915d9f45b36f20a509cf5de0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 20 Jun 2024 11:16:22 -0700 Subject: [PATCH 169/179] update lints, require Dart 3.4 (dart-lang/yaml#167) --- pkgs/yaml/.github/workflows/test-package.yml | 2 +- pkgs/yaml/CHANGELOG.md | 2 +- pkgs/yaml/pubspec.yaml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index c80712a91..ce2b90d18 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.4, dev] steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index c246967f5..37e5660e7 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,6 +1,6 @@ ## 3.1.3-wip -* Require Dart 3.0 +* Require Dart 3.4 ## 3.1.2 diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index e6b6f1580..09b65413c 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -7,7 +7,7 @@ topics: - config-format environment: - sdk: ^3.0.0 + sdk: ^3.4.0 dependencies: collection: ^1.15.0 @@ -15,6 +15,6 @@ dependencies: string_scanner: ^1.1.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 + dart_flutter_team_lints: ^3.0.0 path: ^1.8.0 - test: ^1.16.0 + test: ^1.16.6 From 7440807265f23994e8f10d7153ca7ab1ceda0c36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:01:05 +0000 Subject: [PATCH 170/179] Bump dart-lang/setup-dart in the github-actions group (dart-lang/yaml#168) Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/yaml#118: dart-lang/setup-dartdart-lang/yaml#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/yaml#118: dart-lang/setup-dartdart-lang/yaml#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.4&new-version=1.6.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index ce2b90d18..04a0ca567 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.4, dev] steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From a0f9e571b2e21d2e11680fe63afeb6281dbd1d44 Mon Sep 17 00:00:00 2001 From: Tamcy Date: Sun, 21 Jul 2024 06:19:58 +0800 Subject: [PATCH 171/179] Handle surrogate pairs during scanning (dart-lang/yaml#159) Change back to readChar() whenever possible; remove the need to decode the surrogate for further checking --- pkgs/yaml/CHANGELOG.md | 1 + pkgs/yaml/lib/src/scanner.dart | 61 +++++++++++++++++++++------------- pkgs/yaml/lib/src/utils.dart | 6 ++++ pkgs/yaml/pubspec.yaml | 2 +- pkgs/yaml/test/yaml_test.dart | 13 +++++--- 5 files changed, 54 insertions(+), 29 deletions(-) diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index 37e5660e7..cd800a861 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,6 +1,7 @@ ## 3.1.3-wip * Require Dart 3.4 +* Fix UTF-16 surrogate pair handling in plain scaler. ## 3.1.2 diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 4bf0b9306..4b155e117 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -253,7 +253,7 @@ class Scanner { null => false, LF || CR || BOM => false, TAB || NEL => true, - _ => _isStandardCharacter(char), + _ => _isStandardCharacterAt(0), }; } @@ -267,7 +267,7 @@ class Scanner { null => false, LF || CR || BOM || SP => false, NEL => true, - _ => _isStandardCharacter(char), + _ => _isStandardCharacterAt(0), }; } @@ -614,9 +614,9 @@ class Scanner { // Consume the indicator token. var start = _scanner.state; - _scanner.readChar(); - _scanner.readChar(); - _scanner.readChar(); + _scanner.readCodePoint(); + _scanner.readCodePoint(); + _scanner.readCodePoint(); _tokens.add(Token(type, _scanner.spanFrom(start))); } @@ -732,7 +732,7 @@ class Scanner { /// The span of the new token is the current character. void _addCharToken(TokenType type) { var start = _scanner.state; - _scanner.readChar(); + _scanner.readCodePoint(); _tokens.add(Token(type, _scanner.spanFrom(start))); } @@ -836,7 +836,7 @@ class Scanner { // libyaml doesn't support unknown directives, but the spec says to ignore // them and warn: http://yaml.org/spec/1.2/spec.html#id2781147. while (!_isBreakOrEnd) { - _scanner.readChar(); + _scanner.readCodePoint(); } return null; @@ -866,7 +866,7 @@ class Scanner { // disagrees: http://yaml.org/spec/1.2/spec.html#ns-directive-name. var start = _scanner.position; while (_isNonSpace) { - _scanner.readChar(); + _scanner.readCodePoint(); } var name = _scanner.substring(start); @@ -941,13 +941,13 @@ class Scanner { var start = _scanner.state; // Eat the indicator character. - _scanner.readChar(); + _scanner.readCodePoint(); // libyaml only allows word characters in anchor names, but the spec // disagrees: http://yaml.org/spec/1.2/spec.html#ns-anchor-char. var startPosition = _scanner.position; while (_isAnchorChar) { - _scanner.readChar(); + _scanner.readCodePoint(); } var name = _scanner.substring(startPosition); @@ -1032,7 +1032,7 @@ class Scanner { buffer.write(_scanner.substring(start)); if (_scanner.peekChar() == EXCLAMATION) { - buffer.writeCharCode(_scanner.readChar()); + buffer.writeCharCode(_scanner.readCodePoint()); } else { // It's either the '!' tag or not really a tag handle. If it's a %TAG // directive, it's an error. If it's a tag token, it must be part of a @@ -1083,7 +1083,7 @@ class Scanner { var start = _scanner.state; // Eat the indicator '|' or '>'. - _scanner.readChar(); + _scanner.readCodePoint(); // Check for a chomping indicator. var chomping = _Chomping.clip; @@ -1091,7 +1091,7 @@ class Scanner { var char = _scanner.peekChar(); if (char == PLUS || char == HYPHEN) { chomping = char == PLUS ? _Chomping.keep : _Chomping.strip; - _scanner.readChar(); + _scanner.readCodePoint(); // Check for an indentation indicator. if (_isDigit) { @@ -1101,7 +1101,7 @@ class Scanner { _scanner.spanFrom(start)); } - increment = _scanner.readChar() - NUMBER_0; + increment = _scanner.readCodePoint() - NUMBER_0; } } else if (_isDigit) { // Do the same as above, but in the opposite order. @@ -1110,12 +1110,12 @@ class Scanner { _scanner.spanFrom(start)); } - increment = _scanner.readChar() - NUMBER_0; + increment = _scanner.readCodePoint() - NUMBER_0; char = _scanner.peekChar(); if (char == PLUS || char == HYPHEN) { chomping = char == PLUS ? _Chomping.keep : _Chomping.strip; - _scanner.readChar(); + _scanner.readCodePoint(); } } @@ -1182,7 +1182,7 @@ class Scanner { var startPosition = _scanner.position; while (!_isBreakOrEnd) { - _scanner.readChar(); + _scanner.readCodePoint(); } buffer.write(_scanner.substring(startPosition)); end = _scanner.state; @@ -1373,7 +1373,7 @@ class Scanner { buffer.writeCharCode(value); } } else { - buffer.writeCharCode(_scanner.readChar()); + buffer.writeCharCode(_scanner.readCodePoint()); } } @@ -1462,7 +1462,7 @@ class Scanner { // 1.2's. We use [_isPlainChar] instead of libyaml's character here. var startPosition = _scanner.position; while (_isPlainChar) { - _scanner.readChar(); + _scanner.readCodePoint(); } buffer.write(_scanner.substring(startPosition)); end = _scanner.state; @@ -1587,15 +1587,28 @@ class Scanner { _inBlockContext, SP || TAB || LF || CR || BOM => false, NEL => true, - _ => _isStandardCharacter(char) + _ => _isStandardCharacterAt(offset) }; } + bool _isStandardCharacterAt(int offset) { + var first = _scanner.peekChar(offset); + if (first == null) return false; + + if (isHighSurrogate(first)) { + var next = _scanner.peekChar(offset + 1); + // A surrogate pair encodes code points from U+010000 to U+10FFFF, so it + // must be a standard character. + return next != null && isLowSurrogate(next); + } + + return _isStandardCharacter(first); + } + bool _isStandardCharacter(int char) => - (char >= 0x00020 && char <= 0x00007E) || - (char >= 0x000A0 && char <= 0x00D7FF) || - (char >= 0x0E000 && char <= 0x00FFFD) || - (char >= 0x10000 && char <= 0x10FFFF); + (char >= 0x0020 && char <= 0x007E) || + (char >= 0x00A0 && char <= 0xD7FF) || + (char >= 0xE000 && char <= 0xFFFD); /// Returns the hexidecimal value of [char]. int _asHex(int char) { diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index db4612c83..d9e20d15a 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -43,3 +43,9 @@ YamlWarningCallback yamlWarningCallback = (message, [SourceSpan? span]) { if (span != null) message = span.message(message); print(message); }; + +/// Whether [codeUnit] is a UTF-16 high surrogate. +bool isHighSurrogate(int codeUnit) => codeUnit >>> 10 == 0x36; + +/// Whether [codeUnit] is a UTF-16 low surrogate. +bool isLowSurrogate(int codeUnit) => codeUnit >>> 10 == 0x37; diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 09b65413c..be7d165c8 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -12,7 +12,7 @@ environment: dependencies: collection: ^1.15.0 source_span: ^1.8.0 - string_scanner: ^1.1.0 + string_scanner: ^1.2.0 dev_dependencies: dart_flutter_team_lints: ^3.0.0 diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index bb35ba4b5..3b5b77d2f 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart @@ -420,20 +420,25 @@ void main() { test('[Example 2.17]', () { expectYamlLoads({ - 'unicode': 'Sosa did fine.\u263A', + 'unicode': 'Sosa did fine.\u263A \u{1F680}', 'control': '\b1998\t1999\t2000\n', 'hex esc': '\r\n is \r\n', 'single': '"Howdy!" he cried.', 'quoted': " # Not a 'comment'.", - 'tie-fighter': '|\\-*-/|' + 'tie-fighter': '|\\-*-/|', + 'surrogate-pair': 'I \u{D83D}\u{DE03} ️Dart!', + 'key-\u{D83D}\u{DD11}': 'Look\u{D83D}\u{DE03}\u{D83C}\u{DF89}surprise!', }, """ - unicode: "Sosa did fine.\\u263A" + unicode: "Sosa did fine.\\u263A \\U0001F680" control: "\\b1998\\t1999\\t2000\\n" hex esc: "\\x0d\\x0a is \\r\\n" single: '"Howdy!" he cried.' quoted: ' # Not a ''comment''.' - tie-fighter: '|\\-*-/|'"""); + tie-fighter: '|\\-*-/|' + + surrogate-pair: I \u{D83D}\u{DE03} ️Dart! + key-\u{D83D}\u{DD11}: Look\u{D83D}\u{DE03}\u{D83C}\u{DF89}surprise!"""); }); test('[Example 2.18]', () { From 5bb3a10534f807810387005e79131418535a5db4 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 28 Aug 2024 17:44:57 -0700 Subject: [PATCH 172/179] Drop Pair util class (dart-lang/yaml#169) --- pkgs/yaml/lib/src/parser.dart | 8 +++----- pkgs/yaml/lib/src/scanner.dart | 12 ++++++------ pkgs/yaml/lib/src/utils.dart | 11 ----------- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index ddbfd4e60..e924e40ea 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart @@ -174,9 +174,7 @@ class Parser { // Parse an explicit document. var start = token.span; - var pair = _processDirectives(); - var versionDirective = pair.first; - var tagDirectives = pair.last; + var (versionDirective, tagDirectives) = _processDirectives(); token = _scanner.peek()!; if (token.type != TokenType.documentStart) { throw YamlException('Expected document start.', token.span); @@ -667,7 +665,7 @@ class Parser { ScalarEvent(location.pointSpan() as FileSpan, '', ScalarStyle.PLAIN); /// Parses directives. - Pair> _processDirectives() { + (VersionDirective?, List) _processDirectives() { var token = _scanner.peek()!; VersionDirective? versionDirective; @@ -707,7 +705,7 @@ class Parser { TagDirective('!!', 'tag:yaml.org,2002:'), token.span.start.pointSpan(), allowDuplicates: true); - return Pair(versionDirective, tagDirectives); + return (versionDirective, tagDirectives); } /// Adds a tag directive to the directives stack. diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 4b155e117..1cfd3af61 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart @@ -1142,8 +1142,8 @@ class Scanner { // Scan the leading line breaks to determine the indentation level if // needed. var pair = _scanBlockScalarBreaks(indent); - indent = pair.first; - var trailingBreaks = pair.last; + indent = pair.indent; + var trailingBreaks = pair.trailingBreaks; // Scan the block scalar contents. var buffer = StringBuffer(); @@ -1194,8 +1194,8 @@ class Scanner { // Eat the following indentation and spaces. var pair = _scanBlockScalarBreaks(indent); - indent = pair.first; - trailingBreaks = pair.last; + indent = pair.indent; + trailingBreaks = pair.trailingBreaks; } // Chomp the tail. @@ -1210,7 +1210,7 @@ class Scanner { /// /// Determines the intendation level if needed. Returns the new indentation /// level and the text of the line breaks. - Pair _scanBlockScalarBreaks(int indent) { + ({int indent, String trailingBreaks}) _scanBlockScalarBreaks(int indent) { var maxIndent = 0; var breaks = StringBuffer(); @@ -1238,7 +1238,7 @@ class Scanner { // be supported by the spec. } - return Pair(indent, breaks.toString()); + return (indent: indent, trailingBreaks: breaks.toString()); } // Scans a quoted scalar. diff --git a/pkgs/yaml/lib/src/utils.dart b/pkgs/yaml/lib/src/utils.dart index d9e20d15a..0dc132ff8 100644 --- a/pkgs/yaml/lib/src/utils.dart +++ b/pkgs/yaml/lib/src/utils.dart @@ -7,17 +7,6 @@ import 'package:source_span/source_span.dart'; -/// A pair of values. -class Pair { - final E first; - final F last; - - Pair(this.first, this.last); - - @override - String toString() => '($first, $last)'; -} - /// Print a warning. /// /// If [span] is passed, associates the warning with that span. From 120d197056364e2ad35fd481c806f0501848234e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:48:04 +0000 Subject: [PATCH 173/179] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/yaml#170) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 04a0ca567..867cc9615 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From afdd03c9ee087c8634dcd9f0d10c082b5e34eb15 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 28 Oct 2024 14:51:06 -0700 Subject: [PATCH 174/179] blast_repo fixes (dart-lang/yaml#171) drop-lint --- pkgs/yaml/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/yaml/analysis_options.yaml b/pkgs/yaml/analysis_options.yaml index 369e38633..46e45f0de 100644 --- a/pkgs/yaml/analysis_options.yaml +++ b/pkgs/yaml/analysis_options.yaml @@ -13,7 +13,6 @@ linter: - join_return_with_assignment - missing_whitespace_between_adjacent_strings - no_runtimeType_toString - - package_api_docs - prefer_const_declarations - prefer_expression_function_bodies - use_string_buffers From 5261816f92ba889293bd38c4dbfbd5453e8245c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 11:15:51 +0000 Subject: [PATCH 175/179] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/yaml#172) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index 867cc9615..fff5176e5 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 185e519bd10ec4ca279888965aa892dbfdd75f8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 11:19:25 +0000 Subject: [PATCH 176/179] Bump dart-lang/setup-dart in the github-actions group (dart-lang/yaml#173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/yaml#118: dart-lang/setup-dartdart-lang/yaml#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/yaml/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/pkgs/yaml/.github/workflows/test-package.yml index fff5176e5..7bc6a0b10 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/pkgs/yaml/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.4, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From 5d3b065e01d64666e5610cb8c8aa08a06982033e Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:23:23 +0100 Subject: [PATCH 177/179] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/yaml.md | 5 +++++ pkgs/yaml/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/yaml.md diff --git a/.github/ISSUE_TEMPLATE/yaml.md b/.github/ISSUE_TEMPLATE/yaml.md new file mode 100644 index 000000000..d6a7c7fef --- /dev/null +++ b/.github/ISSUE_TEMPLATE/yaml.md @@ -0,0 +1,5 @@ +--- +name: "package:yaml" +about: "Create a bug or file a feature request against package:yaml." +labels: "package:yaml" +--- \ No newline at end of file diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index be7d165c8..bbdc2168d 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,7 +1,7 @@ name: yaml version: 3.1.3-wip description: A parser for YAML, a human-friendly data serialization standard -repository: https://github.com/dart-lang/yaml +repository: https://github.com/dart-lang/tools/tree/main/pkgs/yaml topics: - yaml - config-format From ebc93fb88a59d7c34ad948cae9a24e3f90e140d4 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:26:02 +0100 Subject: [PATCH 178/179] Moving fixes --- .github/labeler.yml | 4 ++ .../workflows/yaml.yaml | 17 +++++++-- README.md | 1 + pkgs/yaml/.github/dependabot.yml | 15 -------- pkgs/yaml/.github/workflows/no-response.yml | 37 ------------------- pkgs/yaml/.github/workflows/publish.yaml | 17 --------- pkgs/yaml/CHANGELOG.md | 3 +- pkgs/yaml/README.md | 5 ++- pkgs/yaml/pubspec.yaml | 2 +- 9 files changed, 25 insertions(+), 76 deletions(-) rename pkgs/yaml/.github/workflows/test-package.yml => .github/workflows/yaml.yaml (87%) delete mode 100644 pkgs/yaml/.github/dependabot.yml delete mode 100644 pkgs/yaml/.github/workflows/no-response.yml delete mode 100644 pkgs/yaml/.github/workflows/publish.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index 1cc4b2058..24a709575 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -111,3 +111,7 @@ 'package:unified_analytics': - changed-files: - any-glob-to-any-file: 'pkgs/unified_analytics/**' + +'package:yaml': + - changed-files: + - any-glob-to-any-file: 'pkgs/yaml/**' diff --git a/pkgs/yaml/.github/workflows/test-package.yml b/.github/workflows/yaml.yaml similarity index 87% rename from pkgs/yaml/.github/workflows/test-package.yml rename to .github/workflows/yaml.yaml index 7bc6a0b10..735461eec 100644 --- a/pkgs/yaml/.github/workflows/test-package.yml +++ b/.github/workflows/yaml.yaml @@ -1,17 +1,28 @@ -name: Dart CI +name: package:yaml on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/yaml.yaml' + - 'pkgs/yaml/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/yaml.yaml' + - 'pkgs/yaml/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github + +defaults: + run: + working-directory: pkgs/yaml/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index 79d1dde21..f463351df 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ don't naturally belong to other topic monorepos (like | [source_span](pkgs/source_span/) | Provides a standard representation for source code locations and spans. | [![package issues](https://img.shields.io/badge/package:source_span-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_span) | [![pub package](https://img.shields.io/pub/v/source_span.svg)](https://pub.dev/packages/source_span) | | [sse](pkgs/sse/) | Provides client and server functionality for setting up bi-directional communication through Server Sent Events (SSE) and corresponding POST requests. | [![package issues](https://img.shields.io/badge/package:sse-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asse) | [![pub package](https://img.shields.io/pub/v/sse.svg)](https://pub.dev/packages/sse) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | +| [yaml](pkgs/yaml/) | A parser for YAML, a human-friendly data serialization standard | [![package issues](https://img.shields.io/badge/package:yaml-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Ayaml) | [![pub package](https://img.shields.io/pub/v/yaml.svg)](https://pub.dev/packages/yaml) | ## Publishing automation diff --git a/pkgs/yaml/.github/dependabot.yml b/pkgs/yaml/.github/dependabot.yml deleted file mode 100644 index cde02ad6a..000000000 --- a/pkgs/yaml/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/yaml/.github/workflows/no-response.yml b/pkgs/yaml/.github/workflows/no-response.yml deleted file mode 100644 index ab1ac4984..000000000 --- a/pkgs/yaml/.github/workflows/no-response.yml +++ /dev/null @@ -1,37 +0,0 @@ -# A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/actions/stale. - -name: No Response - -# Run as a daily cron. -on: - schedule: - # Every day at 8am - - cron: '0 8 * * *' - -# All permissions not specified are set to 'none'. -permissions: - issues: write - pull-requests: write - -jobs: - no-response: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'dart-lang' }} - steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e - with: - # Don't automatically mark inactive issues+PRs as stale. - days-before-stale: -1 - # Close needs-info issues and PRs after 14 days of inactivity. - days-before-close: 14 - stale-issue-label: "needs-info" - close-issue-message: > - Without additional information we're not able to resolve this issue. - Feel free to add more info or respond to any questions above and we - can reopen the case. Thanks for your contribution! - stale-pr-label: "needs-info" - close-pr-message: > - Without additional information we're not able to resolve this PR. - Feel free to add more info or respond to any questions above. - Thanks for your contribution! diff --git a/pkgs/yaml/.github/workflows/publish.yaml b/pkgs/yaml/.github/workflows/publish.yaml deleted file mode 100644 index 27157a046..000000000 --- a/pkgs/yaml/.github/workflows/publish.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main - permissions: - id-token: write # Required for authentication using OIDC - pull-requests: write # Required for writing the pull request note diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index cd800a861..3f9d3fd22 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md @@ -1,7 +1,8 @@ -## 3.1.3-wip +## 3.1.3 * Require Dart 3.4 * Fix UTF-16 surrogate pair handling in plain scaler. +* Move to `dart-lang/tools` monorepo. ## 3.1.2 diff --git a/pkgs/yaml/README.md b/pkgs/yaml/README.md index 6f5be2882..ba56893df 100644 --- a/pkgs/yaml/README.md +++ b/pkgs/yaml/README.md @@ -1,7 +1,8 @@ -[![Build Status](https://github.com/dart-lang/yaml/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/yaml/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) -[![Pub Package](https://img.shields.io/pub/v/yaml.svg)](https://pub.dev/packages/yaml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/yaml.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/yaml.yaml) +[![pub package](https://img.shields.io/pub/v/yaml.svg)](https://pub.dev/packages/yaml) [![package publisher](https://img.shields.io/pub/publisher/yaml.svg)](https://pub.dev/packages/yaml/publisher) + A parser for [YAML](https://yaml.org/). ## Usage diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index bbdc2168d..3224067d7 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -1,5 +1,5 @@ name: yaml -version: 3.1.3-wip +version: 3.1.3 description: A parser for YAML, a human-friendly data serialization standard repository: https://github.com/dart-lang/tools/tree/main/pkgs/yaml topics: From e0e8ae387bf996de3dbd607629a4bc3e78c5aaa1 Mon Sep 17 00:00:00 2001 From: Moritz Date: Fri, 20 Dec 2024 14:37:09 +0100 Subject: [PATCH 179/179] Update pkgs/yaml/pubspec.yaml Co-authored-by: Devon Carew --- pkgs/yaml/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml index 3224067d7..fb37436f2 100644 --- a/pkgs/yaml/pubspec.yaml +++ b/pkgs/yaml/pubspec.yaml @@ -2,6 +2,7 @@ name: yaml version: 3.1.3 description: A parser for YAML, a human-friendly data serialization standard repository: https://github.com/dart-lang/tools/tree/main/pkgs/yaml + topics: - yaml - config-format