Skip to content

Commit 57c85bd

Browse files
Remove need to give JSON file path
1 parent 9c20b2a commit 57c85bd

File tree

2 files changed

+53
-107
lines changed

2 files changed

+53
-107
lines changed

src/tools/jsondocck/src/cache.rs

+12-58
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,31 @@
1-
use crate::error::CkError;
1+
use crate::config::Config;
22
use serde_json::Value;
33
use std::collections::HashMap;
4-
use std::io;
5-
use std::path::{Path, PathBuf};
4+
use std::path::Path;
65

76
use fs_err as fs;
87

98
#[derive(Debug)]
109
pub struct Cache {
11-
root: PathBuf,
12-
files: HashMap<PathBuf, String>,
13-
values: HashMap<PathBuf, Value>,
10+
value: Value,
1411
pub variables: HashMap<String, Value>,
15-
last_path: Option<PathBuf>,
1612
}
1713

1814
impl Cache {
1915
/// Create a new cache, used to read files only once and otherwise store their contents.
20-
pub fn new(doc_dir: &str) -> Cache {
16+
pub fn new(config: &Config) -> Cache {
17+
let root = Path::new(&config.doc_dir);
18+
let filename = Path::new(&config.template).file_stem().unwrap();
19+
let file_path = root.join(&Path::with_extension(Path::new(filename), "json"));
20+
let content = fs::read_to_string(&file_path).expect("failed to read JSON file");
21+
2122
Cache {
22-
root: Path::new(doc_dir).to_owned(),
23-
files: HashMap::new(),
24-
values: HashMap::new(),
23+
value: serde_json::from_str::<Value>(&content).expect("failed to convert from JSON"),
2524
variables: HashMap::new(),
26-
last_path: None,
2725
}
2826
}
2927

30-
fn resolve_path(&mut self, path: &String) -> PathBuf {
31-
if path != "-" {
32-
let resolve = self.root.join(path);
33-
self.last_path = Some(resolve.clone());
34-
resolve
35-
} else {
36-
self.last_path
37-
.as_ref()
38-
// FIXME: Point to a line number
39-
.expect("No last path set. Make sure to specify a full path before using `-`")
40-
.clone()
41-
}
42-
}
43-
44-
fn read_file(&mut self, path: PathBuf) -> Result<String, io::Error> {
45-
if let Some(f) = self.files.get(&path) {
46-
return Ok(f.clone());
47-
}
48-
49-
let file = fs::read_to_string(&path)?;
50-
51-
self.files.insert(path, file.clone());
52-
53-
Ok(file)
54-
}
55-
56-
/// Get the text from a file. If called multiple times, the file will only be read once
57-
pub fn get_file(&mut self, path: &String) -> Result<String, io::Error> {
58-
let path = self.resolve_path(path);
59-
self.read_file(path)
60-
}
61-
62-
/// Parse the JSON from a file. If called multiple times, the file will only be read once.
63-
pub fn get_value(&mut self, path: &String) -> Result<Value, CkError> {
64-
let path = self.resolve_path(path);
65-
66-
if let Some(v) = self.values.get(&path) {
67-
return Ok(v.clone());
68-
}
69-
70-
let content = self.read_file(path.clone())?;
71-
let val = serde_json::from_str::<Value>(&content)?;
72-
73-
self.values.insert(path, val.clone());
74-
75-
Ok(val)
28+
pub fn value(&self) -> &Value {
29+
&self.value
7630
}
7731
}

src/tools/jsondocck/src/main.rs

+41-49
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn main() -> Result<(), String> {
1717
let config = parse_config(env::args().collect());
1818

1919
let mut failed = Vec::new();
20-
let mut cache = Cache::new(&config.doc_dir);
20+
let mut cache = Cache::new(&config);
2121
let commands = get_commands(&config.template)
2222
.map_err(|_| format!("Jsondocck failed for {}", &config.template))?;
2323

@@ -55,28 +55,23 @@ pub enum CommandKind {
5555
}
5656

5757
impl CommandKind {
58-
fn validate(&self, args: &[String], command_num: usize, lineno: usize) -> bool {
58+
fn validate(&self, args: &[String], lineno: usize) -> bool {
5959
let count = match self {
60-
CommandKind::Has => (1..=3).contains(&args.len()),
61-
CommandKind::IsMany => args.len() >= 3,
62-
CommandKind::Count | CommandKind::Is => 3 == args.len(),
63-
CommandKind::Set => 4 == args.len(),
60+
CommandKind::Has => (1..=2).contains(&args.len()),
61+
CommandKind::IsMany => args.len() >= 2,
62+
CommandKind::Count | CommandKind::Is => 2 == args.len(),
63+
CommandKind::Set => 3 == args.len(),
6464
};
6565

6666
if !count {
6767
print_err(&format!("Incorrect number of arguments to `@{}`", self), lineno);
6868
return false;
6969
}
7070

71-
if args[0] == "-" && command_num == 0 {
72-
print_err(&format!("Tried to use the previous path in the first command"), lineno);
73-
return false;
74-
}
75-
7671
if let CommandKind::Count = self {
77-
if args[2].parse::<usize>().is_err() {
72+
if args[1].parse::<usize>().is_err() {
7873
print_err(
79-
&format!("Third argument to @count must be a valid usize (got `{}`)", args[2]),
74+
&format!("Second argument to @count must be a valid usize (got `{}`)", args[2]),
8075
lineno,
8176
);
8277
return false;
@@ -181,7 +176,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
181176
}
182177
};
183178

184-
if !cmd.validate(&args, commands.len(), lineno) {
179+
if !cmd.validate(&args, lineno) {
185180
errors = true;
186181
continue;
187182
}
@@ -199,26 +194,24 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
199194
let result = match command.kind {
200195
CommandKind::Has => {
201196
match command.args.len() {
202-
// @has <path> = file existence
203-
1 => cache.get_file(&command.args[0]).is_ok(),
204-
// @has <path> <jsonpath> = check path exists
205-
2 => {
206-
let val = cache.get_value(&command.args[0])?;
207-
let results = select(&val, &command.args[1]).unwrap();
197+
// @has <jsonpath> = check path exists
198+
1 => {
199+
let val = cache.value();
200+
let results = select(val, &command.args[0]).unwrap();
208201
!results.is_empty()
209202
}
210-
// @has <path> <jsonpath> <value> = check *any* item matched by path equals value
211-
3 => {
212-
let val = cache.get_value(&command.args[0])?;
213-
let results = select(&val, &command.args[1]).unwrap();
214-
let pat = string_to_value(&command.args[2], cache);
203+
// @has <jsonpath> <value> = check *any* item matched by path equals value
204+
2 => {
205+
let val = cache.value().clone();
206+
let results = select(&val, &command.args[0]).unwrap();
207+
let pat = string_to_value(&command.args[1], cache);
215208
let has = results.contains(&pat.as_ref());
216209
// Give better error for when @has check fails
217210
if !command.negated && !has {
218211
return Err(CkError::FailedCheck(
219212
format!(
220213
"{} matched to {:?} but didn't have {:?}",
221-
&command.args[1],
214+
&command.args[0],
222215
results,
223216
pat.as_ref()
224217
),
@@ -233,13 +226,13 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
233226
}
234227
CommandKind::IsMany => {
235228
// @ismany <path> <jsonpath> <value>...
236-
let (path, query, values) = if let [path, query, values @ ..] = &command.args[..] {
237-
(path, query, values)
229+
let (query, values) = if let [query, values @ ..] = &command.args[..] {
230+
(query, values)
238231
} else {
239232
unreachable!("Checked in CommandKind::validate")
240233
};
241-
let val = cache.get_value(path)?;
242-
let got_values = select(&val, &query).unwrap();
234+
let val = cache.value();
235+
let got_values = select(val, &query).unwrap();
243236
assert!(!command.negated, "`@!ismany` is not supported");
244237

245238
// Serde json doesn't implement Ord or Hash for Value, so we must
@@ -270,18 +263,17 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
270263
true
271264
}
272265
CommandKind::Count => {
273-
// @count <path> <jsonpath> <count> = Check that the jsonpath matches exactly [count] times
274-
assert_eq!(command.args.len(), 3);
275-
let expected: usize = command.args[2].parse().unwrap();
276-
277-
let val = cache.get_value(&command.args[0])?;
278-
let results = select(&val, &command.args[1]).unwrap();
266+
// @count <jsonpath> <count> = Check that the jsonpath matches exactly [count] times
267+
assert_eq!(command.args.len(), 2);
268+
let expected: usize = command.args[1].parse().unwrap();
269+
let val = cache.value();
270+
let results = select(val, &command.args[0]).unwrap();
279271
let eq = results.len() == expected;
280272
if !command.negated && !eq {
281273
return Err(CkError::FailedCheck(
282274
format!(
283275
"`{}` matched to `{:?}` with length {}, but expected length {}",
284-
&command.args[1],
276+
&command.args[0],
285277
results,
286278
results.len(),
287279
expected
@@ -293,17 +285,17 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
293285
}
294286
}
295287
CommandKind::Is => {
296-
// @has <path> <jsonpath> <value> = check *exactly one* item matched by path, and it equals value
297-
assert_eq!(command.args.len(), 3);
298-
let val = cache.get_value(&command.args[0])?;
299-
let results = select(&val, &command.args[1]).unwrap();
300-
let pat = string_to_value(&command.args[2], cache);
288+
// @has <jsonpath> <value> = check *exactly one* item matched by path, and it equals value
289+
assert_eq!(command.args.len(), 2);
290+
let val = cache.value().clone();
291+
let results = select(&val, &command.args[0]).unwrap();
292+
let pat = string_to_value(&command.args[1], cache);
301293
let is = results.len() == 1 && results[0] == pat.as_ref();
302294
if !command.negated && !is {
303295
return Err(CkError::FailedCheck(
304296
format!(
305297
"{} matched to {:?}, but expected {:?}",
306-
&command.args[1],
298+
&command.args[0],
307299
results,
308300
pat.as_ref()
309301
),
@@ -314,16 +306,16 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
314306
}
315307
}
316308
CommandKind::Set => {
317-
// @set <name> = <path> <jsonpath>
318-
assert_eq!(command.args.len(), 4);
309+
// @set <name> = <jsonpath>
310+
assert_eq!(command.args.len(), 3);
319311
assert_eq!(command.args[1], "=", "Expected an `=`");
320-
let val = cache.get_value(&command.args[2])?;
321-
let results = select(&val, &command.args[3]).unwrap();
312+
let val = cache.value().clone();
313+
let results = select(&val, &command.args[2]).unwrap();
322314
assert_eq!(
323315
results.len(),
324316
1,
325317
"Expected 1 match for `{}` (because of @set): matched to {:?}",
326-
command.args[3],
318+
command.args[2],
327319
results
328320
);
329321
match results.len() {
@@ -336,7 +328,7 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
336328
_ => {
337329
panic!(
338330
"Got multiple results in `@set` for `{}`: {:?}",
339-
&command.args[3], results
331+
&command.args[2], results,
340332
);
341333
}
342334
}

0 commit comments

Comments
 (0)