mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-10-26 08:18:26 +03:00
Include line number prefix in DisplaySourceError message
This commit is contained in:
parent
57f465e3b1
commit
9054a3434e
@ -78,7 +78,9 @@ impl DisplaySourceError for OutputError {
|
||||
let mut text = StyledString::new();
|
||||
hurl_core::error::add_source_line(&mut text, content, self.source_info().start.line);
|
||||
text.append(self.fixme(content));
|
||||
text
|
||||
|
||||
let error_line = self.source_info().start.line;
|
||||
hurl_core::error::add_line_info_prefix(&text, content, error_line)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,7 +294,9 @@ impl DisplaySourceError for RunnerError {
|
||||
let mut text = StyledString::new();
|
||||
hurl_core::error::add_source_line(&mut text, content, self.source_info().start.line);
|
||||
text.append(self.fixme(content));
|
||||
text
|
||||
|
||||
let error_line = self.source_info().start.line;
|
||||
hurl_core::error::add_line_info_prefix(&text, content, error_line)
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,7 +336,7 @@ mod tests {
|
||||
error
|
||||
.message(&split_lines(content))
|
||||
.to_string(Format::Plain),
|
||||
" GET http://unknown\n ^^^^^^^^^^^^^^ (6) Could not resolve host: unknown"
|
||||
"\n 1 | GET http://unknown\n | ^^^^^^^^^^^^^^ (6) Could not resolve host: unknown\n |"
|
||||
);
|
||||
assert_eq!(
|
||||
error_string(filename, content, &error, Some(entry_source_info), false),
|
||||
@ -364,12 +366,12 @@ HTTP/1.0 200
|
||||
error
|
||||
.message(&split_lines(content))
|
||||
.to_string(Format::Plain),
|
||||
" HTTP/1.0 200\n ^^^ actual value is <404>"
|
||||
"\n 2 | HTTP/1.0 200\n | ^^^ actual value is <404>\n |"
|
||||
);
|
||||
colored::control::set_override(true);
|
||||
assert_eq!(
|
||||
error.message(&split_lines(content)).to_string(Format::Ansi),
|
||||
" HTTP/1.0 200\n\u{1b}[1;31m ^^^ actual value is <404>\u{1b}[0m",
|
||||
"\n\u{1b}[1;34m 2 |\u{1b}[0m HTTP/1.0 200\n\u{1b}[1;34m |\u{1b}[0m\u{1b}[1;31m ^^^ actual value is <404>\u{1b}[0m\n\u{1b}[1;34m |\u{1b}[0m"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@ -401,7 +403,7 @@ xpath "strong(//head/title)" == "Hello"
|
||||
);
|
||||
assert_eq!(
|
||||
&error.message( &split_lines(content)).to_string(Format::Plain),
|
||||
" xpath \"strong(//head/title)\" == \"Hello\"\n ^^^^^^^^^^^^^^^^^^^^^^ the XPath expression is not valid"
|
||||
"\n 4 | xpath \"strong(//head/title)\" == \"Hello\"\n | ^^^^^^^^^^^^^^^^^^^^^^ the XPath expression is not valid\n |"
|
||||
);
|
||||
assert_eq!(
|
||||
error_string(filename, content, &error, Some(entry_source_info), false),
|
||||
@ -440,9 +442,11 @@ jsonpath "$.count" >= 5
|
||||
error
|
||||
.message(&split_lines(content))
|
||||
.to_string(Format::Plain),
|
||||
r#" jsonpath "$.count" >= 5
|
||||
actual: int <2>
|
||||
expected: greater than int <5>"#
|
||||
r#"
|
||||
4 | jsonpath "$.count" >= 5
|
||||
| actual: int <2>
|
||||
| expected: greater than int <5>
|
||||
|"#
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@ -479,7 +483,7 @@ HTTP/1.0 200
|
||||
error
|
||||
.message(&split_lines(content))
|
||||
.to_string(Format::Plain),
|
||||
" ```<p>Hello</p>\n ^ actual value is <<p>Hello</p>\n\n >"
|
||||
"\n 3 | ```<p>Hello</p>\n | ^ actual value is <<p>Hello</p>\n |\n | >\n |"
|
||||
);
|
||||
assert_eq!(
|
||||
error_string(filename, content, &error, Some(entry_source_info), false),
|
||||
|
@ -16,7 +16,7 @@
|
||||
*
|
||||
*/
|
||||
use crate::ast::SourceInfo;
|
||||
use crate::text::{Format, StyledString};
|
||||
use crate::text::{Format, Style, StyledString};
|
||||
use colored::Colorize;
|
||||
use std::cmp::max;
|
||||
|
||||
@ -121,13 +121,6 @@ pub fn error_string<E: DisplaySourceError>(
|
||||
prefix.to_string()
|
||||
};
|
||||
|
||||
let prefix_with_number = format!("{error_line:>loc_max_width$} {separator}");
|
||||
let prefix_with_number = if colored {
|
||||
prefix_with_number.blue().bold().to_string()
|
||||
} else {
|
||||
prefix_with_number.to_string()
|
||||
};
|
||||
|
||||
// 1. First line is the description, ex. `Assert status code`.
|
||||
let description = if colored {
|
||||
error.description().bold().to_string()
|
||||
@ -180,7 +173,6 @@ pub fn error_string<E: DisplaySourceError>(
|
||||
}
|
||||
|
||||
// 5. Appends the error message (one or more lines)
|
||||
// with the line number '|' prefix
|
||||
let message = error.message(&lines);
|
||||
let message = if colored {
|
||||
message.to_string(Format::Ansi)
|
||||
@ -188,21 +180,57 @@ pub fn error_string<E: DisplaySourceError>(
|
||||
message.to_string(Format::Plain)
|
||||
};
|
||||
|
||||
for (i, line) in split_lines(&message).iter().enumerate() {
|
||||
text.push('\n');
|
||||
text.push_str(if i == 0 { &prefix_with_number } else { &prefix });
|
||||
text.push_str(line);
|
||||
}
|
||||
|
||||
// 6. Appends additional empty line
|
||||
if !message.ends_with('\n') {
|
||||
text.push('\n');
|
||||
text.push_str(&prefix);
|
||||
}
|
||||
text.push_str(&message);
|
||||
|
||||
text
|
||||
}
|
||||
|
||||
pub fn add_line_info_prefix(
|
||||
text: &StyledString,
|
||||
content: &[&str],
|
||||
error_line: usize,
|
||||
) -> StyledString {
|
||||
let text = text.clone();
|
||||
//dd_source_line(&mut text, content, error_line);
|
||||
|
||||
// eprintln!("text={:#?}", text);
|
||||
let separator = "|";
|
||||
|
||||
let loc_max_width = max(content.len().to_string().len(), 2);
|
||||
let spaces = " ".repeat(loc_max_width);
|
||||
let mut prefix = StyledString::new();
|
||||
prefix.push_with(
|
||||
format!("{spaces} {separator}").as_str(),
|
||||
Style::new().blue().bold(),
|
||||
);
|
||||
let mut prefix_with_number = StyledString::new();
|
||||
prefix_with_number.push_with(
|
||||
format!("{error_line:>loc_max_width$} {separator}").as_str(),
|
||||
Style::new().blue().bold(),
|
||||
);
|
||||
|
||||
let mut text2 = StyledString::new();
|
||||
for (i, line) in text.split('\n').iter().enumerate() {
|
||||
text2.push("\n");
|
||||
text2.append(if i == 0 {
|
||||
prefix_with_number.clone()
|
||||
} else {
|
||||
prefix.clone()
|
||||
});
|
||||
text2.append(line.clone());
|
||||
}
|
||||
|
||||
//eprintln!(">>> text2 {:#?}", text2);
|
||||
// Appends additional empty line
|
||||
if !text2.ends_with("|") {
|
||||
text2.push("\n");
|
||||
text2.append(prefix.clone());
|
||||
}
|
||||
// eprintln!(">>> text2 {:#?}", text2);
|
||||
|
||||
text2
|
||||
}
|
||||
|
||||
/// Splits this `text` to a list of LF/CRLF separated lines.
|
||||
pub fn split_lines(text: &str) -> Vec<&str> {
|
||||
regex::Regex::new(r"\n|\r\n").unwrap().split(text).collect()
|
||||
@ -313,7 +341,8 @@ HTTP 200
|
||||
diff
|
||||
}
|
||||
fn message(&self, lines: &[&str]) -> StyledString {
|
||||
self.fixme(lines)
|
||||
let s = self.fixme(lines);
|
||||
add_line_info_prefix(&s, &[], 4)
|
||||
}
|
||||
}
|
||||
let error = E;
|
||||
@ -323,16 +352,17 @@ HTTP 200
|
||||
error
|
||||
.message(&split_lines(content))
|
||||
.to_string(Format::Plain),
|
||||
r#" {
|
||||
"name": "John",
|
||||
- "age": 27
|
||||
+ "age": 28
|
||||
}
|
||||
"#
|
||||
r#"
|
||||
4 | {
|
||||
| "name": "John",
|
||||
|- "age": 27
|
||||
|+ "age": 28
|
||||
| }
|
||||
|"#
|
||||
);
|
||||
assert_eq!(
|
||||
error.message(&split_lines(content)).to_string(Format::Ansi),
|
||||
" {\n \"name\": \"John\",\n\u{1b}[31m- \"age\": 27\u{1b}[0m\n\u{1b}[32m+ \"age\": 28\u{1b}[0m\n }\n"
|
||||
"\n\u{1b}[1;34m 4 |\u{1b}[0m {\n\u{1b}[1;34m |\u{1b}[0m \"name\": \"John\",\n\u{1b}[1;34m |\u{1b}[0m\u{1b}[31m- \"age\": 27\u{1b}[0m\n\u{1b}[1;34m |\u{1b}[0m\u{1b}[32m+ \"age\": 28\u{1b}[0m\n\u{1b}[1;34m |\u{1b}[0m }\n\u{1b}[1;34m |\u{1b}[0m"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
@ -255,7 +255,9 @@ impl DisplaySourceError for ParseError {
|
||||
let mut text = StyledString::new();
|
||||
crate::error::add_source_line(&mut text, content, self.source_info().start.line);
|
||||
text.append(self.fixme(content));
|
||||
text
|
||||
|
||||
let error_line = self.source_info().start.line;
|
||||
crate::error::add_line_info_prefix(&text, content, error_line)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,10 @@ impl StyledString {
|
||||
items.push(item);
|
||||
items
|
||||
}
|
||||
|
||||
pub fn ends_with(&self, value: &str) -> bool {
|
||||
self.to_string(Format::Plain).ends_with(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Token {
|
||||
@ -276,6 +280,14 @@ mod tests {
|
||||
assert_eq!(line.split(','), vec![item0, item1, item2, item3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ends_with() {
|
||||
let mut line = StyledString::new();
|
||||
line.push("Hello,Hi,");
|
||||
assert!(line.ends_with(","));
|
||||
assert!(!line.ends_with("\n"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compare_with_crate_colored() {
|
||||
// These tests are used to check regression against the [colored crate](https://crates.io/crates/colored).
|
||||
|
@ -53,6 +53,8 @@ impl DisplaySourceError for linter::Error {
|
||||
let mut text = StyledString::new();
|
||||
hurl_core::error::add_source_line(&mut text, content, self.source_info().start.line);
|
||||
text.append(self.fixme(content));
|
||||
text
|
||||
|
||||
let error_line = self.source_info().start.line;
|
||||
hurl_core::error::add_line_info_prefix(&text, content, error_line)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user