| // 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 'package:yaml/yaml.dart'; | |
| /// An object used to locate the [YamlNode] associated with a source range. | |
| /// More specifically, it will return the deepest [YamlNode] which completely | |
| /// encompasses the specified range. | |
| class YamlNodeLocator { | |
| /// The inclusive start offset of the range used to identify the node. | |
| final int _startOffset; | |
| /// The inclusive end offset of the range used to identify the node. | |
| final int _endOffset; | |
| /// Initialize a newly created locator to locate the deepest [YamlNode] for | |
| /// which `node.offset <= [start]` and `[end] < node.end`. | |
| /// | |
| /// If the [end] offset is not provided, then it is considered the same as the | |
| /// [start] offset. | |
| new({required int start, int? end}) | |
| : _startOffset = start, | |
| _endOffset = end ?? start; | |
| /// Search within the given Yaml [node] and return the path to the most deeply | |
| /// nested node that includes the whole target range, or an empty list if no | |
| /// node was found. The path is represented by all of the elements from the | |
| /// starting [node] to the most deeply nested node, in reverse order. | |
| List<YamlNode> searchWithin(YamlNode node) { | |
| var path = <YamlNode>[]; | |
| _searchWithin(path, node); | |
| return path; | |
| } | |
| void _searchWithin(List<YamlNode> path, YamlNode node) { | |
| var span = node.span; | |
| if (span.start.offset > _endOffset || span.end.offset < _startOffset) { | |
| return; | |
| } | |
| if (node is YamlList) { | |
| for (var element in node.nodes) { | |
| _searchWithin(path, element); | |
| if (path.isNotEmpty) { | |
| path.add(node); | |
| return; | |
| } | |
| } | |
| } else if (node is YamlMap) { | |
| var nodeMap = node.nodes; | |
| for (var entry in nodeMap.entries) { | |
| _searchWithin(path, entry.key as YamlNode); | |
| if (path.isNotEmpty) { | |
| path.add(node); | |
| return; | |
| } | |
| _searchWithin(path, entry.value); | |
| if (path.isNotEmpty) { | |
| path.add(node); | |
| return; | |
| } | |
| } | |
| } | |
| path.add(node); | |
| } | |
| } |