use super::{Context, LintRule};
use crate::handler::{Handler, Traverse};
use crate::tags::{self, Tags};
use crate::Program;
use deno_ast::view::{JSXAttrName, JSXAttrOrSpread, JSXOpeningElement};
use deno_ast::SourceRanged;
#[derive(Debug)]
pub struct JSXNoChildrenProp;
const CODE: &str = "jsx-no-children-prop";
impl LintRule for JSXNoChildrenProp {
fn tags(&self) -> Tags {
&[tags::RECOMMENDED, tags::REACT, tags::JSX, tags::FRESH]
}
fn code(&self) -> &'static str {
CODE
}
fn lint_program_with_ast_view(
&self,
context: &mut Context,
program: Program,
) {
JSXNoChildrenPropHandler.traverse(program, context);
}
}
const MESSAGE: &str = "Avoid passing children as a prop";
struct JSXNoChildrenPropHandler;
impl Handler for JSXNoChildrenPropHandler {
fn jsx_opening_element(
&mut self,
node: &JSXOpeningElement,
ctx: &mut Context,
) {
for attr in node.attrs {
if let JSXAttrOrSpread::JSXAttr(attr) = attr {
if let JSXAttrName::Ident(id) = attr.name {
if id.sym() == "children" {
ctx.add_diagnostic(attr.range(), CODE, MESSAGE);
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn jsx_no_children_prop_valid() {
assert_lint_ok! {
JSXNoChildrenProp,
filename: "file:///foo.jsx",
r#"<div>foo</div>"#,
r#"<div><Foo /><Bar /></div>"#,
};
}
#[test]
fn jsx_no_children_prop_invalid() {
assert_lint_err! {
JSXNoChildrenProp,
filename: "file:///foo.jsx",
r#"<div children="foo" />"#: [
{
col: 5,
message: MESSAGE,
}
],
r#"<Foo children="foo" />"#: [
{
col: 5,
message: MESSAGE,
}
],
r#"<div children={[1, 2]} />"#: [
{
col: 5,
message: MESSAGE,
}
],
};
}
}