Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/config/config_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ mod test {
// Base config has external rule with options A, severity warn
let base_external_rule_id = store.lookup_rule_id("custom", "my-rule").unwrap();
let base_options_id =
store.add_options(ExternalRuleId::DUMMY, serde_json::json!([{ "opt": "A" }]));
store.add_options(ExternalRuleId::DUMMY, vec![serde_json::json!({ "opt": "A" })]);

let base = Config::new(
vec![],
Expand All @@ -1096,7 +1096,7 @@ mod test {
base_external_rule_id,
store.add_options(
ExternalRuleId::DUMMY,
serde_json::json!([{ "opt": "B" }]),
vec![serde_json::json!({ "opt": "B" })],
),
AllowWarnDeny::Deny,
)],
Expand Down
21 changes: 15 additions & 6 deletions crates/oxc_linter/src/config/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ pub struct ESLintRule {
/// Severity of the rule: `off`, `warn`, `error`, etc.
pub severity: AllowWarnDeny,
/// JSON configuration for the rule, if any.
pub config: Option<serde_json::Value>,
/// If is `Some`, the `Vec` must not be empty.
pub config: Option<Vec<serde_json::Value>>,
}

impl OxlintRules {
Expand Down Expand Up @@ -95,7 +96,15 @@ impl OxlintRules {
.find(|r| r.name() == rule_name && r.plugin_name() == plugin_name)
});
if let Some(rule) = rule {
let config = rule_config.config.clone().unwrap_or_default();
// Configs are stored as `Option<Vec<Value>>`, but `from_configuration` expects
// a single `Value` with `Value::Null` being the equivalent of `None`
let config = match &rule_config.config {
Some(config) => {
debug_assert!(!config.is_empty());
serde_json::Value::Array(config.clone())
}
None => serde_json::Value::Null,
};
rules_to_replace.push((rule.from_configuration(config), severity));
}
} else {
Expand Down Expand Up @@ -190,7 +199,7 @@ impl Serialize for OxlintRules {
let key = rule.full_name();
match rule.config.as_ref() {
// e.g. unicorn/some-rule: ["warn", { foo: "bar" }]
Some(config) if !config.is_null() => {
Some(config) => {
let value = (rule.severity.as_str(), config);
rules.serialize_entry(&key, &value)?;
}
Expand Down Expand Up @@ -283,7 +292,7 @@ pub(super) fn unalias_plugin_name(plugin_name: &str, rule_name: &str) -> (String

fn parse_rule_value(
value: serde_json::Value,
) -> Result<(AllowWarnDeny, Option<serde_json::Value>), Error> {
) -> Result<(AllowWarnDeny, Option<Vec<serde_json::Value>>), Error> {
match value {
serde_json::Value::String(_) | serde_json::Value::Number(_) => {
let severity = AllowWarnDeny::try_from(&value)?;
Expand All @@ -307,7 +316,7 @@ fn parse_rule_value(
} else {
// e.g. ["error", "args", { type: "whatever" }, ["len", "also"]]
v.remove(0);
Some(serde_json::Value::Array(v))
Some(v)
};

Ok((severity, config))
Expand Down Expand Up @@ -382,7 +391,7 @@ mod test {
assert_eq!(r3.rule_name, "dummy");
assert_eq!(r3.plugin_name, "eslint");
assert!(r3.severity.is_warn_deny());
assert_eq!(r3.config, Some(serde_json::json!(["arg1", "args2"])));
assert_eq!(r3.config, Some(vec![serde_json::json!("arg1"), serde_json::json!("args2")]));

let r4 = rules.next().unwrap();
assert_eq!(r4.rule_name, "noop");
Expand Down
10 changes: 1 addition & 9 deletions crates/oxc_linter/src/external_plugin_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,19 +145,11 @@ impl ExternalPluginStore {
}

/// Add options to the store and return its [`ExternalOptionsId`].
///
/// `options` must be a `serde_json::Value::Array`.
///
/// # Panics
/// Panics if `options` is not an array.
pub fn add_options(
&mut self,
rule_id: ExternalRuleId,
options: serde_json::Value,
options: Vec<serde_json::Value>,
) -> ExternalOptionsId {
let serde_json::Value::Array(options) = options else {
panic!("`options` must be an array");
};
debug_assert!(!options.is_empty(), "`options` should never be an empty `Vec`");
self.options.push((rule_id, options))
}
Expand Down
Loading