blob: b3c0c2e0b79a59185293cb6802f4e2bde85e702f [file] [log] [blame]
// 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;
}
}