| // 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:meta/meta.dart'; |
| import 'package:yaml/yaml.dart'; |
| |
| /// Error thrown when a function is passed an invalid path. |
| @sealed |
| class PathError extends ArgumentError { |
| /// The full path that caused the error |
| final Iterable<Object?> path; |
| |
| /// The subpath that caused the error |
| final Iterable<Object?> subPath; |
| |
| /// The last element of [path] that could be traversed. |
| YamlNode? parent; |
| |
| PathError(this.path, this.subPath, this.parent, [String? message]) |
| : super.value(subPath, 'path', message); |
| |
| PathError.unexpected(this.path, String message) |
| : subPath = path, |
| super(message); |
| |
| @override |
| String toString() { |
| if (message == null) { |
| var errorMessage = 'Failed to traverse to subpath $subPath!'; |
| |
| if (subPath.isNotEmpty) { |
| errorMessage += |
| ' Parent $parent does not contain key or index ${subPath.last}'; |
| } |
| |
| return 'Invalid path: $path. $errorMessage.'; |
| } |
| |
| return 'Invalid path: $path. $message'; |
| } |
| } |
| |
| /// 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 propagate |
| /// throughout all the other aliased nodes, or if the user wishes for only that |
| /// particular node to be modified. As such, [AliasException] reflects the |
| /// detection that our change will impact an alias, and we do not intend on |
| /// supporting such changes for the foreseeable future. |
| @sealed |
| class AliasException extends FormatException { |
| /// The path that caused the error |
| final Iterable<Object?> path; |
| |
| /// The anchor node of the alias |
| final YamlNode 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 ' |
| 'the original YAML. As the resulting behavior of mutations on ' |
| 'these nodes is not well-defined, the operation will not be ' |
| 'supported by this library.\n\n' |
| '${anchor.span.message('The alias was first defined here.')}'); |
| } |
| |
| /// Error thrown when an assertion about the YAML fails. Extends |
| /// [AssertionError] to override the [toString] method for pretty printing. |
| class _YamlAssertionError extends AssertionError { |
| _YamlAssertionError(super.message); |
| |
| @override |
| String toString() { |
| if (message != null) { |
| return 'Assertion failed: $message'; |
| } |
| return 'Assertion failed'; |
| } |
| } |
| |
| /// Throws an [AssertionError] with the given [message], and format |
| /// [oldYaml] and [newYaml] for information. |
| Error createAssertionError(String message, String oldYaml, String newYaml) { |
| return _YamlAssertionError(''' |
| (package:yaml_edit) $message |
| |
| # YAML before edit: |
| > ${oldYaml.replaceAll('\n', '\n> ')} |
| |
| # YAML after edit: |
| > ${newYaml.replaceAll('\n', '\n> ')} |
| |
| Please file an issue at: |
| https://github.com/dart-lang/yaml_edit/issues/new?labels=bug |
| '''); |
| } |