mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-12-23 19:12:06 +03:00
Add Regex predicate value
This commit is contained in:
parent
45b15e8b7f
commit
b83bbf67ed
@ -2,7 +2,9 @@
|
||||
</span><span class="response"><span class="line"><span class="version">HTTP/1.0</span> <span class="number">200</span></span>
|
||||
<span class="line section-header">[Asserts]</span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.date1"</span> <span class="predicate-type">matches</span> <span class="string">"\\d{4}-\\d{2}-\\d{2}"</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.date2"</span> <span class="predicate-type">matches</span> <span class="string">"\\d{4}-\\d{2}-\\d{2}"</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.date1"</span> <span class="predicate-type">matches</span> <span class="string">"^\\d{4}-\\d{2}-\\d{2}$"</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.date2"</span> <span class="not">not</span> <span class="predicate-type">matches</span> <span class="string">"^\\d{4}-\\d{2}-\\d{2}$"</span></span>
|
||||
</span></span></code></pre>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.date1"</span> <span class="predicate-type">matches</span> <span class="regex">/\d{4}-\d{2}-\d{2}/</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.date2"</span> <span class="predicate-type">matches</span> <span class="regex">/\d{4}-\d{2}-\d{2}/</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.date1"</span> <span class="predicate-type">matches</span> <span class="regex">/^\d{4}-\d{2}-\d{2}$/</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.date2"</span> <span class="not">not</span> <span class="predicate-type">matches</span> <span class="regex">/^\d{4}-\d{2}-\d{2}$/</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.path1"</span> <span class="predicate-type">matches</span> <span class="regex">/aa\/bb/</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.path2"</span> <span class="predicate-type">matches</span> <span class="regex">/aa\\bb/</span></span></span></span></code></pre>
|
@ -2,6 +2,9 @@ GET http://localhost:8000/assert-match
|
||||
HTTP/1.0 200
|
||||
[Asserts]
|
||||
jsonpath "$.date1" matches "\\d{4}-\\d{2}-\\d{2}"
|
||||
jsonpath "$.date2" matches "\\d{4}-\\d{2}-\\d{2}"
|
||||
jsonpath "$.date1" matches "^\\d{4}-\\d{2}-\\d{2}$"
|
||||
jsonpath "$.date2" not matches "^\\d{4}-\\d{2}-\\d{2}$"
|
||||
jsonpath "$.date1" matches /\d{4}-\d{2}-\d{2}/
|
||||
jsonpath "$.date2" matches /\d{4}-\d{2}-\d{2}/
|
||||
jsonpath "$.date1" matches /^\d{4}-\d{2}-\d{2}$/
|
||||
jsonpath "$.date2" not matches /^\d{4}-\d{2}-\d{2}$/
|
||||
jsonpath "$.path1" matches /aa\/bb/
|
||||
jsonpath "$.path2" matches /aa\\bb/
|
@ -1 +1 @@
|
||||
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/assert-match"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.date1"},"predicate":{"type":"match","value":"\\d{4}-\\d{2}-\\d{2}"}},{"query":{"type":"jsonpath","expr":"$.date2"},"predicate":{"type":"match","value":"\\d{4}-\\d{2}-\\d{2}"}},{"query":{"type":"jsonpath","expr":"$.date1"},"predicate":{"type":"match","value":"^\\d{4}-\\d{2}-\\d{2}$"}},{"query":{"type":"jsonpath","expr":"$.date2"},"predicate":{"not":true,"type":"match","value":"^\\d{4}-\\d{2}-\\d{2}$"}}]}}]}
|
||||
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/assert-match"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.date1"},"predicate":{"type":"match","value":"\\d{4}-\\d{2}-\\d{2}"}},{"query":{"type":"jsonpath","expr":"$.date1"},"predicate":{"type":"match","value":"\\d{4}-\\d{2}-\\d{2}","encoding":"regex"}},{"query":{"type":"jsonpath","expr":"$.date2"},"predicate":{"type":"match","value":"\\d{4}-\\d{2}-\\d{2}","encoding":"regex"}},{"query":{"type":"jsonpath","expr":"$.date1"},"predicate":{"type":"match","value":"^\\d{4}-\\d{2}-\\d{2}$","encoding":"regex"}},{"query":{"type":"jsonpath","expr":"$.date2"},"predicate":{"not":true,"type":"match","value":"^\\d{4}-\\d{2}-\\d{2}$","encoding":"regex"}},{"query":{"type":"jsonpath","expr":"$.path1"},"predicate":{"type":"match","value":"aa/bb","encoding":"regex"}},{"query":{"type":"jsonpath","expr":"$.path2"},"predicate":{"type":"match","value":"aa\\\\bb","encoding":"regex"}}]}}]}
|
@ -1,4 +1,6 @@
|
||||
{
|
||||
"date1": "2014-01-01",
|
||||
"date2": "x2014-01-01"
|
||||
"date2": "x2014-01-01",
|
||||
"path1": "aa/bb",
|
||||
"path2": "aa\\bb"
|
||||
}
|
@ -5,7 +5,9 @@ from flask import Response
|
||||
def assert_match():
|
||||
return Response('''{
|
||||
"date1": "2014-01-01",
|
||||
"date2": "x2014-01-01"
|
||||
"date2": "x2014-01-01",
|
||||
"path1": "aa/bb",
|
||||
"path2": "aa\\\\bb"
|
||||
}''', mimetype='application/json')
|
||||
|
||||
|
||||
|
7
integration/tests_error_parser/invalid_regex.err
Normal file
7
integration/tests_error_parser/invalid_regex.err
Normal file
@ -0,0 +1,7 @@
|
||||
error: Parsing regex
|
||||
--> tests_error_parser/invalid_regex.hurl:4:23
|
||||
|
|
||||
4 | jsonpath "$.data" == /aa{a}/
|
||||
| ^ Invalid Regex expression: repetition quantifier expects a valid decimal
|
||||
|
|
||||
|
1
integration/tests_error_parser/invalid_regex.exit
Normal file
1
integration/tests_error_parser/invalid_regex.exit
Normal file
@ -0,0 +1 @@
|
||||
2
|
4
integration/tests_error_parser/invalid_regex.hurl
Normal file
4
integration/tests_error_parser/invalid_regex.hurl
Normal file
@ -0,0 +1,4 @@
|
||||
GET http://localhost:8000/unused
|
||||
HTTP/1.1 200
|
||||
[Asserts]
|
||||
jsonpath "$.data" == /aa{a}/
|
@ -51,6 +51,7 @@ impl Value {
|
||||
serde_json::Value::String(encoded)
|
||||
}
|
||||
Value::Null => serde_json::Value::Null,
|
||||
Value::Regex(value) => serde_json::Value::String(value.to_string()),
|
||||
Value::Unit => todo!("how to serialize that in json?"),
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
*/
|
||||
use std::collections::HashMap;
|
||||
|
||||
use regex::Regex;
|
||||
use regex;
|
||||
|
||||
use hurl_core::ast::*;
|
||||
|
||||
@ -109,6 +109,7 @@ impl Value {
|
||||
Value::Bytes(value) => format!("byte array <{}>", hex::encode(value)),
|
||||
Value::Null => "null".to_string(),
|
||||
Value::Unit => "unit".to_string(),
|
||||
Value::Regex(value) => format!("regex <{}>", value.as_str()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,6 +146,7 @@ impl Value {
|
||||
Value::Object(values) => format!("list of size {}", values.len()),
|
||||
Value::String(value) => format!("string <{}>", value),
|
||||
Value::Unit => "something".to_string(),
|
||||
Value::Regex(value) => format!("regex <{}>", value),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -409,13 +411,10 @@ fn eval_something(
|
||||
PredicateFuncValue::Match {
|
||||
value: expected, ..
|
||||
} => {
|
||||
let template = if let PredicateValue::String(template) = expected {
|
||||
template
|
||||
} else {
|
||||
panic!("expect a string predicate value")
|
||||
};
|
||||
let regex = match expected {
|
||||
PredicateValue::String(template) => {
|
||||
let expected = eval_template(&template, variables)?;
|
||||
let regex = match Regex::new(expected.as_str()) {
|
||||
match regex::Regex::new(expected.as_str()) {
|
||||
Ok(re) => re,
|
||||
Err(_) => {
|
||||
return Err(Error {
|
||||
@ -424,18 +423,22 @@ fn eval_something(
|
||||
assert: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
PredicateValue::Regex(regex) => regex.inner,
|
||||
_ => panic!("expect a string predicate value"), // should have failed in parsing
|
||||
};
|
||||
match value.clone() {
|
||||
Value::String(actual) => Ok(AssertResult {
|
||||
success: regex.is_match(actual.as_str()),
|
||||
actual: value.display(),
|
||||
expected: format!("matches regex <{}>", expected),
|
||||
expected: format!("matches regex <{}>", regex),
|
||||
type_mismatch: false,
|
||||
}),
|
||||
_ => Ok(AssertResult {
|
||||
success: false,
|
||||
actual: value.display(),
|
||||
expected: format!("matches regex <{}>", expected),
|
||||
expected: format!("matches regex <{}>", regex),
|
||||
type_mismatch: true,
|
||||
}),
|
||||
}
|
||||
@ -1556,4 +1559,32 @@ mod tests {
|
||||
let variables = HashMap::new();
|
||||
assert!(eval_predicate(predicate, &variables, None).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_predicate_match() {
|
||||
let variables = HashMap::new();
|
||||
let whitespace = Whitespace {
|
||||
value: String::from(" "),
|
||||
source_info: SourceInfo::init(0, 0, 0, 0),
|
||||
};
|
||||
// // a float can be equals to an int (but the reverse)
|
||||
let assert_result = eval_something(
|
||||
PredicateFunc {
|
||||
value: PredicateFuncValue::Match {
|
||||
space0: whitespace,
|
||||
value: PredicateValue::Regex(Regex {
|
||||
inner: regex::Regex::new(r#"a{3}"#).unwrap(),
|
||||
}),
|
||||
},
|
||||
source_info: SourceInfo::init(0, 0, 0, 0),
|
||||
},
|
||||
&variables,
|
||||
Value::String("aa".to_string()),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(!assert_result.success);
|
||||
assert!(!assert_result.type_mismatch);
|
||||
assert_eq!(assert_result.actual.as_str(), "string <aa>");
|
||||
assert_eq!(assert_result.expected.as_str(), "matches regex <a{3}>");
|
||||
}
|
||||
}
|
||||
|
@ -47,5 +47,6 @@ pub fn eval_predicate_value(
|
||||
let value = eval_expr(expr, variables)?;
|
||||
Ok(value)
|
||||
}
|
||||
PredicateValue::Regex(regex) => Ok(Value::Regex(regex.inner)),
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ pub enum Value {
|
||||
Object(Vec<(String, Value)>),
|
||||
String(String),
|
||||
Unit,
|
||||
Regex(regex::Regex),
|
||||
}
|
||||
|
||||
// You must implement it yourself because of the Float
|
||||
@ -53,6 +54,7 @@ impl PartialEq for Value {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Value {}
|
||||
|
||||
impl fmt::Display for Value {
|
||||
@ -71,6 +73,10 @@ impl fmt::Display for Value {
|
||||
Value::Bytes(v) => format!("hex, {};", hex::encode(v)),
|
||||
Value::Null => "null".to_string(),
|
||||
Value::Unit => "Unit".to_string(),
|
||||
Value::Regex(x) => {
|
||||
let s = str::replace(x.as_str(), "/", "\\/");
|
||||
format!("/{}/", s)
|
||||
}
|
||||
};
|
||||
write!(f, "{}", value)
|
||||
}
|
||||
@ -97,6 +103,7 @@ impl Value {
|
||||
Value::Bytes(_) => "bytes".to_string(),
|
||||
Value::Null => "null".to_string(),
|
||||
Value::Unit => "unit".to_string(),
|
||||
Value::Regex(_) => "regex".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,6 +422,7 @@ pub enum PredicateValue {
|
||||
Hex(Hex),
|
||||
Base64(Base64),
|
||||
Expression(Expr),
|
||||
Regex(Regex),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@ -600,6 +601,19 @@ pub struct Hex {
|
||||
pub space1: Whitespace,
|
||||
}
|
||||
|
||||
// Literal Regex
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Regex {
|
||||
pub inner: regex::Regex,
|
||||
}
|
||||
|
||||
impl PartialEq for Regex {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner.to_string() == other.inner.to_string()
|
||||
}
|
||||
}
|
||||
impl Eq for Regex {}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Pos {
|
||||
pub line: usize,
|
||||
|
@ -137,6 +137,12 @@ impl fmt::Display for Hex {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Regex {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl PredicateFuncValue {
|
||||
pub fn name(&self) -> String {
|
||||
match self {
|
||||
|
@ -93,7 +93,7 @@ impl Error for parser::Error {
|
||||
ParseError::Json { .. } => "json error".to_string(),
|
||||
ParseError::Predicate { .. } => "expecting a predicate".to_string(),
|
||||
ParseError::PredicateValue { .. } => "invalid predicate value".to_string(),
|
||||
ParseError::RegexExpr { .. } => "Invalid Regex expression".to_string(),
|
||||
ParseError::RegexExpr { message } => format!("Invalid Regex expression: {}", message),
|
||||
ParseError::DuplicateSection { .. } => "The section is already defined".to_string(),
|
||||
ParseError::RequestSection { .. } => {
|
||||
"This is not a valid section for a request".to_string()
|
||||
|
@ -636,6 +636,7 @@ impl Htmlable for PredicateValue {
|
||||
PredicateValue::Base64(value) => value.to_html(),
|
||||
PredicateValue::Expression(value) => value.to_html(),
|
||||
PredicateValue::Null {} => "<span class=\"null\">null</span>".to_string(),
|
||||
PredicateValue::Regex(value) => value.to_html(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -797,6 +798,12 @@ impl Htmlable for Hex {
|
||||
}
|
||||
}
|
||||
|
||||
impl Htmlable for Regex {
|
||||
fn to_html(&self) -> String {
|
||||
let s = str::replace(self.inner.as_str(), "/", "\\/");
|
||||
format!("<span class=\"regex\">/{}/</span>", s)
|
||||
}
|
||||
}
|
||||
impl Htmlable for EncodedString {
|
||||
fn to_html(&self) -> String {
|
||||
format!("<span class=\"string\">{}</span>", self.encoded)
|
||||
|
@ -43,7 +43,7 @@ pub enum ParseError {
|
||||
Xml {},
|
||||
Predicate,
|
||||
PredicateValue,
|
||||
RegexExpr,
|
||||
RegexExpr { message: String },
|
||||
|
||||
Unexpected { character: String },
|
||||
Eof {},
|
||||
|
@ -311,7 +311,7 @@ fn match_predicate(reader: &mut Reader) -> ParseResult<'static, PredicateFuncVal
|
||||
let space0 = one_or_more_spaces(reader)?;
|
||||
let save = reader.state.clone();
|
||||
let value = predicate_value(reader)?;
|
||||
if !value.is_string() {
|
||||
if !matches!(value, PredicateValue::String(_)) && !matches!(value, PredicateValue::Regex(_)) {
|
||||
return Err(Error {
|
||||
pos: save.pos,
|
||||
recoverable: false,
|
||||
|
@ -65,6 +65,10 @@ pub fn predicate_value(reader: &mut Reader) -> ParseResult<'static, PredicateVal
|
||||
Ok(value) => Ok(PredicateValue::Raw(value)),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
|p1| match regex(p1) {
|
||||
Ok(value) => Ok(PredicateValue::Regex(value)),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
],
|
||||
reader,
|
||||
)
|
||||
|
@ -332,6 +332,71 @@ pub fn hex(reader: &mut Reader) -> ParseResult<'static, Hex> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn regex(reader: &mut Reader) -> ParseResult<'static, Regex> {
|
||||
try_literal("/", reader)?;
|
||||
let start = reader.state.pos.clone();
|
||||
let mut s = String::from("");
|
||||
|
||||
// Hurl escaping /
|
||||
// in order to avoid terminating the regex
|
||||
// eg. \a\b/
|
||||
//
|
||||
// Other escaped sequences such as \* are part of the regex expression
|
||||
// They are not part of the syntax of Hurl itself.
|
||||
loop {
|
||||
match reader.read() {
|
||||
None => {
|
||||
return Err(Error {
|
||||
pos: reader.state.pos.clone(),
|
||||
recoverable: false,
|
||||
inner: ParseError::Eof {},
|
||||
})
|
||||
}
|
||||
Some('/') => break,
|
||||
Some('\\') => {
|
||||
if let Some('/') = reader.peek() {
|
||||
reader.read();
|
||||
s.push('/');
|
||||
} else {
|
||||
s.push('\\');
|
||||
}
|
||||
}
|
||||
Some(c) => s.push(c),
|
||||
}
|
||||
}
|
||||
match regex::Regex::new(s.as_str()) {
|
||||
Ok(inner) => Ok(Regex { inner }),
|
||||
Err(e) => {
|
||||
let message = match e {
|
||||
regex::Error::Syntax(s) => {
|
||||
// The regex syntax error from the crate returns a multiline String
|
||||
// For example
|
||||
// regex parse error:
|
||||
// x{a}
|
||||
// ^
|
||||
// error: repetition quantifier expects a valid decimal
|
||||
//
|
||||
// To fit nicely in Hurl Error reporting, you need an error message string that does not spread on multiple lines
|
||||
// You will assume that the error most relevant description is on the last line
|
||||
let lines = s.split('\n').clone().collect::<Vec<&str>>();
|
||||
let last_line = lines.last().expect("at least one line");
|
||||
last_line
|
||||
.strip_prefix("error: ")
|
||||
.unwrap_or(last_line)
|
||||
.to_string()
|
||||
}
|
||||
regex::Error::CompiledTooBig(_) => "Size limit exceeded".to_string(),
|
||||
_ => "unknown".to_string(),
|
||||
};
|
||||
Err(Error {
|
||||
pos: start,
|
||||
recoverable: false,
|
||||
inner: ParseError::RegexExpr { message },
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn null(reader: &mut Reader) -> ParseResult<'static, ()> {
|
||||
try_literal("null", reader)
|
||||
}
|
||||
@ -1332,6 +1397,66 @@ mod tests {
|
||||
assert_eq!(error.inner, ParseError::OddNumberOfHexDigits {});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_regex() {
|
||||
let mut reader = Reader::init(r#"/a{3}/"#);
|
||||
assert_eq!(
|
||||
regex(&mut reader).unwrap(),
|
||||
Regex {
|
||||
inner: regex::Regex::new(r#"a{3}"#).unwrap()
|
||||
}
|
||||
);
|
||||
|
||||
let mut reader = Reader::init(r#"/a\/b/"#);
|
||||
assert_eq!(
|
||||
regex(&mut reader).unwrap(),
|
||||
Regex {
|
||||
inner: regex::Regex::new(r#"a/b"#).unwrap()
|
||||
}
|
||||
);
|
||||
|
||||
let mut reader = Reader::init(r#"/a\.b/"#);
|
||||
assert_eq!(
|
||||
regex(&mut reader).unwrap(),
|
||||
Regex {
|
||||
inner: regex::Regex::new(r#"a\.b"#).unwrap()
|
||||
}
|
||||
);
|
||||
|
||||
let mut reader = Reader::init(r#"/\d{4}-\d{2}-\d{2}/"#);
|
||||
assert_eq!(
|
||||
regex(&mut reader).unwrap(),
|
||||
Regex {
|
||||
inner: regex::Regex::new(r#"\d{4}-\d{2}-\d{2}"#).unwrap()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_regex_error() {
|
||||
let mut reader = Reader::init("xxx");
|
||||
let error = regex(&mut reader).err().unwrap();
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
||||
assert!(error.recoverable);
|
||||
|
||||
let mut reader = Reader::init("/xxx");
|
||||
let error = regex(&mut reader).err().unwrap();
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 5 });
|
||||
assert!(!error.recoverable);
|
||||
assert_eq!(error.inner, ParseError::Eof {});
|
||||
|
||||
let mut reader = Reader::init("/x{a}/");
|
||||
let error = regex(&mut reader).err().unwrap();
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 2 });
|
||||
assert!(!error.recoverable);
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::RegexExpr {
|
||||
message: "repetition quantifier expects a valid decimal".to_string()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file() {
|
||||
let mut reader = Reader::init("file,data.xml;");
|
||||
|
@ -465,6 +465,9 @@ fn json_predicate_value(predicate_value: PredicateValue) -> (JValue, Option<Stri
|
||||
Some("base64".to_string()),
|
||||
),
|
||||
PredicateValue::Expression(value) => (JValue::String(value.to_string()), None),
|
||||
PredicateValue::Regex(value) => {
|
||||
(JValue::String(value.to_string()), Some("regex".to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -653,6 +653,7 @@ impl Tokenizable for PredicateValue {
|
||||
PredicateValue::Hex(value) => vec![Token::String(value.to_string())],
|
||||
PredicateValue::Base64(value) => value.tokenize(),
|
||||
PredicateValue::Expression(value) => value.tokenize(),
|
||||
PredicateValue::Regex(value) => value.tokenize(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -735,6 +736,13 @@ impl Tokenizable for Expr {
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokenizable for Regex {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
let s = str::replace(self.inner.as_str(), "/", "\\/");
|
||||
vec![Token::String(format!("/{}/", s))]
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokenizable for LineTerminator {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
let mut tokens: Vec<Token> = vec![];
|
||||
|
@ -508,6 +508,7 @@ impl Lintable<PredicateValue> for PredicateValue {
|
||||
PredicateValue::Hex(value) => PredicateValue::Hex(value.lint()),
|
||||
PredicateValue::Base64(value) => PredicateValue::Base64(value.lint()),
|
||||
PredicateValue::Expression(value) => PredicateValue::Expression(value.clone()),
|
||||
PredicateValue::Regex(value) => PredicateValue::Regex(value.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user