yerba 0.9.1-arm-linux-gnu → 0.10.0-arm-linux-gnu

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -16
  3. data/exe/arm-linux-gnu/yerba +0 -0
  4. data/ext/yerba/include/yerba.h +67 -32
  5. data/ext/yerba/yerba.c +296 -186
  6. data/lib/yerba/3.2/yerba.so +0 -0
  7. data/lib/yerba/3.3/yerba.so +0 -0
  8. data/lib/yerba/3.4/yerba.so +0 -0
  9. data/lib/yerba/4.0/yerba.so +0 -0
  10. data/lib/yerba/collection.rb +4 -4
  11. data/lib/yerba/document.rb +134 -0
  12. data/lib/yerba/formatting.rb +1 -0
  13. data/lib/yerba/location.rb +8 -1
  14. data/lib/yerba/map.rb +16 -6
  15. data/lib/yerba/node.rb +41 -0
  16. data/lib/yerba/query_result.rb +33 -10
  17. data/lib/yerba/scalar.rb +29 -0
  18. data/lib/yerba/selector.rb +142 -0
  19. data/lib/yerba/sequence.rb +38 -33
  20. data/lib/yerba/version.rb +1 -1
  21. data/lib/yerba.rb +1 -0
  22. data/rust/Cargo.lock +1 -1
  23. data/rust/Cargo.toml +1 -1
  24. data/rust/src/commands/get.rs +12 -12
  25. data/rust/src/commands/init.rs +8 -8
  26. data/rust/src/commands/insert.rs +4 -18
  27. data/rust/src/commands/location.rs +2 -0
  28. data/rust/src/commands/mod.rs +34 -6
  29. data/rust/src/commands/move_item.rs +1 -1
  30. data/rust/src/commands/move_key.rs +8 -8
  31. data/rust/src/commands/rename.rs +1 -1
  32. data/rust/src/commands/selectors.rs +1 -1
  33. data/rust/src/commands/set.rs +14 -6
  34. data/rust/src/document/condition.rs +25 -25
  35. data/rust/src/document/delete.rs +57 -43
  36. data/rust/src/document/get.rs +91 -82
  37. data/rust/src/document/insert.rs +77 -77
  38. data/rust/src/document/mod.rs +138 -64
  39. data/rust/src/document/nodes.rs +162 -0
  40. data/rust/src/document/schema.rs +8 -8
  41. data/rust/src/document/set.rs +49 -26
  42. data/rust/src/document/sort.rs +54 -54
  43. data/rust/src/document/style.rs +50 -49
  44. data/rust/src/document/unique.rs +5 -5
  45. data/rust/src/error.rs +8 -4
  46. data/rust/src/ffi.rs +272 -102
  47. data/rust/src/json.rs +62 -2
  48. data/rust/src/lib.rs +2 -1
  49. data/rust/src/main.rs +2 -1
  50. data/rust/src/selector.rs +48 -7
  51. data/rust/src/syntax.rs +449 -56
  52. data/rust/src/validation.rs +5 -3
  53. data/rust/src/yerbafile.rs +124 -76
  54. metadata +4 -2
@@ -2,6 +2,7 @@ mod condition;
2
2
  mod delete;
3
3
  mod get;
4
4
  mod insert;
5
+ mod nodes;
5
6
  mod set;
6
7
  mod sort;
7
8
  mod unique;
@@ -32,6 +33,7 @@ pub struct LocatedNode {
32
33
  use std::fs;
33
34
  use std::path::{Path, PathBuf};
34
35
  use std::sync::atomic::{AtomicU64, Ordering};
36
+ use std::sync::OnceLock;
35
37
 
36
38
  use rowan::ast::AstNode;
37
39
  use rowan::{TextRange, TextSize};
@@ -46,34 +48,34 @@ use crate::syntax::{
46
48
  column_at, dedent_block_scalar, extract_scalar, extract_scalar_text, find_block_map, find_block_sequence, find_entry_by_key, find_flow_entry_by_key,
47
49
  find_flow_map, find_flow_sequence, find_scalar_token, first_collection, flow_map_entries, flow_sequence_entries, format_scalar_value, in_flow_collection,
48
50
  is_map_key, is_yaml_non_string, line_at, line_start_at, preceding_whitespace_indent, preceding_whitespace_token, raw_scalar_value, removal_range,
49
- FirstCollection, ScalarValue,
51
+ FirstCollection, LineIndex, ScalarValue,
50
52
  };
51
53
 
52
54
  #[derive(Debug, Clone)]
53
55
  pub struct SortField {
54
- pub path: String,
56
+ pub selector: String,
55
57
  pub ascending: bool,
56
58
  }
57
59
 
58
60
  impl SortField {
59
- pub fn asc(path: &str) -> Self {
61
+ pub fn asc(selector: &str) -> Self {
60
62
  SortField {
61
- path: path.to_string(),
63
+ selector: selector.to_string(),
62
64
  ascending: true,
63
65
  }
64
66
  }
65
67
 
66
- pub fn desc(path: &str) -> Self {
68
+ pub fn desc(selector: &str) -> Self {
67
69
  SortField {
68
- path: path.to_string(),
70
+ selector: selector.to_string(),
69
71
  ascending: false,
70
72
  }
71
73
  }
72
74
 
73
75
  pub fn parse(input: &str) -> Self {
74
- if let Some((path, direction)) = input.rsplit_once(':') {
76
+ if let Some((selector, direction)) = input.rsplit_once(':') {
75
77
  match direction {
76
- "desc" | "descending" => SortField::desc(path),
78
+ "desc" | "descending" => SortField::desc(selector),
77
79
  _ => SortField::asc(input),
78
80
  }
79
81
  } else {
@@ -82,7 +84,35 @@ impl SortField {
82
84
  }
83
85
 
84
86
  pub fn parse_list(input: &str) -> Vec<Self> {
85
- input.split(',').map(|field| SortField::parse(field.trim())).collect()
87
+ let mut fields = Vec::new();
88
+ let mut current = String::new();
89
+ let mut depth = 0usize;
90
+ let mut quote: Option<char> = None;
91
+
92
+ for character in input.chars() {
93
+ match (quote, character) {
94
+ (Some(open), _) if character == open => quote = None,
95
+ (Some(_), _) => {}
96
+ (None, '"' | '\'') => quote = Some(character),
97
+ (None, '[') => depth += 1,
98
+ (None, ']') => depth = depth.saturating_sub(1),
99
+ (None, ',') if depth == 0 => {
100
+ fields.push(std::mem::take(&mut current));
101
+ continue;
102
+ }
103
+ (None, _) if character.is_whitespace() && depth == 0 => {
104
+ fields.push(std::mem::take(&mut current));
105
+ continue;
106
+ }
107
+ _ => {}
108
+ }
109
+
110
+ current.push(character);
111
+ }
112
+
113
+ fields.push(current);
114
+
115
+ fields.iter().filter(|field| !field.is_empty()).map(|field| SortField::parse(field)).collect()
86
116
  }
87
117
  }
88
118
 
@@ -103,6 +133,8 @@ pub struct Location {
103
133
  pub end_column: usize,
104
134
  pub start_offset: usize,
105
135
  pub end_offset: usize,
136
+ pub start_character_column: usize,
137
+ pub end_character_column: usize,
106
138
  }
107
139
 
108
140
  #[derive(Debug)]
@@ -127,6 +159,28 @@ pub enum InsertPosition {
127
159
  FromSortOrder(Vec<String>),
128
160
  }
129
161
 
162
+ impl InsertPosition {
163
+ pub fn before(target: impl Into<String>) -> Self {
164
+ let target = target.into();
165
+
166
+ if target.starts_with('.') {
167
+ InsertPosition::BeforeCondition(target)
168
+ } else {
169
+ InsertPosition::Before(target)
170
+ }
171
+ }
172
+
173
+ pub fn after(target: impl Into<String>) -> Self {
174
+ let target = target.into();
175
+
176
+ if target.starts_with('.') {
177
+ InsertPosition::AfterCondition(target)
178
+ } else {
179
+ InsertPosition::After(target)
180
+ }
181
+ }
182
+ }
183
+
130
184
  static NEXT_GENERATION: AtomicU64 = AtomicU64::new(1);
131
185
 
132
186
  #[derive(Debug)]
@@ -134,6 +188,7 @@ pub struct Document {
134
188
  root: SyntaxNode,
135
189
  path: Option<PathBuf>,
136
190
  generation: u64,
191
+ line_index: OnceLock<LineIndex>,
137
192
  }
138
193
 
139
194
  impl Document {
@@ -146,6 +201,7 @@ impl Document {
146
201
  root: tree,
147
202
  path: None,
148
203
  generation: NEXT_GENERATION.fetch_add(1, Ordering::Relaxed),
204
+ line_index: OnceLock::new(),
149
205
  })
150
206
  }
151
207
 
@@ -181,49 +237,49 @@ impl Document {
181
237
  Ok(())
182
238
  }
183
239
 
184
- pub fn source(&self, dot_path: &str) -> Result<String, YerbaError> {
185
- let node = self.navigate(dot_path)?;
240
+ pub fn source(&self, selector: &str) -> Result<String, YerbaError> {
241
+ let node = self.navigate(selector)?;
186
242
  Ok(node.text().to_string())
187
243
  }
188
244
 
189
- pub fn navigate(&self, dot_path: &str) -> Result<SyntaxNode, YerbaError> {
190
- Self::validate_path(dot_path)?;
245
+ pub fn navigate(&self, selector: &str) -> Result<SyntaxNode, YerbaError> {
246
+ Self::validate_selector(selector)?;
191
247
 
192
- if dot_path.is_empty() {
193
- let root = Root::cast(self.root.clone()).ok_or_else(|| YerbaError::SelectorNotFound(dot_path.to_string()))?;
248
+ if selector.is_empty() {
249
+ let root = Root::cast(self.root.clone()).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
194
250
 
195
- let document = root.documents().next().ok_or_else(|| YerbaError::SelectorNotFound(dot_path.to_string()))?;
251
+ let document = root.documents().next().ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
196
252
 
197
253
  return Ok(document.syntax().clone());
198
254
  }
199
255
 
200
- let nodes = self.navigate_all_compact(dot_path);
256
+ let nodes = self.navigate_all_compact(selector);
201
257
 
202
258
  match nodes.len() {
203
- 0 => Err(YerbaError::SelectorNotFound(dot_path.to_string())),
259
+ 0 => Err(YerbaError::SelectorNotFound(selector.to_string())),
204
260
  1 => Ok(nodes.into_iter().next().unwrap()),
205
- _ => Err(YerbaError::AmbiguousSelector(dot_path.to_string(), nodes.len())),
261
+ _ => Err(YerbaError::AmbiguousSelector(selector.to_string(), nodes.len())),
206
262
  }
207
263
  }
208
264
 
209
- pub fn navigate_all_compact(&self, dot_path: &str) -> Vec<SyntaxNode> {
210
- self.navigate_all(dot_path).into_iter().flatten().collect()
265
+ pub fn navigate_all_compact(&self, selector: &str) -> Vec<SyntaxNode> {
266
+ self.navigate_all(selector).into_iter().flatten().collect()
211
267
  }
212
268
 
213
- pub(crate) fn refuse_flow_target(&self, dot_path: &str) -> Result<(), YerbaError> {
214
- if self.navigate_all_compact(dot_path).iter().any(in_flow_collection) {
215
- return Err(YerbaError::FlowCollectionNotWritable(dot_path.to_string()));
269
+ pub(crate) fn refuse_flow_target(&self, selector: &str) -> Result<(), YerbaError> {
270
+ if self.navigate_all_compact(selector).iter().any(in_flow_collection) {
271
+ return Err(YerbaError::FlowCollectionNotWritable(selector.to_string()));
216
272
  }
217
273
 
218
274
  Ok(())
219
275
  }
220
276
 
221
- pub fn navigate_all(&self, dot_path: &str) -> Vec<Option<SyntaxNode>> {
222
- if Document::validate_path(dot_path).is_err() {
277
+ pub fn navigate_all(&self, selector: &str) -> Vec<Option<SyntaxNode>> {
278
+ if Document::validate_selector(selector).is_err() {
223
279
  return Vec::new();
224
280
  }
225
281
 
226
- let parsed = crate::selector::Selector::parse(dot_path);
282
+ let parsed = crate::selector::Selector::parse(selector);
227
283
 
228
284
  let root = match Root::cast(self.root.clone()) {
229
285
  Some(root) => root,
@@ -299,21 +355,21 @@ impl Document {
299
355
  current_nodes
300
356
  }
301
357
 
302
- pub fn validate_path(dot_path: &str) -> Result<(), YerbaError> {
303
- if dot_path.ends_with('.') {
304
- return Err(YerbaError::ParseError(format!("invalid path: trailing dot in '{}'", dot_path)));
358
+ pub fn validate_selector(selector: &str) -> Result<(), YerbaError> {
359
+ if selector.ends_with('.') {
360
+ return Err(YerbaError::ParseError(format!("invalid selector: trailing dot in '{}'", selector)));
305
361
  }
306
362
 
307
- if dot_path.contains("..") {
308
- return Err(YerbaError::ParseError(format!("invalid path: double dot in '{}'", dot_path)));
363
+ if selector.contains("..") {
364
+ return Err(YerbaError::ParseError(format!("invalid selector: double dot in '{}'", selector)));
309
365
  }
310
366
 
311
- if dot_path.starts_with('.') {
312
- return Err(YerbaError::ParseError(format!("invalid path: leading dot in '{}'", dot_path)));
367
+ if selector.starts_with('.') {
368
+ return Err(YerbaError::ParseError(format!("invalid selector: leading dot in '{}'", selector)));
313
369
  }
314
370
 
315
- if dot_path.contains('[') && !dot_path.contains(']') {
316
- return Err(YerbaError::ParseError(format!("invalid path: unclosed bracket in '{}'", dot_path)));
371
+ if selector.contains('[') && !selector.contains(']') {
372
+ return Err(YerbaError::ParseError(format!("invalid selector: unclosed bracket in '{}'", selector)));
317
373
  }
318
374
 
319
375
  Ok(())
@@ -487,6 +543,10 @@ impl Document {
487
543
  self.root.text().to_string()
488
544
  }
489
545
 
546
+ fn line_index(&self) -> &LineIndex {
547
+ self.line_index.get_or_init(|| LineIndex::new(&self.source_text()))
548
+ }
549
+
490
550
  fn reparse(&mut self, new_source: &str) -> Result<(), YerbaError> {
491
551
  let document = Self::parse(new_source)?;
492
552
  let path = self.path.take();
@@ -538,17 +598,19 @@ fn check_duplicate_keys(root: &SyntaxNode) -> Result<(), YerbaError> {
538
598
  Ok(())
539
599
  }
540
600
 
541
- pub(crate) fn compute_location(source: &str, start_offset: usize, end_offset: usize) -> Location {
542
- let start = start_offset.min(source.len());
543
- let end = end_offset.min(source.len());
601
+ pub(crate) fn compute_location(index: &LineIndex, start_offset: usize, end_offset: usize) -> Location {
602
+ let start = start_offset.min(index.source_length());
603
+ let end = end_offset.min(index.source_length());
544
604
 
545
605
  Location {
546
606
  start_offset: start,
547
607
  end_offset: end,
548
- start_line: line_at(source, start),
549
- start_column: column_at(source, start),
550
- end_line: line_at(source, end),
551
- end_column: column_at(source, end),
608
+ start_line: index.line_at(start),
609
+ start_column: index.column_at(start),
610
+ end_line: index.line_at(end),
611
+ end_column: index.column_at(end),
612
+ start_character_column: index.character_column_at(start),
613
+ end_character_column: index.character_column_at(end),
552
614
  }
553
615
  }
554
616
 
@@ -635,25 +697,17 @@ pub(crate) fn node_to_yaml_value(node: &SyntaxNode) -> yaml_serde::Value {
635
697
  }
636
698
 
637
699
  if let Some(scalar) = extract_scalar(node) {
638
- use crate::syntax::{detect_yaml_type, is_yaml_truthy, YerbaValueType};
639
-
640
- return match detect_yaml_type(&scalar) {
641
- YerbaValueType::Null => yaml_serde::Value::Null,
642
- YerbaValueType::Boolean => yaml_serde::Value::Bool(is_yaml_truthy(&scalar.text)),
643
-
644
- YerbaValueType::Integer => scalar
645
- .text
646
- .parse::<i64>()
647
- .map(|n| yaml_serde::Value::Number(yaml_serde::Number::from(n)))
648
- .unwrap_or(yaml_serde::Value::String(scalar.text)),
649
-
650
- YerbaValueType::Float => scalar
651
- .text
652
- .parse::<f64>()
653
- .map(|n| yaml_serde::Value::Number(yaml_serde::Number::from(n)))
654
- .unwrap_or(yaml_serde::Value::String(scalar.text)),
655
-
656
- YerbaValueType::String => yaml_serde::Value::String(scalar.text),
700
+ use crate::syntax::{resolve_scalar, PlainScalar};
701
+
702
+ return match resolve_scalar(&scalar) {
703
+ PlainScalar::Null => yaml_serde::Value::Null,
704
+ PlainScalar::Boolean(boolean) => yaml_serde::Value::Bool(boolean),
705
+ PlainScalar::Integer(integer) => yaml_serde::Value::Number(match i64::try_from(integer) {
706
+ Ok(integer) => yaml_serde::Number::from(integer),
707
+ Err(_) => yaml_serde::Number::from(integer as u64),
708
+ }),
709
+ PlainScalar::Float(float) => yaml_serde::Value::Number(yaml_serde::Number::from(float)),
710
+ PlainScalar::String => yaml_serde::Value::String(scalar.text),
657
711
  };
658
712
  }
659
713
 
@@ -728,6 +782,26 @@ fn resolve_segment(node: &SyntaxNode, segment: &crate::selector::SelectorSegment
728
782
  }
729
783
  }
730
784
 
785
+ SelectorSegment::IndexFromEnd(_) => {
786
+ if let Some(sequence) = find_block_sequence(node) {
787
+ segment
788
+ .sequence_index(sequence.entries().count())
789
+ .and_then(|index| sequence.entries().nth(index))
790
+ .map(|entry| vec![entry.syntax().clone()])
791
+ .unwrap_or_default()
792
+ } else if let Some(sequence) = find_flow_sequence(node) {
793
+ let entries = flow_sequence_entries(&sequence);
794
+
795
+ segment
796
+ .sequence_index(entries.len())
797
+ .and_then(|index| entries.into_iter().nth(index))
798
+ .map(|entry| vec![entry])
799
+ .unwrap_or_default()
800
+ } else {
801
+ Vec::new()
802
+ }
803
+ }
804
+
731
805
  SelectorSegment::AllKeys => {
732
806
  if let Some(map) = find_block_map(node) {
733
807
  map.entries().filter_map(|entry| entry.value().map(|value| value.syntax().clone())).collect()
@@ -765,8 +839,8 @@ fn resolve_segment(node: &SyntaxNode, segment: &crate::selector::SelectorSegment
765
839
  }
766
840
  }
767
841
 
768
- pub(crate) fn navigate_from_node(node: &SyntaxNode, path: &str) -> Vec<SyntaxNode> {
769
- let parsed = crate::selector::Selector::parse(path);
842
+ pub(crate) fn navigate_from_node(node: &SyntaxNode, selector: &str) -> Vec<SyntaxNode> {
843
+ let parsed = crate::selector::Selector::parse(selector);
770
844
 
771
845
  navigate_remaining(node, parsed.segments())
772
846
  }
@@ -0,0 +1,162 @@
1
+ use super::*;
2
+
3
+ #[derive(Debug)]
4
+ pub struct NodeRecord {
5
+ pub parent: Option<usize>,
6
+ pub node_type: NodeType,
7
+ pub selector: String,
8
+ pub key_name: Option<String>,
9
+ pub scalar: Option<ScalarValue>,
10
+ pub has_value: bool,
11
+ pub location: Location,
12
+ pub key_location: Location,
13
+ }
14
+
15
+ fn location_of(lines: &LineIndex, range: TextRange) -> Location {
16
+ compute_location(lines, range.start().into(), range.end().into())
17
+ }
18
+
19
+ fn collection_type(node: &SyntaxNode) -> Option<NodeType> {
20
+ let mut flow = None;
21
+
22
+ for descendant in node.descendants() {
23
+ match descendant.kind() {
24
+ SyntaxKind::BLOCK_SEQ => return Some(NodeType::Sequence),
25
+ SyntaxKind::BLOCK_MAP => return Some(NodeType::Map),
26
+ SyntaxKind::FLOW_SEQ if flow.is_none() => flow = Some(NodeType::Sequence),
27
+ SyntaxKind::FLOW_MAP if flow.is_none() => flow = Some(NodeType::Map),
28
+ _ => {}
29
+ }
30
+ }
31
+
32
+ flow
33
+ }
34
+
35
+ struct Walker<'a> {
36
+ lines: &'a LineIndex,
37
+ records: Vec<NodeRecord>,
38
+ }
39
+
40
+ impl Walker<'_> {
41
+ fn push(&mut self, parent: Option<usize>, node: Option<&SyntaxNode>, selector: String, key: Option<(String, Location)>) {
42
+ let collection = node.and_then(collection_type);
43
+ let scalar = match (node, collection) {
44
+ (Some(node), None) => extract_scalar(node),
45
+ _ => None,
46
+ };
47
+ let node_type = match (collection, &scalar) {
48
+ (Some(node_type), _) => node_type,
49
+ (None, Some(_)) => NodeType::Scalar,
50
+ (None, None) => NodeType::NotFound,
51
+ };
52
+ let location = match node {
53
+ Some(node) if parent.is_some() || !matches!(node_type, NodeType::Sequence) => location_of(self.lines, node.text_range()),
54
+ _ => Location::default(),
55
+ };
56
+ let (key_name, key_location) = key.map(|(name, location)| (Some(name), location)).unwrap_or((None, Location::default()));
57
+
58
+ let index = self.records.len();
59
+
60
+ self.records.push(NodeRecord {
61
+ parent,
62
+ node_type,
63
+ selector: selector.clone(),
64
+ key_name,
65
+ scalar,
66
+ has_value: true,
67
+ location,
68
+ key_location,
69
+ });
70
+
71
+ if let Some(node) = node {
72
+ match node_type {
73
+ NodeType::Sequence => self.sequence_children(index, node, &selector),
74
+ NodeType::Map => self.map_children(index, node, &selector),
75
+ _ => {}
76
+ }
77
+ }
78
+ }
79
+
80
+ fn sequence_children(&mut self, index: usize, node: &SyntaxNode, selector: &str) {
81
+ let entries: Vec<SyntaxNode> = if let Some(sequence) = find_block_sequence(node) {
82
+ sequence.entries().map(|entry| entry.syntax().clone()).collect()
83
+ } else if let Some(sequence) = find_flow_sequence(node) {
84
+ flow_sequence_entries(&sequence)
85
+ } else {
86
+ Vec::new()
87
+ };
88
+
89
+ for (position, entry) in entries.iter().enumerate() {
90
+ self.push(Some(index), Some(entry), format!("{}[{}]", selector, position), None);
91
+ }
92
+ }
93
+
94
+ fn map_children(&mut self, index: usize, node: &SyntaxNode, selector: &str) {
95
+ let entries: Vec<(SyntaxNode, Option<SyntaxNode>, Option<SyntaxNode>)> = if let Some(map) = find_block_map(node) {
96
+ map
97
+ .entries()
98
+ .map(|entry| {
99
+ (
100
+ entry.syntax().clone(),
101
+ entry.key().map(|key| key.syntax().clone()),
102
+ entry.value().map(|value| value.syntax().clone()),
103
+ )
104
+ })
105
+ .collect()
106
+ } else if let Some(map) = find_flow_map(node) {
107
+ flow_map_entries(&map)
108
+ .into_iter()
109
+ .map(|entry| {
110
+ (
111
+ entry.syntax().clone(),
112
+ entry.key().map(|key| key.syntax().clone()),
113
+ entry.value().map(|value| value.syntax().clone()),
114
+ )
115
+ })
116
+ .collect()
117
+ } else {
118
+ Vec::new()
119
+ };
120
+
121
+ for (entry_node, key_node, value_node) in entries {
122
+ let Some(key_node) = key_node else { continue };
123
+ let Some(key_name) = extract_scalar_text(&key_node) else { continue };
124
+
125
+ let key_location = location_of(self.lines, key_node.text_range());
126
+ let child_selector = if selector.is_empty() {
127
+ key_name.clone()
128
+ } else {
129
+ format!("{}.{}", selector, key_name)
130
+ };
131
+
132
+ match value_node {
133
+ Some(value_node) => self.push(Some(index), Some(&value_node), child_selector, Some((key_name, key_location))),
134
+ None => self.records.push(NodeRecord {
135
+ parent: Some(index),
136
+ node_type: NodeType::Scalar,
137
+ selector: child_selector,
138
+ key_name: Some(key_name),
139
+ scalar: None,
140
+ has_value: false,
141
+ location: location_of(self.lines, entry_node.text_range()),
142
+ key_location,
143
+ }),
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ impl Document {
150
+ pub fn node_records(&self) -> Vec<NodeRecord> {
151
+ let mut walker = Walker {
152
+ lines: self.line_index(),
153
+ records: Vec::new(),
154
+ };
155
+
156
+ if let Some(document) = Root::cast(self.root.clone()).and_then(|root| root.documents().next()) {
157
+ walker.push(None, Some(document.syntax()), String::new(), None);
158
+ }
159
+
160
+ walker.records
161
+ }
162
+ }
@@ -2,10 +2,10 @@ use super::*;
2
2
 
3
3
  impl Document {
4
4
  pub fn validate_schema(&self, schema: &serde_json::Value, items: bool, selector: Option<&str>) -> Vec<crate::schema::ValidationError> {
5
- let path = selector.unwrap_or("");
6
- let has_wildcard = crate::selector::Selector::parse(path).has_wildcard();
5
+ let selector = selector.unwrap_or("");
6
+ let has_wildcard = crate::selector::Selector::parse(selector).has_wildcard();
7
7
 
8
- let value = match self.get_value(path) {
8
+ let value = match self.get_value(selector) {
9
9
  Some(value) => crate::json::yaml_to_json(&value),
10
10
  None => return vec![],
11
11
  };
@@ -62,12 +62,12 @@ fn json_pointer_to_selector(pointer: &str) -> String {
62
62
  segment.to_string()
63
63
  }
64
64
  })
65
- .fold(String::new(), |mut path, segment| {
66
- if !path.is_empty() && !segment.starts_with('[') {
67
- path.push('.');
65
+ .fold(String::new(), |mut selector, segment| {
66
+ if !selector.is_empty() && !segment.starts_with('[') {
67
+ selector.push('.');
68
68
  }
69
69
 
70
- path.push_str(&segment);
71
- path
70
+ selector.push_str(&segment);
71
+ selector
72
72
  })
73
73
  }