use memchr::memmem;
use crate::diagnostic::{LintDiagnostic, Severity};
use super::{ScriptLintResult, ScriptRule, ScriptRuleMeta};
static META: ScriptRuleMeta = ScriptRuleMeta {
name: "script/prefer-use-attrs",
description: "Recommend using useAttrs() over context.attrs",
default_severity: Severity::Warning,
};
pub struct PreferUseAttrs;
impl ScriptRule for PreferUseAttrs {
fn meta(&self) -> &'static ScriptRuleMeta {
&META
}
fn check(&self, source: &str, offset: usize, result: &mut ScriptLintResult) {
let bytes = source.as_bytes();
let finder = memmem::Finder::new(b"{ attrs }");
let mut search_start = 0;
while let Some(pos) = finder.find(&bytes[search_start..]) {
let abs_pos = search_start + pos;
search_start = abs_pos + 9;
let before = &source[..abs_pos];
if before.contains("setup(") {
result.add_diagnostic(
LintDiagnostic::warn(
META.name,
"Prefer useAttrs() over destructuring attrs from setup context",
(offset + abs_pos) as u32,
(offset + abs_pos + 9) as u32,
)
.with_help("Use `const attrs = useAttrs()` instead"),
);
}
}
let finder2 = memmem::Finder::new(b"context.attrs");
search_start = 0;
while let Some(pos) = finder2.find(&bytes[search_start..]) {
let abs_pos = search_start + pos;
search_start = abs_pos + 13;
result.add_diagnostic(
LintDiagnostic::warn(
META.name,
"Prefer useAttrs() over context.attrs",
(offset + abs_pos) as u32,
(offset + abs_pos + 13) as u32,
)
.with_help("Use `const attrs = useAttrs()` instead"),
);
}
}
}
#[cfg(test)]
mod tests {
use super::PreferUseAttrs;
use crate::rules::script::ScriptLinter;
fn create_linter() -> ScriptLinter {
let mut linter = ScriptLinter::new();
linter.add_rule(Box::new(PreferUseAttrs));
linter
}
#[test]
fn test_valid_use_attrs() {
let linter = create_linter();
let result = linter.lint("const attrs = useAttrs()", 0);
assert_eq!(result.warning_count, 0);
}
#[test]
fn test_invalid_context_attrs() {
let linter = create_linter();
let result = linter.lint("console.log(context.attrs)", 0);
assert_eq!(result.warning_count, 1);
}
#[test]
fn test_invalid_destructure_attrs() {
let linter = create_linter();
let result = linter.lint("setup(props, { attrs }) {", 0);
assert_eq!(result.warning_count, 1);
}
}