Skip to content

Commit

Permalink
feat(linter): complete custom components setting
Browse files Browse the repository at this point in the history
  • Loading branch information
huangjunjie.coder committed Jan 31, 2024
1 parent bd23c3a commit b8a0984
Show file tree
Hide file tree
Showing 4 changed files with 343 additions and 89 deletions.
109 changes: 103 additions & 6 deletions crates/oxc_linter/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@ use std::path::Path;

use oxc_diagnostics::{Error, FailedToOpenFileError, Report};
use rustc_hash::{FxHashMap, FxHashSet};
use serde_json::Value;
use serde_json::{Map, Value};

use crate::{rules::RuleEnum, AllowWarnDeny};

use self::errors::{
FailedToParseConfigError, FailedToParseConfigJsonError, FailedToParseJsonc,
FailedToParseRuleValueError,
};
pub use self::{
env::ESLintEnv,
settings::{ESLintSettings, JsxA11y, Nextjs},
};
use self::{
errors::{
FailedToParseConfigError, FailedToParseConfigJsonError, FailedToParseJsonc,
FailedToParseRuleValueError,
},
settings::{FormComponents, LinkComponents},
};

/// ESLint Config
/// <https://eslint.org/docs/latest/use/configure/configuration-files-new#configuration-objects>
Expand Down Expand Up @@ -180,6 +183,8 @@ pub fn parse_settings(setting_value: &Value) -> ESLintSettings {
if let Value::Object(settings_object) = setting_value {
let mut jsx_a11y_setting = JsxA11y::new(None, FxHashMap::default());
let mut nextjs_setting = Nextjs::new(vec![]);
let mut link_components_setting: Vec<LinkComponents> = vec![];
let mut form_components_setting: Vec<FormComponents> = vec![];
if let Some(Value::Object(jsx_a11y)) = settings_object.get("jsx-a11y") {
if let Some(Value::Object(components)) = jsx_a11y.get("components") {
let components_map: FxHashMap<String, String> = components
Expand Down Expand Up @@ -208,12 +213,104 @@ pub fn parse_settings(setting_value: &Value) -> ESLintSettings {
}
}

return ESLintSettings::new(jsx_a11y_setting, nextjs_setting);
parse_custom_components(
settings_object,
CustomComponentEnum::LinkComponents(&mut link_components_setting),
);
parse_custom_components(
settings_object,
CustomComponentEnum::FormComponents(&mut form_components_setting),
);

return ESLintSettings::new(
jsx_a11y_setting,
nextjs_setting,
link_components_setting,
form_components_setting,
);
}

ESLintSettings::default()
}

enum CustomComponentEnum<'a> {
LinkComponents(&'a mut Vec<LinkComponents>),
FormComponents(&'a mut Vec<FormComponents>),
}

fn parse_custom_components(settings_object: &Map<String, Value>, settings: CustomComponentEnum) {
fn parse_obj(obj: &Map<String, Value>, attribute_name: &str) -> Option<(String, Vec<String>)> {
if let Some(Value::String(name)) = obj.get("name") {
let mut arr: Vec<String> = vec![];
if let Some(Value::String(attribute)) = obj.get(attribute_name) {
arr.push(attribute.to_string());
} else if let Some(Value::Array(attributes)) = obj.get(attribute_name) {
for attribute in attributes {
if let Value::String(attribute) = attribute {
arr.push(attribute.to_string());
}
}
}
return Some((name.to_string(), arr));
}
None
}

fn parse_component(
settings_object: &Map<String, Value>,
component_name: &str,
attribute_name: &str,
) -> Vec<Option<(String, Vec<String>)>> {
match settings_object.get(component_name) {
Some(Value::Array(component)) => component
.iter()
.map(|component| {
if let Value::String(name) = component {
return Some((name.to_string(), [].to_vec()));
}
if let Value::Object(obj) = component {
return parse_obj(obj, attribute_name);
}
None
})
.collect(),
Some(Value::Object(obj)) => [parse_obj(obj, attribute_name)].to_vec(),
_ => [].to_vec(),
}
}

match settings {
CustomComponentEnum::FormComponents(setting) => {
let res = parse_component(settings_object, "FormComponents", "formAttribute");
let mut setting_list: Vec<FormComponents> = res
.into_iter()
.filter_map(|option_tuple| {
if let Some(tuple) = option_tuple {
Some(FormComponents { name: tuple.0, form_attribute: tuple.1 })
} else {
None
}
})
.collect();
setting.append(&mut setting_list);
}
CustomComponentEnum::LinkComponents(setting) => {
let res = parse_component(settings_object, "linkComponents", "linkAttribute");
let mut setting_list: Vec<LinkComponents> = res
.into_iter()
.filter_map(|option_tuple| {
if let Some(tuple) = option_tuple {
Some(LinkComponents { name: tuple.0, link_attribute: tuple.1 })
} else {
None
}
})
.collect();
setting.append(&mut setting_list);
}
}
}

fn parse_env_from_root(root_json: &Value) -> ESLintEnv {
let Value::Object(root_object) = root_json else { return ESLintEnv::default() };

Expand Down
25 changes: 23 additions & 2 deletions crates/oxc_linter/src/config/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,29 @@ use rustc_hash::FxHashMap;
pub struct ESLintSettings {
pub jsx_a11y: JsxA11y,
pub nextjs: Nextjs,
pub link_components: Vec<LinkComponents>,
pub form_components: Vec<FormComponents>,
}

impl Default for ESLintSettings {
fn default() -> Self {
Self {
jsx_a11y: JsxA11y { polymorphic_prop_name: None, components: FxHashMap::default() },
nextjs: Nextjs { root_dir: vec![] },
link_components: vec![],
form_components: vec![],
}
}
}

impl ESLintSettings {
pub fn new(jsx_a11y: JsxA11y, nextjs: Nextjs) -> Self {
Self { jsx_a11y, nextjs }
pub fn new(
jsx_a11y: JsxA11y,
nextjs: Nextjs,
link_components: Vec<LinkComponents>,
form_components: Vec<FormComponents>,
) -> Self {
Self { jsx_a11y, nextjs, link_components, form_components }
}
}

Expand Down Expand Up @@ -61,3 +70,15 @@ impl Nextjs {
self.root_dir = root_dir;
}
}

#[derive(Debug, Clone)]
pub struct LinkComponents {
pub name: String,
pub link_attribute: Vec<String>,
}

#[derive(Debug, Clone)]
pub struct FormComponents {
pub name: String,
pub form_attribute: Vec<String>,
}
Loading

0 comments on commit b8a0984

Please sign in to comment.