Skip to content

Commit

Permalink
fix: performance improvement
Browse files Browse the repository at this point in the history
  • Loading branch information
yossydev committed Jan 9, 2024
1 parent 1b830be commit 9d9a43c
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::collections::{HashMap, HashSet};

use crate::{context::LintContext, rule::Rule, utils::has_jsx_prop_lowercase, AstNode};
use once_cell::sync::OnceCell;
use oxc_ast::{
ast::{JSXAttributeItem, JSXAttributeValue},
AstKind,
Expand All @@ -9,7 +12,6 @@ use oxc_diagnostics::{
};
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use phf::{phf_map, phf_set};

#[derive(Debug, Error, Diagnostic)]
#[error(
Expand Down Expand Up @@ -42,21 +44,42 @@ declare_oxc_lint!(
///
/// // Good
/// <div role="checkbox" aria-checked="false" />
/// ````
/// ```
RoleHasRequiredAriaProps,
correctness
);

static ROLE_TO_REQUIRED_ARIA_PROPS: phf::Map<&'static str, phf::Set<&'static str>> = phf_map! {
"checkbox" => phf_set!{"aria-checked"},
"radio" => phf_set!{"aria-checked"},
"combobox" => phf_set!{"aria-controls", "aria-expanded"},
"tab" => phf_set!{"aria-selected"},
"slider" => phf_set!{"aria-valuemax", "aria-valuemin", "aria-valuenow"},
"scrollbar" => phf_set!{"aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-orientation", "aria-controls"},
"heading" => phf_set!{"aria-level"},
"option" => phf_set!{"aria-selected"},
};
static ROLE_TO_REQUIRED_ARIA_PROPS: OnceCell<HashMap<&'static str, HashSet<&'static str>>> =
OnceCell::new();

fn get_role_to_required_aria_props() -> &'static HashMap<&'static str, HashSet<&'static str>> {
ROLE_TO_REQUIRED_ARIA_PROPS.get_or_init(|| {
let mut map = HashMap::new();
map.insert("checkbox", vec!["aria-checked"].into_iter().collect());
map.insert("radio", vec!["aria-checked"].into_iter().collect());
map.insert("combobox", vec!["aria-controls", "aria-expanded"].into_iter().collect());
map.insert("tab", vec!["aria-selected"].into_iter().collect());
map.insert(
"slider",
vec!["aria-valuemax", "aria-valuemin", "aria-valuenow"].into_iter().collect(),
);
map.insert(
"scrollbar",
vec![
"aria-valuemax",
"aria-valuemin",
"aria-valuenow",
"aria-orientation",
"aria-controls",
]
.into_iter()
.collect(),
);
map.insert("heading", vec!["aria-level"].into_iter().collect());
map.insert("option", vec!["aria-selected"].into_iter().collect());
map
})
}

impl Rule for RoleHasRequiredAriaProps {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
Expand All @@ -65,8 +88,9 @@ impl Rule for RoleHasRequiredAriaProps {
let JSXAttributeItem::Attribute(attr) = role_prop else { return };
let Some(JSXAttributeValue::StringLiteral(role_values)) = &attr.value else { return };
let roles = role_values.value.split_whitespace();
let role_to_required_aria_props = get_role_to_required_aria_props();
for role in roles {
if let Some(props) = ROLE_TO_REQUIRED_ARIA_PROPS.get(role) {
if let Some(props) = role_to_required_aria_props.get(role) {
for prop in props {
if has_jsx_prop_lowercase(jsx_el, prop).is_none() {
ctx.diagnostic(RoleHasRequiredAriaPropsDiagnostic {
Expand Down
70 changes: 35 additions & 35 deletions crates/oxc_linter/src/snapshots/role_has_required_aria_props.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
source: crates/oxc_linter/src/tester.rs
expression: role_has_required_aria_props
---
eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuenow`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuemax`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='slider' />
· ─────────────
╰────
help: Add missing aria props `aria-valuenow` to the element with `slider` role.
help: Add missing aria props `aria-valuemax` to the element with `slider` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuemin`.
╭─[role_has_required_aria_props.tsx:1:1]
Expand All @@ -16,26 +16,26 @@ expression: role_has_required_aria_props
╰────
help: Add missing aria props `aria-valuemin` to the element with `slider` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuemax`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuenow`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='slider' />
· ─────────────
╰────
help: Add missing aria props `aria-valuemax` to the element with `slider` role.
help: Add missing aria props `aria-valuenow` to the element with `slider` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuenow`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuemin`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='slider' aria-valuemax />
· ─────────────
╰────
help: Add missing aria props `aria-valuenow` to the element with `slider` role.
help: Add missing aria props `aria-valuemin` to the element with `slider` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuemin`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuenow`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='slider' aria-valuemax />
· ─────────────
╰────
help: Add missing aria props `aria-valuemin` to the element with `slider` role.
help: Add missing aria props `aria-valuenow` to the element with `slider` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `slider` role is missing required aria props `aria-valuenow`.
╭─[role_has_required_aria_props.tsx:1:1]
Expand Down Expand Up @@ -114,26 +114,26 @@ expression: role_has_required_aria_props
╰────
help: Add missing aria props `aria-expanded` to the element with `combobox` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-orientation`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemax`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' />
· ────────────────
╰────
help: Add missing aria props `aria-orientation` to the element with `scrollbar` role.
help: Add missing aria props `aria-valuemax` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemax`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuenow`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' />
· ────────────────
╰────
help: Add missing aria props `aria-valuemax` to the element with `scrollbar` role.
help: Add missing aria props `aria-valuenow` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemin`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-orientation`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' />
· ────────────────
╰────
help: Add missing aria props `aria-valuemin` to the element with `scrollbar` role.
help: Add missing aria props `aria-orientation` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-controls`.
╭─[role_has_required_aria_props.tsx:1:1]
Expand All @@ -142,11 +142,18 @@ expression: role_has_required_aria_props
╰────
help: Add missing aria props `aria-controls` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuenow`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemin`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' />
· ────────────────
╰────
help: Add missing aria props `aria-valuemin` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuenow`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemax />
· ────────────────
╰────
help: Add missing aria props `aria-valuenow` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-orientation`.
Expand All @@ -156,23 +163,23 @@ expression: role_has_required_aria_props
╰────
help: Add missing aria props `aria-orientation` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemin`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-controls`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemax />
· ────────────────
╰────
help: Add missing aria props `aria-valuemin` to the element with `scrollbar` role.
help: Add missing aria props `aria-controls` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-controls`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemin`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemax />
· ────────────────
╰────
help: Add missing aria props `aria-controls` to the element with `scrollbar` role.
help: Add missing aria props `aria-valuemin` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuenow`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemax />
1<div role='scrollbar' aria-valuemax aria-valuemin />
· ────────────────
╰────
help: Add missing aria props `aria-valuenow` to the element with `scrollbar` role.
Expand All @@ -191,47 +198,40 @@ expression: role_has_required_aria_props
╰────
help: Add missing aria props `aria-controls` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuenow`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemax aria-valuemin />
· ────────────────
╰────
help: Add missing aria props `aria-valuenow` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-orientation`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemax aria-valuenow />
· ────────────────
╰────
help: Add missing aria props `aria-orientation` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemin`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-controls`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemax aria-valuenow />
· ────────────────
╰────
help: Add missing aria props `aria-valuemin` to the element with `scrollbar` role.
help: Add missing aria props `aria-controls` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-controls`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemin`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemax aria-valuenow />
· ────────────────
╰────
help: Add missing aria props `aria-controls` to the element with `scrollbar` role.
help: Add missing aria props `aria-valuemin` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-orientation`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemax`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemin aria-valuenow />
· ────────────────
╰────
help: Add missing aria props `aria-orientation` to the element with `scrollbar` role.
help: Add missing aria props `aria-valuemax` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-valuemax`.
eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-orientation`.
╭─[role_has_required_aria_props.tsx:1:1]
1<div role='scrollbar' aria-valuemin aria-valuenow />
· ────────────────
╰────
help: Add missing aria props `aria-valuemax` to the element with `scrollbar` role.
help: Add missing aria props `aria-orientation` to the element with `scrollbar` role.

eslint-plugin-jsx-a11y(role-has-required-aria-props): `scrollbar` role is missing required aria props `aria-controls`.
╭─[role_has_required_aria_props.tsx:1:1]
Expand Down

0 comments on commit 9d9a43c

Please sign in to comment.