Skip to content

Commit

Permalink
AliasError -> AliasException
Browse files Browse the repository at this point in the history
  • Loading branch information
sigurdm committed Sep 28, 2023
1 parent 4a9734d commit 775748f
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 23 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# 2.2.0
- `AliasError` is changed to `AliasException` and exposed in the public API.

All node-mutating methods on `YamlEditor`, i.e. `update()`, `appendToList()`,
`prependToList()`, `insertIntoList()`, `spliceList()`, `remove()` will now
throw an exception instead of an error when encountering an alias on the path
to modify.

This allows catching and handling when this is happening.

## 2.1.1

- Require Dart 2.19
Expand Down
29 changes: 21 additions & 8 deletions lib/src/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ class YamlEditor {
///
/// Throws a [ArgumentError] if [path] is invalid.
///
/// Throws an [AliasException] if a node on [path] is an alias or anchor.
///
/// **Example:** (using [update])
/// ```dart
/// final doc = YamlEditor('''
Expand Down Expand Up @@ -279,6 +281,8 @@ class YamlEditor {
/// Throws a [ArgumentError] if the element at the given path is not a
/// [YamlList] or if the path is invalid.
///
/// Throws an [AliasException] if a node on [path] is an alias or anchor.
///
/// **Example:**
/// ```dart
/// final doc = YamlEditor('[0, 1]');
Expand All @@ -295,6 +299,8 @@ class YamlEditor {
/// Throws a [ArgumentError] if the element at the given path is not a
/// [YamlList] or if the path is invalid.
///
/// Throws an [AliasException] if a node on [path] is an alias or anchor.
///
/// **Example:**
/// ```dart
/// final doc = YamlEditor('[1, 2]');
Expand All @@ -311,6 +317,8 @@ class YamlEditor {
/// Throws a [ArgumentError] if the element at the given path is not a
/// [YamlList] or if the path is invalid.
///
/// Throws an [AliasException] if a node on [path] is an alias or anchor.
///
/// **Example:**
/// ```dart
/// final doc = YamlEditor('[0, 2]');
Expand Down Expand Up @@ -340,6 +348,8 @@ class YamlEditor {
/// Throws a [ArgumentError] if the element at the given path is not a
/// [YamlList] or if the path is invalid.
///
/// Throws an [AliasException] if a node on [path] is an alias or anchor.
///
/// **Example:**
/// ```dart
/// final doc = YamlEditor('[Jan, March, April, June]');
Expand Down Expand Up @@ -375,7 +385,9 @@ class YamlEditor {
/// Removes the node at [path]. Comments "belonging" to the node will be
/// removed while surrounding comments will be left untouched.
///
/// Throws a [ArgumentError] if [path] is invalid.
/// Throws an [ArgumentError] if [path] is invalid.
///
/// Throws an [AliasException] if a node on [path] is an alias or anchor.
///
/// **Example:**
/// ```dart
Expand Down Expand Up @@ -441,7 +453,7 @@ class YamlEditor {
///
/// If [orElse] is omitted, it defaults to throwing a [PathError].
///
/// If [checkAlias] is `true`, throw [AliasError] if an aliased node is
/// If [checkAlias] is `true`, throw [AliasException] if an aliased node is
/// encountered.
YamlNode _traverse(Iterable<Object?> path,
{bool checkAlias = false, YamlNode Function()? orElse}) {
Expand All @@ -454,7 +466,7 @@ class YamlEditor {
final keyOrIndex = pathList[i];

if (checkAlias && _aliases.contains(currentNode)) {
throw AliasError(path, currentNode);
throw AliasException(path, currentNode);
}

if (currentNode is YamlList) {
Expand All @@ -473,7 +485,7 @@ class YamlEditor {
final keyNode = getKeyNode(map, keyOrIndex);

if (checkAlias) {
if (_aliases.contains(keyNode)) throw AliasError(path, keyNode);
if (_aliases.contains(keyNode)) throw AliasException(path, keyNode);
}

currentNode = map.nodes[keyNode]!;
Expand All @@ -498,7 +510,7 @@ class YamlEditor {
/// Asserts that [node] and none its children are aliases
void _assertNoChildAlias(Iterable<Object?> path, [YamlNode? node]) {
if (node == null) return _assertNoChildAlias(path, _traverse(path));
if (_aliases.contains(node)) throw AliasError(path, node);
if (_aliases.contains(node)) throw AliasException(path, node);

if (node is YamlScalar) return;

Expand All @@ -514,7 +526,7 @@ class YamlEditor {
for (var i = 0; i < node.length; i++) {
final updatedPath = [...path, keyList[i]];
if (_aliases.contains(keyList[i])) {
throw AliasError(path, keyList[i] as YamlNode);
throw AliasException(path, keyList[i] as YamlNode);
}
_assertNoChildAlias(updatedPath, node.nodes[keyList[i]]);
}
Expand All @@ -527,9 +539,10 @@ class YamlEditor {
///
/// Throws [ArgumentError] if the element at the given path is not a
/// [YamlList] or if the path is invalid. If [checkAlias] is `true`, and an
/// aliased node is encountered along [path], an [AliasError] will be thrown.
/// aliased node is encountered along [path], an [AliasException] will be
/// thrown.
YamlList _traverseToList(Iterable<Object?> path, {bool checkAlias = false}) {
final possibleList = _traverse(path, checkAlias: true);
final possibleList = _traverse(path, checkAlias: checkAlias);

if (possibleList is YamlList) {
return possibleList;
Expand Down
6 changes: 3 additions & 3 deletions lib/src/errors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class PathError extends ArgumentError {
}
}

/// Error thrown when the path contains an alias along the way.
/// Exception thrown when the path contains an alias along the way.
///
/// When a path contains an aliased node, the behavior becomes less well-defined
/// because we cannot be certain if the user wishes for the change to
Expand All @@ -50,14 +50,14 @@ class PathError extends ArgumentError {
/// the detection that our change will impact an alias, and we do not intend
/// on supporting such changes for the foreseeable future.
@sealed
class AliasError extends UnsupportedError {
class AliasException extends FormatException {
/// The path that caused the error
final Iterable<Object?> path;

/// The anchor node of the alias
final YamlNode anchor;

AliasError(this.path, this.anchor)
AliasException(this.path, this.anchor)
: super('Encountered an alias node along $path! '
'Alias nodes are nodes that refer to a previously serialized '
'nodes, and are denoted by either the "*" or the "&" indicators in '
Expand Down
1 change: 1 addition & 0 deletions lib/yaml_edit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@
library yaml_edit;

export 'src/editor.dart';
export 'src/errors.dart' show AliasException;
export 'src/source_edit.dart';
export 'src/wrap.dart' show wrapAsYamlNode;
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: yaml_edit
version: 2.1.1
version: 2.2.0
description: A library for YAML manipulation with comment and whitespace preservation.
repository: https://github.com/dart-lang/yaml_edit
issue_tracker: https://github.com/dart-lang/yaml_edit/issues
Expand Down
20 changes: 10 additions & 10 deletions test/alias_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ void main() {
- &SS Sammy Sosa
- *SS
''');
expect(() => doc.remove([0]), throwsAliasError);
expect(() => doc.remove([0]), throwsAliasException);
});

test('removing an alias reference results in AliasError', () {
Expand All @@ -25,7 +25,7 @@ void main() {
- *SS
''');

expect(() => doc.remove([1]), throwsAliasError);
expect(() => doc.remove([1]), throwsAliasException);
});

test('it is okay to remove a non-alias node', () {
Expand All @@ -50,7 +50,7 @@ a: &SS Sammy Sosa
b: *SS
''');

expect(() => doc.remove(['a']), throwsAliasError);
expect(() => doc.remove(['a']), throwsAliasException);
});

test('removing an alias reference value results in AliasError', () {
Expand All @@ -59,7 +59,7 @@ a: &SS Sammy Sosa
b: *SS
''');

expect(() => doc.remove(['b']), throwsAliasError);
expect(() => doc.remove(['b']), throwsAliasException);
});

test('removing an alias anchor key results in AliasError', () {
Expand All @@ -68,7 +68,7 @@ b: *SS
b: *SS
''');

expect(() => doc.remove(['Sammy Sosa']), throwsAliasError);
expect(() => doc.remove(['Sammy Sosa']), throwsAliasException);
});

test('removing an alias reference key results in AliasError', () {
Expand All @@ -77,7 +77,7 @@ a: &SS Sammy Sosa
*SS : b
''');

expect(() => doc.remove(['Sammy Sosa']), throwsAliasError);
expect(() => doc.remove(['Sammy Sosa']), throwsAliasException);
});

test('it is okay to remove a non-alias node', () {
Expand All @@ -103,7 +103,7 @@ b: *SS
- *SS
''');

expect(() => doc.remove([0]), throwsAliasError);
expect(() => doc.remove([0]), throwsAliasException);
});

test('nested list alias references are detected too', () {
Expand All @@ -113,7 +113,7 @@ b: *SS
- *SS
''');

expect(() => doc.remove([1]), throwsAliasError);
expect(() => doc.remove([1]), throwsAliasException);
});

test('removing nested map alias anchor results in AliasError', () {
Expand All @@ -123,7 +123,7 @@ a:
b: *SS
''');

expect(() => doc.remove(['a']), throwsAliasError);
expect(() => doc.remove(['a']), throwsAliasException);
});

test('removing nested map alias reference results in AliasError', () {
Expand All @@ -133,7 +133,7 @@ b:
c: *SS
''');

expect(() => doc.remove(['b']), throwsAliasError);
expect(() => doc.remove(['b']), throwsAliasException);
});
});
}
2 changes: 1 addition & 1 deletion test/test_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Matcher notEquals(dynamic expected) => isNot(equals(expected));
Matcher throwsPathError = throwsA(isA<PathError>());

/// A matcher for functions that throw [AliasError].
Matcher throwsAliasError = throwsA(isA<AliasError>());
Matcher throwsAliasException = throwsA(isA<AliasException>());

/// Enum to hold the possible modification methods.
enum YamlModificationMethod {
Expand Down

0 comments on commit 775748f

Please sign in to comment.