Skip to main content

miniextendr_lint/rules/
r_reserved_params.rs

1//! R reserved-word parameter name check.
2//!
3//! - MXL110: A `#[miniextendr]` function or method has a parameter whose name
4//!   is an R reserved word. The proc macro forwards parameter names verbatim
5//!   into the generated R wrapper, so the wrapper will be syntactically invalid.
6
7use crate::crate_index::CrateIndex;
8use crate::diagnostic::Diagnostic;
9use crate::lint_code::LintCode;
10
11/// R reserved words from `?Reserved`.
12///
13/// Strictly reserved only — does not include quasi-reserved (`T`, `F`, `c`, `t`, `q`)
14/// to avoid false positives.
15const R_RESERVED: &[&str] = &[
16    "if",
17    "else",
18    "repeat",
19    "while",
20    "function",
21    "for",
22    "in",
23    "next",
24    "break",
25    "TRUE",
26    "FALSE",
27    "NULL",
28    "Inf",
29    "NaN",
30    "NA",
31    "NA_integer_",
32    "NA_real_",
33    "NA_complex_",
34    "NA_character_",
35];
36
37pub fn check(index: &CrateIndex, diagnostics: &mut Vec<Diagnostic>) {
38    for (path, data) in &index.file_data {
39        for (fn_name, params) in &data.fn_param_names {
40            for (param, line) in params {
41                if R_RESERVED.contains(&param.as_str()) {
42                    diagnostics.push(
43                        Diagnostic::new(
44                            LintCode::MXL110,
45                            path,
46                            *line,
47                            format!(
48                                "parameter `{param}` of `{fn_name}` is an R reserved word; \
49                                 the generated R wrapper will be syntactically invalid",
50                            ),
51                        )
52                        .with_help("rename the parameter (e.g., `n_chunks` instead of `repeat`)"),
53                    );
54                }
55            }
56        }
57    }
58}