Skip to content

Commit 127a480

Browse files
authored
Merge pull request #2915 from Xanewok/file-lines-ser-json
Expose FileLines JSON representation
2 parents a275a05 + 9d52940 commit 127a480

File tree

1 file changed

+81
-12
lines changed

1 file changed

+81
-12
lines changed

src/config/file_lines.rs

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use std::rc::Rc;
1616
use std::{cmp, fmt, iter, str};
1717

1818
use serde::de::{Deserialize, Deserializer};
19+
use serde::ser::{self, Serialize, Serializer};
1920
use serde_json as json;
2021

2122
use syntax::codemap::{self, FileMap};
@@ -53,6 +54,36 @@ impl fmt::Display for FileName {
5354
}
5455
}
5556

57+
impl<'de> Deserialize<'de> for FileName {
58+
fn deserialize<D>(deserializer: D) -> Result<FileName, D::Error>
59+
where
60+
D: Deserializer<'de>,
61+
{
62+
let s = String::deserialize(deserializer)?;
63+
if s == "stdin" {
64+
Ok(FileName::Stdin)
65+
} else {
66+
Ok(FileName::Real(s.into()))
67+
}
68+
}
69+
}
70+
71+
impl Serialize for FileName {
72+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73+
where
74+
S: Serializer,
75+
{
76+
let s = match self {
77+
FileName::Stdin => Ok("stdin"),
78+
FileName::Real(path) => path
79+
.to_str()
80+
.ok_or_else(|| ser::Error::custom("path can't be serialized as UTF-8 string")),
81+
};
82+
83+
s.and_then(|s| serializer.serialize_str(s))
84+
}
85+
}
86+
5687
impl LineRange {
5788
pub fn file_name(&self) -> FileName {
5889
self.file.name.clone().into()
@@ -175,6 +206,20 @@ impl FileLines {
175206
Files(self.0.as_ref().map(|m| m.keys()))
176207
}
177208

209+
/// Returns JSON representation as accepted by the `--file-lines JSON` arg.
210+
pub fn to_json_spans(&self) -> Vec<JsonSpan> {
211+
match &self.0 {
212+
None => vec![],
213+
Some(file_ranges) => file_ranges
214+
.iter()
215+
.flat_map(|(file, ranges)| ranges.iter().map(move |r| (file, r)))
216+
.map(|(file, range)| JsonSpan {
217+
file: file.to_owned(),
218+
range: (range.lo, range.hi),
219+
}).collect(),
220+
}
221+
}
222+
178223
/// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in
179224
/// the designated file (if any) and returns true if `f` ever does.
180225
fn file_range_matches<F>(&self, file_name: &FileName, f: F) -> bool
@@ -249,22 +294,12 @@ impl str::FromStr for FileLines {
249294
}
250295

251296
// For JSON decoding.
252-
#[derive(Clone, Debug, Deserialize)]
253-
struct JsonSpan {
254-
#[serde(deserialize_with = "deserialize_filename")]
297+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Deserialize, Serialize)]
298+
pub struct JsonSpan {
255299
file: FileName,
256300
range: (usize, usize),
257301
}
258302

259-
fn deserialize_filename<'de, D: Deserializer<'de>>(d: D) -> Result<FileName, D::Error> {
260-
let s = String::deserialize(d)?;
261-
if s == "stdin" {
262-
Ok(FileName::Stdin)
263-
} else {
264-
Ok(FileName::Real(s.into()))
265-
}
266-
}
267-
268303
impl JsonSpan {
269304
fn into_tuple(self) -> Result<(FileName, Range), String> {
270305
let (lo, hi) = self.range;
@@ -350,4 +385,38 @@ mod test {
350385
Range::new(3, 7).merge(Range::new(4, 5))
351386
);
352387
}
388+
389+
use super::json::{self, json, json_internal};
390+
use super::{FileLines, FileName};
391+
use std::{collections::HashMap, path::PathBuf};
392+
393+
#[test]
394+
fn file_lines_to_json() {
395+
let ranges: HashMap<FileName, Vec<Range>> = [
396+
(
397+
FileName::Real(PathBuf::from("src/main.rs")),
398+
vec![Range::new(1, 3), Range::new(5, 7)],
399+
),
400+
(
401+
FileName::Real(PathBuf::from("src/lib.rs")),
402+
vec![Range::new(1, 7)],
403+
),
404+
]
405+
.iter()
406+
.cloned()
407+
.collect();
408+
409+
let file_lines = FileLines::from_ranges(ranges);
410+
let mut spans = file_lines.to_json_spans();
411+
spans.sort();
412+
let json = json::to_value(&spans).unwrap();
413+
assert_eq!(
414+
json,
415+
json! {[
416+
{"file": "src/lib.rs", "range": [1, 7]},
417+
{"file": "src/main.rs", "range": [1, 3]},
418+
{"file": "src/main.rs", "range": [5, 7]},
419+
]}
420+
);
421+
}
353422
}

0 commit comments

Comments
 (0)