1//! MXL111: `s4_*` method name on `#[miniextendr(s4)]` impl.
2//!
3//! S4 codegen auto-prepends `s4_` to every instance method name when generating
4//! the R generic. A Rust method named `s4_foo` on an `#[miniextendr(s4)]` impl
5//! produces an R generic `s4_s4_foo`, making it unreachable via the expected
6//! `s4_foo(obj, ...)` call.
78use crate::crate_index::{CrateIndex, MethodReceiverKind};
9use crate::diagnostic::Diagnostic;
10use crate::lint_code::LintCode;
1112pub fn check(index: &CrateIndex, diagnostics: &mut Vec<Diagnostic>) {
13for (path, data) in &index.file_data {
14for (impl_type, methods) in &data.impl_methods {
15for entry in methods {
16if entry.class_system != "s4" {
17continue;
18 }
19// Only instance methods are auto-prefixed. A receiver-less
20 // method is the class constructor, named after the type, or a
21 // static method, `Class_method()`.
22if entry.receiver_kind == MethodReceiverKind::None {
23continue;
24 }
25if let Some(rest) = entry.method_name.strip_prefix("s4_") {
26 diagnostics.push(
27 Diagnostic::new(
28 LintCode::MXL111,
29 path,
30 entry.line,
31::alloc::__export::must_use({
::alloc::fmt::format(format_args!("method `{2}::{0}` will produce R generic `s4_{1}` (s4 codegen auto-prepends `s4_`); rename to `{3}` to avoid the double prefix",
entry.method_name, entry.method_name, impl_type, rest))
})format!(
32"method `{impl_type}::{}` will produce R generic \
33 `s4_{}` (s4 codegen auto-prepends `s4_`); \
34 rename to `{rest}` to avoid the double prefix",
35 entry.method_name, entry.method_name,
36 ),
37 )
38 .with_help(
39"the macro prepends `s4_` to every S4 method name; \
40 keep the Rust method name unprefixed",
41 ),
42 );
43 }
44 }
45 }
46 }
47}