Include carets in fixme message

This commit is contained in:
Fabrice Reix 2024-04-10 15:23:10 +02:00
parent 151a139701
commit ff7ff9543d
No known key found for this signature in database
GPG Key ID: BF5213154B2E7155
11 changed files with 263 additions and 167 deletions

View File

@ -2,6 +2,6 @@
--> tests_error_parser/parallel_parsing_error_c.hurl:4:5
 |
 4 | GET //localhost:8000/hello
 | ^ expecting http://, https:// or {{
 | ^ expecting http://, https:// or {{
 |

View File

@ -4,34 +4,34 @@
 | GET http://localhost:8000/error/multiline
 | ...
 4 | {
 | ^ actual value is <{
 |  "first_name": "John",
 |  "last_name": "Smith",
 |  "is_alive": true,
 |  "age": 28,
 |  "address": {
 |  "street_address": "21 2nd Street",
 |  "city": "New York",
 |  "state": "NY",
 |  "postal_code": "10021-3100"
 |  },
 |  "phone_numbers": [
 |  {
 |  "type": "home",
 |  "number": "212 555-1234"
 |  },
 |  {
 |  "type": "office",
 |  "number": "646 555-4567"
 |  }
 |  ],
 |  "children": [
 |  "Catherine",
 |  "Thomas",
 |  "Trevor"
 |  ],
 |  "spouse": null
 | }
 | >
 | ^ actual value is <{
 | "first_name": "John",
 | "last_name": "Smith",
 | "is_alive": true,
 | "age": 28,
 | "address": {
 | "street_address": "21 2nd Street",
 | "city": "New York",
 | "state": "NY",
 | "postal_code": "10021-3100"
 | },
 | "phone_numbers": [
 | {
 | "type": "home",
 | "number": "212 555-1234"
 | },
 | {
 | "type": "office",
 | "number": "646 555-4567"
 | }
 | ],
 | "children": [
 | "Catherine",
 | "Thomas",
 | "Trevor"
 | ],
 | "spouse": null
 | }
 | >
 |

View File

@ -4,7 +4,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
 6 | `Hello World`
 | ^^^^^^^^^^^^^ actual value is <Hello World!>
 | ^^^^^^^^^^^^^ actual value is <Hello World!>
 |
error: Assert failure
@ -13,8 +13,8 @@
 | GET http://localhost:8000/runner_errors
 | ...
 12 | body == "Hello World"
 | actual: string <Hello World!>
 | expected: string <Hello World>
 | actual: string <Hello World!>
 | expected: string <Hello World>
 |
error: Assert header value
@ -23,7 +23,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
 17 | Content-Length: 200
 | ^^^ actual value is <12>
 | ^^^ actual value is <12>
 |
error: Assert status code
@ -31,7 +31,7 @@
 |
 | GET http://localhost:8000/undefined
 21 | HTTP 200
 | ^^^ actual value is <404>
 | ^^^ actual value is <404>
 |
error: Assert HTTP version
@ -39,7 +39,7 @@
 |
 | GET http://localhost:8000/undefined
 25 | HTTP/3 *
 | ^^^^^^ actual value is <HTTP/1.1>
 | ^^^^^^ actual value is <HTTP/1.1>
 |
error: Decompression error
@ -48,7 +48,7 @@
 | GET http://localhost:8000/runner_errors/could_not_uncompress
 | ...
 31 | body startsWith "Hello"
 | ^^^^ could not uncompress response with brotli
 | ^^^^ could not uncompress response with brotli
 |
error: File read access
@ -56,7 +56,7 @@
 |
 | GET http://localhost:8000/undefined
 35 | file,undefined.txt;
 | ^^^^^^^^^^^^^ file undefined.txt can not be read
 | ^^^^^^^^^^^^^ file undefined.txt can not be read
 |
warning: tests_failed~~~output can not be written (~~~)
@ -66,7 +66,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
 46 | md5 decode "utf-8" == "café"
 | ^^^^^^^^^^^^^^ value can not be decoded with <utf-8> encoding
 | ^^^^^^^^^^^^^^ value can not be decoded with <utf-8> encoding
 |
error: Filter error
@ -75,7 +75,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
 52 | bytes decode "toto" == "café"
 | ^^^^^^^^^^^^^ <toto> encoding is not supported
 | ^^^^^^^^^^^^^ <toto> encoding is not supported
 |
error: Filter error
@ -84,7 +84,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
 58 | body toInt == 1
 | ^^^^^ invalid filter input: string <Hello World!>
 | ^^^^^ invalid filter input: string <Hello World!>
 |
error: Filter error
@ -93,14 +93,14 @@
 | GET http://localhost:8000/runner_errors
 | ...
 64 | header "count" toInt == 1
 | ^^^^^ missing value to apply filter
 | ^^^^^ missing value to apply filter
 |
error: HTTP connection
--> tests_failed/runner_errors.hurl:67:5
 |
 67 | GET http://unknown
 | ^^^^^^^^^^^^^^ (6) Could not resolve host: unknown
 | ^^^^^^^^^^^^^^ (6) Could not resolve host: unknown
 |
error: Invalid charset
@ -109,7 +109,7 @@
 | GET http://localhost:8000/runner_errors/invalid-charset
 | ...
 73 | body == "Hello"
 | ^^^^ the charset 'unknown' is not valid
 | ^^^^ the charset 'unknown' is not valid
 |
error: Invalid decoding
@ -118,7 +118,7 @@
 | GET http://localhost:8000/runner_errors/invalid-decoding
 | ...
 79 | body == "Hello"
 | ^^^^ the body can not be decoded with charset 'utf-8'
 | ^^^^ the body can not be decoded with charset 'utf-8'
 |
error: Invalid JSON
@ -127,7 +127,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
 85 | { "a": {{x}} }
 | ^ actual value is <a>
 | ^ actual value is <a>
 |
error: Invalid regex
@ -136,14 +136,14 @@
 | GET http://localhost:8000/runner_errors
 | ...
 91 | body regex "{}" == "a"
 | ^^^^ regex expression is not valid
 | ^^^^ regex expression is not valid
 |
error: Invalid URL
--> tests_failed/runner_errors.hurl:94:5
 |
 94 | GET {{url}}
 | ^^^^^^^ invalid URL <localhost:8000/runner_errors> (Missing protocol http or https)
 | ^^^^^^^ invalid URL <localhost:8000/runner_errors> (Missing protocol http or https)
 |
error: No query result
@ -152,7 +152,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
102 | count: header "count"
 | ^^^^^^^^^^^^^^ The query didn't return any result
 | ^^^^^^^^^^^^^^ The query didn't return any result
 |
error: Header not found
@ -161,7 +161,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
107 | count: 10
 | ^^^^^ this header has not been found in the response
 | ^^^^^ this header has not been found in the response
 |
error: Invalid JSON
@ -170,7 +170,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
113 | jsonpath "$.count" == 10
 | ^^^^^^^^^^^^^^^^^^ the HTTP response is not a valid JSON
 | ^^^^^^^^^^^^^^^^^^ the HTTP response is not a valid JSON
 |
error: Invalid JSONPath
@ -179,7 +179,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
119 | jsonpath "xxx" == 10
 | ^^^^^ the JSONPath expression 'xxx' is not valid
 | ^^^^^ the JSONPath expression 'xxx' is not valid
 |
error: Invalid XML
@ -188,7 +188,7 @@
 | GET http://localhost:8000/runner_errors/invalid-xml
 | ...
125 | xpath "//a" == 10
 | ^^^^^^^^^^^ the HTTP response is not a valid XML
 | ^^^^^^^^^^^ the HTTP response is not a valid XML
 |
error: Invalid XPath expression
@ -197,7 +197,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
131 | xpath "//" == 10
 | ^^^^ the XPath expression is not valid
 | ^^^^ the XPath expression is not valid
 |
error: Invalid variable type
@ -206,7 +206,7 @@
 | GET http://localhost:8000/runner_errors
 | ...
137 | verbose: {{verbose}}
 | ^^^^^^^ expecting boolean, actual value is <1>
 | ^^^^^^^ expecting boolean, actual value is <1>
 |
error: Undefined variable
@ -215,14 +215,14 @@
 | GET http://localhost:8000/runner_errors
 | ...
142 | param: {{value}}
 | ^^^^^ you must set the variable value
 | ^^^^^ you must set the variable value
 |
error: HTTP connection
--> tests_failed/runner_errors.hurl:145:5
 |
145 | GET http://localhost:8000/runner_errors/redirect/2
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ too many redirect
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ too many redirect
 |
error: Unauthorized file access
@ -230,7 +230,7 @@
 |
 | GET http://localhost:8000/runner_errors
152 | file,/root/file;
 | ^^^^^^^^^^ unauthorized access to file /root/file, check --file-root option
 | ^^^^^^^^^^ unauthorized access to file /root/file, check --file-root option
 |
error: Unrenderable variable
@ -238,7 +238,7 @@
 |
 | GET http://localhost:8000/runner_errors
160 | `{{list}}`
 | ^^^^ variable <list> with value [1,2,3] can not be rendered
 | ^^^^ variable <list> with value [1,2,3] can not be rendered
 |
error: Decompression error
@ -247,13 +247,13 @@
 | GET http://localhost:8000/runner_errors/unsupported-content-encoding
 | ...
166 | bytes count == 10
 | ^^^^^ compression unknown is not supported
 | ^^^^^ compression unknown is not supported
 |
error: Unsupported HTTP version
--> tests_failed/runner_errors.hurl:169:5
 |
169 | GET http://localhost:8000/runner_errors
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ HTTP/3 is not supported, check --version
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ HTTP/3 is not supported, check --version
 |

View File

@ -30,7 +30,7 @@ impl Error {
impl From<runner::Error> for Error {
fn from(error: runner::Error) -> Self {
Error::new(&error.fixme())
Error::new(&error.fixme(&[]))
}
}

View File

@ -159,10 +159,11 @@ impl hurl_core::error::Error for Error {
}
}
fn fixme(&self) -> String {
fn fixme(&self, content: &[&str]) -> String {
match &self.inner {
RunnerError::AssertBodyValueError { actual, .. } => {
format!("actual value is <{actual}>")
let message = &format!("actual value is <{actual}>");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::AssertFailure {
actual,
@ -178,75 +179,130 @@ impl hurl_core::error::Error for Error {
format!(" actual: {actual}\n expected: {expected}{additional}")
}
RunnerError::AssertHeaderValueError { actual } => {
format!("actual value is <{actual}>")
let message = &format!("actual value is <{actual}>");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::AssertStatus { actual, .. } => {
let message = &format!("actual value is <{actual}>");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::AssertVersion { actual, .. } => {
let message = &format!("actual value is <{actual}>");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::AssertStatus { actual, .. } => format!("actual value is <{actual}>"),
RunnerError::AssertVersion { actual, .. } => format!("actual value is <{actual}>"),
RunnerError::CouldNotUncompressResponse(algorithm) => {
format!("could not uncompress response with {algorithm}")
let message = &format!("could not uncompress response with {algorithm}");
// only add carets if source_info is set
// TODO: add additional attribute in the error to be more explicit?
if self.source_info.start.line == 0 {
message.to_string()
} else {
hurl_core::error::add_carets(message, self.source_info, content)
}
}
RunnerError::FileReadAccess { path } => {
format!("file {} can not be read", path.to_string_lossy())
let message = &format!("file {} can not be read", path.to_string_lossy());
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::FileWriteAccess { path, error } => {
format!("{} can not be written ({error})", path.to_string_lossy())
}
RunnerError::FilterDecode(encoding) => {
format!("value can not be decoded with <{encoding}> encoding")
let message = &format!("value can not be decoded with <{encoding}> encoding");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::FilterInvalidEncoding(encoding) => {
format!("<{encoding}> encoding is not supported")
let message = &format!("<{encoding}> encoding is not supported");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::FilterInvalidInput(message) => {
format!("invalid filter input: {message}")
let message = &format!("invalid filter input: {message}");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::FilterMissingInput => {
let message = "missing value to apply filter";
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::HttpConnection(message) => {
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::FilterMissingInput => "missing value to apply filter".to_string(),
RunnerError::HttpConnection(message) => message.to_string(),
RunnerError::InvalidCharset { charset } => {
format!("the charset '{charset}' is not valid")
let message = &format!("the charset '{charset}' is not valid");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::InvalidDecoding { charset } => {
format!("the body can not be decoded with charset '{charset}'")
let message = &format!("the body can not be decoded with charset '{charset}'");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::InvalidJson { value } => {
format!("actual value is <{value}>")
let message = &format!("actual value is <{value}>");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::InvalidRegex => {
let message = "regex expression is not valid";
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::InvalidUrl(url, reason) => {
let message = &format!("invalid URL <{url}> ({reason})");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::NoQueryResult => {
let message = "The query didn't return any result";
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::InvalidRegex => "regex expression is not valid".to_string(),
RunnerError::InvalidUrl(url, reason) => format!("invalid URL <{url}> ({reason})"),
RunnerError::NoQueryResult => "The query didn't return any result".to_string(),
RunnerError::QueryHeaderNotFound => {
"this header has not been found in the response".to_string()
let message = "this header has not been found in the response";
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::QueryInvalidJson => {
let message = "the HTTP response is not a valid JSON";
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::QueryInvalidJson => "the HTTP response is not a valid JSON".to_string(),
RunnerError::QueryInvalidJsonpathExpression { value } => {
format!("the JSONPath expression '{value}' is not valid")
let message = &format!("the JSONPath expression '{value}' is not valid");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::QueryInvalidXml => {
let message = "the HTTP response is not a valid XML";
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::QueryInvalidXpathEval => {
let message = "the XPath expression is not valid";
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::QueryInvalidXml => "the HTTP response is not a valid XML".to_string(),
RunnerError::QueryInvalidXpathEval => "the XPath expression is not valid".to_string(),
RunnerError::TemplateVariableInvalidType {
value, expecting, ..
} => {
format!("expecting {expecting}, actual value is <{value}>")
let message = &format!("expecting {expecting}, actual value is <{value}>");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::TemplateVariableNotDefined { name } => {
format!("you must set the variable {name}")
let message = &format!("you must set the variable {name}");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::TooManyRedirect => {
let message = "too many redirect";
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::TooManyRedirect => "too many redirect".to_string(),
RunnerError::UnauthorizedFileAccess { path } => {
format!(
let message = &format!(
"unauthorized access to file {}, check --file-root option",
path.to_string_lossy()
)
);
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::UnrenderableVariable { name, value } => {
format!("variable <{name}> with value {value} can not be rendered")
let message = &format!("variable <{name}> with value {value} can not be rendered");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::UnsupportedContentEncoding(algorithm) => {
format!("compression {algorithm} is not supported")
let message = &format!("compression {algorithm} is not supported");
hurl_core::error::add_carets(message, self.source_info, content)
}
RunnerError::UnsupportedHttpVersion(version) => {
format!("{version} is not supported, check --version")
let message = &format!("{version} is not supported, check --version");
hurl_core::error::add_carets(message, self.source_info, content)
}
}
}
@ -254,10 +310,6 @@ impl hurl_core::error::Error for Error {
fn show_source_line(&self) -> bool {
true
}
fn show_caret(&self) -> bool {
!matches!(&self.inner, RunnerError::AssertFailure { .. })
}
}
impl From<HttpError> for RunnerError {

View File

@ -285,7 +285,7 @@ pub fn run_entries(
stdout,
source_info,
) {
logger.warning(&error.fixme());
logger.warning(&error.fixme(&[]));
}
}
}

View File

@ -567,57 +567,14 @@ fn get_message<E: Error>(error: &E, lines: &[&str], colored: bool) -> String {
text.push_str(&line);
text.push('\n');
}
let mut prefix = if error.show_caret() {
//let mut prefix = String::new();
// the fixme message is offset with space and carets according to the error column
let error_line = error.source_info().start.line;
let error_column = error.source_info().start.column;
// Error source info start and end can be on different lines, we insure a minimum width.
let width = if error.source_info().end.column > error_column {
error.source_info().end.column - error_column
} else {
1
};
// We take tabs into account because we have normalize the display of the error line by replacing
// tabs with 4 spaces.
// TODO: add a unit test with tabs in source info.
let mut tab_shift = 0;
let line_raw = lines.get(error_line - 1).unwrap();
for (i, c) in line_raw.chars().enumerate() {
if i >= (error_column - 1) {
break;
};
if c == '\t' {
tab_shift += 1;
}
}
let mut value = " ".repeat(error_column + tab_shift * 3);
value.push_str("^".repeat(width).as_str());
value.push(' ');
value
} else {
String::new()
};
let fixme = error.fixme();
let fixme = error.fixme(lines);
let lines = split_lines(&fixme);
for (i, line) in lines.iter().enumerate() {
if i > 0 {
if !prefix.is_empty() {
prefix = " ".repeat(prefix.len());
}
text.push('\n');
}
if !line.is_empty() {
text.push_str(color_if_needed(&prefix, colored).as_str());
}
text.push_str(color_if_needed(line, colored).as_str());
}
text
}
@ -688,7 +645,7 @@ HTTP/1.0 200
colored::control::set_override(true);
assert_eq!(
get_message(&error, &split_lines(content), true),
" HTTP/1.0 200\n\u{1b}[1;31m ^^^ \u{1b}[0m\u{1b}[1;31mactual value is <404>\u{1b}[0m"
" HTTP/1.0 200\n\u{1b}[1;31m ^^^ actual value is <404>\u{1b}[0m"
);
assert_eq!(
@ -853,7 +810,7 @@ HTTP 200
"Assert body value".to_string()
}
fn fixme(&self) -> String {
fn fixme(&self, _lines: &[&str]) -> String {
r#" {
"name": "John",
- "age": 27
@ -866,10 +823,6 @@ HTTP 200
fn show_source_line(&self) -> bool {
false
}
fn show_caret(&self) -> bool {
false
}
}
let error = E;

View File

@ -20,7 +20,104 @@ use crate::ast::SourceInfo;
pub trait Error {
fn source_info(&self) -> SourceInfo;
fn description(&self) -> String;
fn fixme(&self) -> String;
fn fixme(&self, content: &[&str]) -> String;
fn show_source_line(&self) -> bool;
fn show_caret(&self) -> bool;
}
/// Show column position with carets
pub fn add_carets(message: &str, source_info: SourceInfo, content: &[&str]) -> String {
let error_line = source_info.start.line;
let error_column = source_info.start.column;
// Error source info start and end can be on different lines, we insure a minimum width.
let width = if source_info.end.column > error_column {
source_info.end.column - error_column
} else {
1
};
let line_raw = content.get(error_line - 1).unwrap();
let prefix = get_carets(line_raw, error_column, width);
let mut s = String::new();
for (i, line) in split_lines(message).iter().enumerate() {
if i == 0 {
s.push_str(format!("{prefix}{line}").as_str());
} else {
s.push('\n');
if !line.is_empty() {
s.push_str(" ".repeat(prefix.len()).as_str());
}
s.push_str(line);
};
}
s
}
/// Splits this `text` to a list of LF/CRLF separated lines.
fn split_lines(text: &str) -> Vec<&str> {
regex::Regex::new(r"\n|\r\n").unwrap().split(text).collect()
}
/// Generate carets for the given source_line/source_info
fn get_carets(line_raw: &str, error_column: usize, width: usize) -> String {
// We take tabs into account because we have normalize the display of the error line by replacing
// tabs with 4 spaces.
let mut tab_shift = 0;
for (i, c) in line_raw.chars().enumerate() {
if i >= (error_column - 1) {
break;
};
if c == '\t' {
tab_shift += 1;
}
}
let mut prefix = " ".repeat(error_column + tab_shift * 3);
prefix.push_str("^".repeat(width).as_str());
prefix.push(' ');
prefix
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ast::Pos;
#[test]
fn test_add_carets() {
// `Hello World`
// ^^^^^^^^^^^^^ actual value is <Hello World!>
assert_eq!(
add_carets(
"actual value is <Hello World!>",
SourceInfo::new(Pos::new(1, 1), Pos::new(1, 14)),
&["`Hello World`"]
),
" ^^^^^^^^^^^^^ actual value is <Hello World!>".to_string()
);
}
#[test]
fn test_get_carets() {
// `Hello World`
// ^^^^^^^^^^^^^ actual value is <Hello World!>
assert_eq!(
get_carets("`Hello World`", 1, 13),
" ^^^^^^^^^^^^^ ".to_string()
);
// Content-Length: 200
// ^^^ actual value is <12>
assert_eq!(
get_carets("Content-Length: 200", 17, 3),
" ^^^ ".to_string()
);
// With a tab instead of a space
// Content-Length: 200
// ^^^ actual value is <12>
assert_eq!(
get_carets("Content-Length:\t200", 17, 3),
" ^^^ ".to_string()
);
}
}

View File

@ -131,8 +131,8 @@ impl crate::error::Error for Error {
}
}
fn fixme(&self) -> String {
match &self.inner {
fn fixme(&self, content: &[&str]) -> String {
let message = match &self.inner {
ParseError::DuplicateSection => "the section is already defined".to_string(),
ParseError::EscapeChar => "the escaping sequence is not valid".to_string(),
ParseError::Expecting { value } => format!("expecting '{value}'"),
@ -233,16 +233,14 @@ impl crate::error::Error for Error {
}
ParseError::XPathExpr => "expecting a XPath expression".to_string(),
ParseError::Xml => "invalid XML".to_string(),
}
};
crate::error::add_carets(&message, self.source_info(), content)
}
fn show_source_line(&self) -> bool {
true
}
fn show_caret(&self) -> bool {
true
}
}
fn did_you_mean(valid_values: &[&str], actual: &str, default: &str) -> String {

View File

@ -17,12 +17,11 @@
*/
use std::path::PathBuf;
use crate::linter;
use colored::*;
use hurl_core::error::Error;
use hurl_core::parser;
use crate::linter;
pub fn make_logger_verbose(verbose: bool) -> impl Fn(&str) {
move |message| log_verbose(verbose, message)
}
@ -130,8 +129,9 @@ fn log_error(
// TODO: to clean/Refacto
// specific case for assert errors
let lines = lines.iter().map(|s| s.as_str()).collect::<Vec<&str>>();
if error.source_info().start.column == 0 {
let fix_me = &error.fixme();
let fix_me = &error.fixme(&lines);
let fixme_lines: Vec<&str> = regex::Regex::new(r"\n|\r\n")
.unwrap()
.split(fix_me)
@ -162,7 +162,7 @@ fn log_error(
" ".repeat(line_number_size).as_str(),
" ".repeat(error.source_info().start.column - 1 + tab_shift * 3),
"^".repeat(if width > 1 { width } else { 1 }),
fixme = error.fixme().as_str(),
fixme = error.fixme(&lines).as_str(),
);
}

View File

@ -37,7 +37,7 @@ impl Error for linter::Error {
}
}
fn fixme(&self) -> String {
fn fixme(&self, _lines: &[&str]) -> String {
match self.inner {
LinterError::UnnecessarySpace => "Remove space".to_string(),
LinterError::UnnecessaryJsonEncoding => "Use Simple String".to_string(),
@ -48,8 +48,4 @@ impl Error for linter::Error {
fn show_source_line(&self) -> bool {
true
}
fn show_caret(&self) -> bool {
true
}
}