-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
regexp.rs
72 lines (63 loc) · 2.99 KB
/
regexp.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use swc_common::util::take::Take;
use swc_ecma_ast::{CallExpr, Expr, Lit, Regex};
use swc_ecma_utils::{quote_ident, ExprFactory};
use swc_ecma_visit::{as_folder, standard_only_visit_mut, Fold, VisitMut, VisitMutWith};
pub fn regexp(config: Config) -> impl Fold + VisitMut {
as_folder(RegExp { config })
}
#[derive(Default, Clone, Copy)]
pub struct Config {
/// [s/dotAll flag for regular expressions](https://tc39.github.io/proposal-regexp-dotall-flag/)
pub dot_all_regex: bool,
/// [RegExp.prototype.hasIndices](https://262.ecma-international.org/13.0/#sec-get-regexp.prototype.hasIndices)
pub has_indices: bool,
/// [RegExp Lookbehind Assertions](https://tc39.es/proposal-regexp-lookbehind/)
pub lookbehind_assertion: bool,
/// [Named capture groups in regular expressions](https://tc39.es/proposal-regexp-named-groups/)
pub named_capturing_groups_regex: bool,
/// [RegExp.prototype.sticky](https://tc39.es/ecma262/multipage/text-processing.html#sec-get-regexp.prototype.sticky)
pub sticky_regex: bool,
/// [Unicode property escapes in regular expressions](https://tc39.es/proposal-regexp-unicode-property-escapes/)
pub unicode_property_regex: bool,
/// [RegExp.prototype.unicode](https://tc39.es/ecma262/multipage/text-processing.html#sec-get-regexp.prototype.unicode)
pub unicode_regex: bool,
// [RegExp.prototype.unicodeSets](https://github.com/tc39/proposal-regexp-v-flag)
pub unicode_sets_regex: bool,
}
struct RegExp {
config: Config,
}
impl VisitMut for RegExp {
standard_only_visit_mut!();
fn visit_mut_expr(&mut self, expr: &mut Expr) {
expr.visit_mut_children_with(self);
if let Expr::Lit(Lit::Regex(regex)) = expr {
if (self.config.dot_all_regex && regex.flags.contains('s'))
|| (self.config.sticky_regex && regex.flags.contains('y'))
|| (self.config.unicode_regex && regex.flags.contains('u'))
|| (self.config.unicode_sets_regex && regex.flags.contains('v'))
|| (self.config.has_indices && regex.flags.contains('d'))
|| (self.config.named_capturing_groups_regex && regex.exp.contains("(?<"))
|| (self.config.lookbehind_assertion && regex.exp.contains("(?<=")
|| regex.exp.contains("(?<!"))
|| (self.config.unicode_property_regex
&& (regex.exp.contains("\\p{") || regex.exp.contains("\\P{")))
{
let Regex { exp, flags, span } = regex.take();
let exp: Expr = exp.into();
let mut args = vec![exp.into()];
if !flags.is_empty() {
let flags: Expr = flags.into();
args.push(flags.into());
}
*expr = CallExpr {
span,
callee: quote_ident!("RegExp").as_callee(),
args,
..Default::default()
}
.into()
}
}
}
}