| // 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'; |
| |
| extension YamlNodeExtensions on YamlNode { |
| /// Return the child of this node that contains the given [offset], or `null` |
| /// if none of the children contains the offset. |
| YamlNode? childContainingOffset(int offset) { |
| var node = this; |
| if (node is YamlList) { |
| for (var element in node.nodes) { |
| if (element.containsOffset(offset)) { |
| return element; |
| } |
| } |
| for (var element in node.nodes) { |
| if (element is YamlScalar && element.value == null) { |
| // TODO(brianwilkerson) Testing for a null value probably gets |
| // confused when there are multiple null values. |
| return element; |
| } |
| } |
| } else if (node is YamlMap) { |
| var entries = node.nodes.entries.toList(); |
| for (var i = 0; i < entries.length; i++) { |
| var entry = entries[i]; |
| var nextEntryOffset = i + 1 < entries.length |
| ? (entries[i + 1].key as YamlNode).span.start.offset |
| : null; |
| var key = entry.key as YamlNode; |
| if (key.containsOffset(offset)) { |
| return key; |
| } |
| var value = entry.value; |
| if (value.containsOffset(offset) || |
| (value is YamlScalar && |
| value.value == null && |
| // To match a null, we need to be the last node, or the offset |
| // needs to be before the next key. |
| (nextEntryOffset == null || offset < nextEntryOffset))) { |
| return entry.value; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /// Return `true` if this node contains the given [offset]. |
| bool containsOffset(int offset) { |
| // TODO(brianwilkerson) Nodes at the end of the file contain any trailing |
| // whitespace. This needs to be accounted for, here or elsewhere. |
| var nodeOffset = span.start.offset; |
| var nodeEnd = nodeOffset + span.length; |
| return nodeOffset <= offset && offset <= nodeEnd; |
| } |
| } |