Skip to content

Commit

Permalink
feat(linter): support eslint config in nextjs eslint (#2107)
Browse files Browse the repository at this point in the history
related: #1929

Support Next.js eslint config settings.
- [custom settings
](https://nextjs.org/docs/app/building-your-application/configuring/eslint#custom-settings)
- also handle Next.js eslint rule name mapping

these are need before implementing [this
rule](https://nextjs.org/docs/messages/no-html-link-for-pages)
  • Loading branch information
kaykdm authored Jan 22, 2024
1 parent 2228aa8 commit b160842
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 8 deletions.
23 changes: 19 additions & 4 deletions crates/oxc_linter/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use oxc_diagnostics::{Error, FailedToOpenFileError, Report};
use rustc_hash::{FxHashMap, FxHashSet};
use serde_json::Value;

use crate::{rules::RuleEnum, AllowWarnDeny, JsxA11y, LintSettings};
use crate::{rules::RuleEnum, settings::Nextjs, AllowWarnDeny, JsxA11y, LintSettings};

use self::errors::{
FailedToParseConfigError, FailedToParseConfigJsonError, FailedToParseRuleValueError,
Expand Down Expand Up @@ -167,9 +167,9 @@ fn parse_settings_from_root(root_json: &Value) -> LintSettings {

pub fn parse_settings(setting_value: &Value) -> LintSettings {
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![]);
if let Some(Value::Object(jsx_a11y)) = settings_object.get("jsx-a11y") {
let mut jsx_a11y_setting = JsxA11y::new(None, FxHashMap::default());

if let Some(Value::Object(components)) = jsx_a11y.get("components") {
let components_map: FxHashMap<String, String> = components
.iter()
Expand All @@ -184,9 +184,20 @@ pub fn parse_settings(setting_value: &Value) -> LintSettings {
jsx_a11y_setting
.set_polymorphic_prop_name(Some(String::from(polymorphic_prop_name)));
}
}

return LintSettings::new(jsx_a11y_setting);
if let Some(Value::Object(nextjs)) = settings_object.get("next") {
if let Some(Value::String(root_dir)) = nextjs.get("rootDir") {
nextjs_setting.set_root_dir(vec![String::from(root_dir)]);
}
if let Some(Value::Array(root_dir)) = nextjs.get("rootDir") {
nextjs_setting.set_root_dir(
root_dir.iter().map(|v| v.as_str().unwrap().to_string()).collect(),
);
}
}

return LintSettings::new(jsx_a11y_setting, nextjs_setting);
}

LintSettings::default()
Expand All @@ -201,9 +212,13 @@ fn parse_rule_name(name: &str) -> (&str, &str) {
"typescript-eslint" => "typescript",
// plugin name in RuleEnum is in snake_case
"jsx-a11y" => "jsx_a11y",
"next" => "nextjs",
_ => category,
};

// since next.js eslint rule starts with @next/next/
let name = name.trim_start_matches("next/");

(category, name)
} else {
("eslint", name)
Expand Down
25 changes: 22 additions & 3 deletions crates/oxc_linter/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ use rustc_hash::FxHashMap;
#[derive(Debug, Clone)]
pub struct LintSettings {
pub jsx_a11y: JsxA11y,
pub nextjs: Nextjs,
}

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

impl LintSettings {
pub fn new(jsx_a11y: JsxA11y) -> Self {
Self { jsx_a11y }
pub fn new(jsx_a11y: JsxA11y, nextjs: Nextjs) -> Self {
Self { jsx_a11y, nextjs }
}
}

Expand All @@ -40,3 +44,18 @@ impl JsxA11y {
self.polymorphic_prop_name = name;
}
}

#[derive(Debug, Clone)]
pub struct Nextjs {
pub root_dir: Vec<String>,
}

impl Nextjs {
pub fn new(root_dir: Vec<String>) -> Self {
Self { root_dir }
}

pub fn set_root_dir(&mut self, root_dir: Vec<String>) {
self.root_dir = root_dir;
}
}
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/utils/react.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ pub fn get_element_type(context: &LintContext, element: &JSXOpeningElement) -> O
return None;
};

let LintSettings { jsx_a11y } = context.settings();
let LintSettings { jsx_a11y, .. } = context.settings();
let JsxA11y { polymorphic_prop_name, components } = jsx_a11y;

if let Some(polymorphic_prop_name_value) = polymorphic_prop_name {
Expand Down

0 comments on commit b160842

Please sign in to comment.