swc_ecma_lints/rules/
no_dupe_args.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
use swc_atoms::JsWord;
use swc_common::{collections::AHashMap, errors::HANDLER, Span};
use swc_ecma_ast::*;
use swc_ecma_utils::find_pat_ids;
use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};

use crate::rule::{visitor_rule, Rule};

pub fn no_dupe_args() -> Box<dyn Rule> {
    visitor_rule(NoDupeArgs::default())
}

#[derive(Debug, Default)]
struct NoDupeArgs {}

impl NoDupeArgs {
    fn check(&self, param_list: Vec<(JsWord, Span)>) {
        let mut variables_map = AHashMap::<JsWord, Span>::default();

        param_list.into_iter().for_each(|(js_word, span)| {
            if let Some(old_span) = variables_map.insert(js_word.clone(), span) {
                HANDLER.with(|handler| {
                    handler
                        .struct_span_err(
                            span,
                            &format!(
                                "the name `{}` is bound more than once in this parameter list",
                                js_word
                            ),
                        )
                        .span_label(old_span, "previous definition here".to_string())
                        .span_label(span, &"used as parameter more than once".to_string())
                        .emit();
                });
            }
        });
    }
}

impl Visit for NoDupeArgs {
    noop_visit_type!();

    fn visit_function(&mut self, f: &Function) {
        let variables: Vec<(JsWord, Span)> = find_pat_ids(&f.params);

        self.check(variables);

        f.visit_children_with(self);
    }

    fn visit_arrow_expr(&mut self, arrow_fn: &ArrowExpr) {
        let variables: Vec<(JsWord, Span)> = find_pat_ids(&arrow_fn.params);

        self.check(variables);

        arrow_fn.visit_children_with(self);
    }

    fn visit_constructor(&mut self, n: &Constructor) {
        let variables: Vec<(JsWord, Span)> = find_pat_ids(&n.params);

        self.check(variables);

        n.visit_children_with(self);
    }
}