Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

Commit

Permalink
chore: address code suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
ematipico committed Nov 28, 2022
1 parent 7e8d0a0 commit e4a09df
Show file tree
Hide file tree
Showing 14 changed files with 749 additions and 744 deletions.
1 change: 0 additions & 1 deletion crates/rome_analyze/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use std::{borrow, collections::BTreeSet};
pub enum Phases {
Syntax = 0,
Semantic = 1,
Accessibility = 2,
}

/// Defines which phase a rule will run. This will be defined
Expand Down
5 changes: 3 additions & 2 deletions crates/rome_analyze/src/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,9 @@ impl RuleDiagnostic {
self.footer(LogCategory::Info, msg)
}

///
pub fn note_list(mut self, message: impl Display, list: &[impl Display]) -> Self {
/// It creates a new footer note which contains a message and a list of possible suggestions.
/// Useful when there's need to suggest a list of things inside a diagnostic.
pub fn footer_list(mut self, message: impl Display, list: &[impl Display]) -> Self {
if !list.is_empty() {
self.rule_advice.suggestion_list = Some(SuggestionList {
message: markup! { {message} }.to_owned(),
Expand Down
3 changes: 0 additions & 3 deletions crates/rome_aria/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
//! - ARIA properties
//! - ARIA property types
//! - ARIA roles
//!
//! **Note**: the crate relies on `binary_search`, which means that the
//! entries of all these constants must be ordered!
pub const ARIA_PROPERTIES: [&str; 48] = [
"aria-activedescendant",
Expand Down
796 changes: 391 additions & 405 deletions crates/rome_aria/src/generated.rs

Large diffs are not rendered by default.

279 changes: 6 additions & 273 deletions crates/rome_aria/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,281 +1,14 @@
extern crate core;

use crate::constants::{
ARIA_ABSTRACT_ROLES, ARIA_DOCUMENT_STRUCTURE_ROLES, ARIA_PROPERTIES, ARIA_PROPERTY_TYPE,
ARIA_WIDGET_ROLES,
};
use crate::generated::{
AriaAbstractRolesEnum, AriaDocumentStructureRolesEnum, AriaPropertiesEnum,
AriaPropertyTypeEnum, AriaWidgetRolesEnum,
};
use rustc_hash::FxHashMap;
use crate::constants::{ARIA_PROPERTIES, ARIA_PROPERTY_TYPE};

#[rustfmt::skip]
mod generated;

pub mod constants;
pub mod properties;
pub mod roles;

#[derive(Debug)]
pub enum AriaRole {
Widget(AriaWidgetRolesEnum),
Document(AriaDocumentStructureRolesEnum),
Abstract(AriaAbstractRolesEnum),
}

impl From<AriaRole> for &str {
fn from(s: AriaRole) -> Self {
match s {
AriaRole::Widget(widget) => widget.into(),
AriaRole::Document(document) => document.into(),
AriaRole::Abstract(abs) => abs.into(),
}
}
}

impl From<&str> for AriaRole {
fn from(s: &str) -> Self {
if ARIA_WIDGET_ROLES.binary_search(&s).is_ok() {
Self::Widget(AriaWidgetRolesEnum::from(s))
} else if ARIA_ABSTRACT_ROLES.binary_search(&s).is_ok() {
Self::Abstract(AriaAbstractRolesEnum::from(s))
} else if ARIA_DOCUMENT_STRUCTURE_ROLES.binary_search(&s).is_ok() {
Self::Document(AriaDocumentStructureRolesEnum::from(s))
} else {
unreachable!("Should not come here")
}
}
}

/// Table reference example: https://www.w3.org/TR/wai-aria-1.1/#checkbox
#[derive(Debug, Default)]
pub struct AriaRoleDefinition {
properties: Vec<AriaRoleProperty>,
super_class_role: Vec<AriaRole>,
}

#[derive(Debug)]
pub struct AriaRoleProperty {
pub property: AriaPropertiesEnum,
pub required: bool,
}

impl AriaRoleDefinition {
fn with_prop(mut self, property_name: &str, required: bool) -> Self {
self.properties.push(AriaRoleProperty {
property: AriaPropertiesEnum::from(property_name),
required,
});

self
}

fn with_roles(mut self, roles: &[&str]) -> Self {
for role_name in roles {
self.super_class_role.push(AriaRole::from(*role_name))
}

self
}

/// Given a [aria property](ARIA_PROPERTIES) as input, it checks if it's required
/// for the current role.
///
/// If the property doesn't exist for the current role, [false] is returned.
///
/// ## Examples
///
/// ```
///
/// use rome_aria::AriaRoles;
/// let roles = AriaRoles::default();
///
/// let checkbox_role = roles.get_role("checkbox").unwrap();
///
/// assert_eq!(checkbox_role.is_property_required("aria-readonly"), false);
/// assert_eq!(checkbox_role.is_property_required("aria-checked"), true);
///
/// ```
pub fn is_property_required(&self, property_to_check: &str) -> bool {
if is_aria_property_valid(property_to_check) {
let property_to_check = AriaPropertiesEnum::from(property_to_check);
for role_property in &self.properties {
if role_property.property == property_to_check {
return role_property.required;
}
}
}
false
}

/// It returns an iterator over the properties of the current role
///
/// ## Examples
///
/// ```
/// use rome_aria::AriaRoles;
/// let roles = AriaRoles::default();
///
/// let checkbox_role = roles.get_role("checkbox").unwrap();
///
/// let properties = checkbox_role.properties();
/// assert_eq!(properties.len(), 2);
/// ```
pub fn properties(&self) -> std::slice::Iter<AriaRoleProperty> {
self.properties.iter()
}
}

/// A collection of ARIA roles with their metadata, necessary to perform various operations.
#[derive(Debug)]
pub struct AriaRoles(FxHashMap<&'static str, AriaRoleDefinition>);

impl Default for AriaRoles {
fn default() -> Self {
Self::new()
}
}

impl AriaRoles {
/// It instantiate the ARIA roles
pub fn new() -> Self {
let mut hash_map = FxHashMap::default();
// https://www.w3.org/TR/wai-aria-1.1/#button
hash_map.insert(
"button",
AriaRoleDefinition::default()
.with_prop("aria-expanded", false)
.with_prop("aria-pressed", false)
.with_roles(&["roletype", "widget", "command"]),
);
// https://www.w3.org/TR/wai-aria-1.1/#checkbox
hash_map.insert(
"checkbox",
AriaRoleDefinition::default()
.with_prop("aria-checked", true)
.with_prop("aria-readonly", false)
.with_roles(&["switch", "menuitemcheckbox", "widget"]),
);

Self(hash_map)
}

/// It returns the metadata of a role, if it exits.
///
/// ## Examples
///
/// ```
/// use rome_aria::AriaRoles;
/// let roles = AriaRoles::default();
///
///
/// let button_role = roles.get_role("button");
/// let made_up_role = roles.get_role("made-up");
///
/// assert!(button_role.is_some());
/// assert!(made_up_role.is_none());
/// ```
pub fn get_role(&self, role: &str) -> Option<&AriaRoleDefinition> {
self.0.get(role)
}
}

/// A collection of ARIA properties with their metadata, necessary to perform various operations.
#[derive(Debug)]
pub struct AriaProperties(FxHashMap<&'static str, AriaPropertyDefinition>);

impl Default for AriaProperties {
fn default() -> Self {
Self::new()
}
}

impl AriaProperties {
pub fn new() -> Self {
let mut list = FxHashMap::default();

list.insert(
"aria-current",
AriaPropertyDefinition::new("token")
.with_values(&["page", "step", "location", "date", "time", "true", "false"]),
);

Self(list)
}

pub fn get_property(&self, property_name: &str) -> Option<&AriaPropertyDefinition> {
self.0.get(property_name)
}
}

#[derive(Debug)]
pub struct AriaPropertyDefinition {
property_type: AriaPropertyTypeEnum,
values: Vec<String>,
}

impl AriaPropertyDefinition {
fn new(property_type: &str) -> Self {
Self {
property_type: AriaPropertyTypeEnum::from(property_type),
values: vec![],
}
}

fn with_values(mut self, values: &[&str]) -> Self {
self.values = values.iter().map(|value| value.to_string()).collect();
self
}

/// It checks if a value is complaint for the current ARIA property.
///
/// [Source](https://www.w3.org/TR/wai-aria-1.1/#propcharacteristic_value)
///
/// ## Examples
///
/// ```
/// use rome_aria::AriaProperties;
///
/// let aria_properties = AriaProperties::default();
///
/// let aria_current = aria_properties.get_property("aria-current").unwrap();
///
/// assert!(aria_current.contains_correct_value("true"));
/// assert!(aria_current.contains_correct_value("false"));
/// assert!(aria_current.contains_correct_value("step"));
/// assert!(!aria_current.contains_correct_value("something_not_allowed"));
/// ```
pub fn contains_correct_value(&self, input_value: &str) -> bool {
match self.property_type {
AriaPropertyTypeEnum::String | AriaPropertyTypeEnum::Id => {
input_value.parse::<f32>().is_err()
}
AriaPropertyTypeEnum::Idlist => input_value
.split(' ')
.any(|piece| piece.parse::<f32>().is_err()),
// A numerical value without a fractional component.
AriaPropertyTypeEnum::Integer => input_value.parse::<u32>().is_ok(),
AriaPropertyTypeEnum::Number => input_value.parse::<f32>().is_ok(),
AriaPropertyTypeEnum::Boolean => {
matches!(input_value, "false" | "true")
}
AriaPropertyTypeEnum::Token => self
.values
.iter()
.any(|allowed_token| allowed_token == input_value),
AriaPropertyTypeEnum::Tokenlist => input_value.split(' ').all(|input_token| {
self.values
.iter()
.any(|allowed_token| allowed_token == input_token)
}),
AriaPropertyTypeEnum::Tristate => {
matches!(input_value, "false" | "true" | "mixed")
}
}
}
pub fn get_allowed_values(&self) -> &Vec<String> {
&self.values
}
}
pub use properties::AriaProperties;
pub use roles::AriaRoles;

/// It checks if an ARIA property is valid
///
Expand Down Expand Up @@ -307,7 +40,7 @@ pub fn is_aria_property_type_valid(property_type: &str) -> bool {

#[cfg(test)]
mod test {
use crate::AriaRoles;
use crate::roles::AriaRoles;

#[test]
fn property_is_required() {
Expand Down
Loading

0 comments on commit e4a09df

Please sign in to comment.