diff --git a/apps/oxlint/src-js/package/config.generated.ts b/apps/oxlint/src-js/package/config.generated.ts index def3732fb7..8ff41ef092 100644 --- a/apps/oxlint/src-js/package/config.generated.ts +++ b/apps/oxlint/src-js/package/config.generated.ts @@ -80,12 +80,13 @@ export type CurlyType = "all" | "multi" | "multi-line" | "multi-or-nest"; export type CurlyConsistent = "consistent"; export type CompareType = "always" | "smart"; export type NullType = "always" | "never" | "ignore"; -export type DummyRule = AllowWarnDeny | [AllowWarnDeny, ...unknown[]]; +export type FuncNameMatchingMode = "always" | "never"; export type FuncNamesConfigType = "always" | "as-needed" | "never"; export type Style = "expression" | "declaration"; export type NamedExports = "ignore" | "expression" | "declaration"; export type PairOrder = "anyOrder" | "getBeforeSet" | "setBeforeGet"; export type Mode = "prefer-top-level" | "prefer-inline"; +export type DummyRule = AllowWarnDeny | [AllowWarnDeny, ...unknown[]]; export type AbsoluteFirst = "absolute-first" | "disable-absolute-first"; export type MaxDependenciesConfigJson = number | MaxDependenciesConfig; export type Target = "single" | "any"; @@ -829,7 +830,7 @@ export interface DummyRuleMap { "block-scoped-var"?: RuleNoConfig; "capitalized-comments"?: RuleNoConfig | [AllowWarnDeny, AlwaysNever] | [AllowWarnDeny, AlwaysNever, OptionsJsonEnum]; "class-methods-use-this"?: RuleNoConfig | [AllowWarnDeny, ClassMethodsUseThisConfig]; - complexity?: RuleNoConfig | [AllowWarnDeny, number | ComplexityConfig]; + complexity?: RuleNoConfig | ([AllowWarnDeny, number] | [AllowWarnDeny, ComplexityConfig]); "constructor-super"?: RuleNoConfig; curly?: RuleNoConfig | [AllowWarnDeny, CurlyType] | [AllowWarnDeny, CurlyType, CurlyConsistent]; "default-case"?: RuleNoConfig | [AllowWarnDeny, DefaultCaseConfig]; @@ -837,7 +838,14 @@ export interface DummyRuleMap { "default-param-last"?: RuleNoConfig; eqeqeq?: RuleNoConfig | [AllowWarnDeny, CompareType] | [AllowWarnDeny, CompareType, EqeqeqOptions]; "for-direction"?: RuleNoConfig; - "func-name-matching"?: DummyRule; + "func-name-matching"?: + | RuleNoConfig + | ( + | [AllowWarnDeny, FuncNameMatchingMode] + | [AllowWarnDeny, FuncNameMatchingMode, FuncNameMatchingConfig] + | [AllowWarnDeny, FuncNameMatchingMode] + | [AllowWarnDeny, FuncNameMatchingConfig] + ); "func-names"?: | RuleNoConfig | [AllowWarnDeny, FuncNamesConfigType] @@ -1014,13 +1022,13 @@ export interface DummyRuleMap { | RuleNoConfig | [AllowWarnDeny, AlwaysNever] | [AllowWarnDeny, AlwaysNever, LogicalAssignmentOperatorsConfig]; - "max-classes-per-file"?: RuleNoConfig | [AllowWarnDeny, number | MaxClassesPerFileConfig]; - "max-depth"?: RuleNoConfig | [AllowWarnDeny, number | MaxDepth]; - "max-lines"?: RuleNoConfig | [AllowWarnDeny, number | MaxLinesConfig]; - "max-lines-per-function"?: RuleNoConfig | [AllowWarnDeny, number | MaxLinesPerFunctionConfig]; - "max-nested-callbacks"?: RuleNoConfig | [AllowWarnDeny, number | MaxNestedCallbacks]; - "max-params"?: RuleNoConfig | [AllowWarnDeny, number | MaxParamsConfig]; - "max-statements"?: RuleNoConfig | [AllowWarnDeny, number | MaxStatementsConfig]; + "max-classes-per-file"?: RuleNoConfig | ([AllowWarnDeny, number] | [AllowWarnDeny, MaxClassesPerFileConfig]); + "max-depth"?: RuleNoConfig | ([AllowWarnDeny, number] | [AllowWarnDeny, MaxDepth]); + "max-lines"?: RuleNoConfig | ([AllowWarnDeny, number] | [AllowWarnDeny, MaxLinesConfig]); + "max-lines-per-function"?: RuleNoConfig | ([AllowWarnDeny, number] | [AllowWarnDeny, MaxLinesPerFunctionConfig]); + "max-nested-callbacks"?: RuleNoConfig | ([AllowWarnDeny, number] | [AllowWarnDeny, MaxNestedCallbacks]); + "max-params"?: RuleNoConfig | ([AllowWarnDeny, number] | [AllowWarnDeny, MaxParamsConfig]); + "max-statements"?: RuleNoConfig | ([AllowWarnDeny, number] | [AllowWarnDeny, MaxStatementsConfig]); "new-cap"?: RuleNoConfig | [AllowWarnDeny, NewCapConfig]; "nextjs/google-font-display"?: RuleNoConfig; "nextjs/google-font-preconnect"?: RuleNoConfig; @@ -1800,6 +1808,16 @@ export interface EqeqeqOptions { */ null?: NullType; } +export interface FuncNameMatchingConfig { + /** + * If `considerPropertyDescriptor` is set to `true`, the check will take into account the use of `Object.create`, `Object.defineProperty`, `Object.defineProperties`, and `Reflect.defineProperty`. + */ + considerPropertyDescriptor?: boolean; + /** + * If `includeCommonJSModuleExports` is set to `true`, `module.exports` and `module["exports"]` will be checked by this rule. + */ + includeCommonJSModuleExports?: boolean; +} export interface FuncNamesGeneratorsConfig { /** * Configuration for generator function expressions. If not specified, uses the diff --git a/crates/oxc_linter/src/config/rules.rs b/crates/oxc_linter/src/config/rules.rs index b532f12a7e..79329b6665 100644 --- a/crates/oxc_linter/src/config/rules.rs +++ b/crates/oxc_linter/src/config/rules.rs @@ -397,104 +397,123 @@ impl JsonSchema for OxlintRules { .into() } + fn append_allow_warn_deny_to_schema( + config_schema: Schema, + r#gen: &mut SchemaGenerator, + ) -> Schema { + let Schema::Object(mut obj) = config_schema else { + return SchemaObject { + instance_type: Some(InstanceType::Array.into()), + array: Some(Box::new(ArrayValidation { + items: Some(SingleOrVec::Vec(vec![ + r#gen.subschema_for::(), + config_schema, + ])), + min_items: Some(2), + max_items: Some(2), + ..Default::default() + })), + ..Default::default() + } + .into(); + }; + + debug_assert!( + (u8::from(obj.array.is_some()) + + u8::from(obj.object.is_some()) + + u8::from(obj.reference.is_some())) + <= 1, + "Expected rule schema to be either an object, an array, or a reference, but not multiple" + ); + + if let Some(reference) = obj.reference { + return SchemaObject { + instance_type: Some(InstanceType::Array.into()), + array: Some(Box::new(ArrayValidation { + items: Some(SingleOrVec::Vec(vec![ + r#gen.subschema_for::(), + Schema::Object(SchemaObject { + reference: Some(reference), + ..Default::default() + }), + ])), + min_items: Some(2), + max_items: Some(2), + ..Default::default() + })), + ..Default::default() + } + .into(); + } + + if let Some(array) = obj.array { + let items = match array.items { + None => vec![r#gen.subschema_for::()], + Some(SingleOrVec::Single(config)) => { + vec![r#gen.subschema_for::(), *config] + } + Some(SingleOrVec::Vec(configs)) => { + let mut items = + Vec::with_capacity(configs.len().saturating_add(1)); + items.push(r#gen.subschema_for::()); + items.extend(configs); + items + } + }; + + let config_length = items.len() as u32; + + return SchemaObject { + instance_type: Some(InstanceType::Array.into()), + array: Some(Box::new(ArrayValidation { + items: Some(SingleOrVec::Vec(items)), + min_items: Some(2), + max_items: Some(config_length), + ..Default::default() + })), + ..Default::default() + } + .into(); + } + + if let Some(subschemas) = &mut obj.subschemas + && let Some(any_of) = &subschemas.any_of + { + subschemas.any_of = Some( + any_of + .iter() + .map(|schema| { + append_allow_warn_deny_to_schema(schema.clone(), r#gen) + }) + .collect(), + ); + + return obj.into(); + } + + SchemaObject { + instance_type: Some(InstanceType::Array.into()), + array: Some(Box::new(ArrayValidation { + items: Some(SingleOrVec::Vec(vec![ + r#gen.subschema_for::(), + Schema::Object(obj), + ])), + min_items: Some(2), + max_items: Some(2), + ..Default::default() + })), + ..Default::default() + } + .into() + } + let Some(schema) = r.schema(r#gen) else { return r#gen.subschema_for::(); }; let schema = resolve_references_in_schema(&schema, r#gen).clone(); - - let Schema::Object(obj) = schema else { - let array_schema = SchemaObject { - instance_type: Some(InstanceType::Array.into()), - array: Some(Box::new(ArrayValidation { - items: Some(SingleOrVec::Vec(vec![ - r#gen.subschema_for::(), - Schema::Bool(true), - ])), - min_items: Some(2), - max_items: Some(2), - ..Default::default() - })), - ..Default::default() - } - .into(); - return with_default_rule_schema(array_schema, r#gen); - }; - - debug_assert!( - (u8::from(obj.array.is_some()) - + u8::from(obj.object.is_some()) - + u8::from(obj.reference.is_some())) - <= 1, - "Expected rule schema to be either an object, an array, or a reference, but not multiple" - ); - - if let Some(reference) = obj.reference { - let array_schema = SchemaObject { - instance_type: Some(InstanceType::Array.into()), - array: Some(Box::new(ArrayValidation { - items: Some(SingleOrVec::Vec(vec![ - r#gen.subschema_for::(), - Schema::Object(SchemaObject { - reference: Some(reference), - ..Default::default() - }), - ])), - min_items: Some(2), - max_items: Some(2), - ..Default::default() - })), - ..Default::default() - } - .into(); - return with_default_rule_schema(array_schema, r#gen); - } - - if let Some(array) = obj.array { - let items = match array.items { - None => vec![r#gen.subschema_for::()], - Some(SingleOrVec::Single(config)) => { - vec![r#gen.subschema_for::(), *config] - } - Some(SingleOrVec::Vec(configs)) => { - let mut items = Vec::with_capacity(configs.len().saturating_add(1)); - items.push(r#gen.subschema_for::()); - items.extend(configs); - items - } - }; - - let config_length = items.len() as u32; - - let array_schema = SchemaObject { - instance_type: Some(InstanceType::Array.into()), - array: Some(Box::new(ArrayValidation { - items: Some(SingleOrVec::Vec(items)), - min_items: Some(2), - max_items: Some(config_length), - ..Default::default() - })), - ..Default::default() - } - .into(); - return with_default_rule_schema(array_schema, r#gen); - } - - let array_schema = Schema::Object(SchemaObject { - instance_type: Some(InstanceType::Array.into()), - array: Some(Box::new(ArrayValidation { - items: Some(SingleOrVec::Vec(vec![ - r#gen.subschema_for::(), - Schema::Object(obj), - ])), - min_items: Some(2), - max_items: Some(2), - ..Default::default() - })), - ..Default::default() - }); - - with_default_rule_schema(array_schema, r#gen) + let schema = append_allow_warn_deny_to_schema(schema, r#gen); + with_default_rule_schema(schema, r#gen) } let dummy_schema = r#gen.subschema_for::(); diff --git a/crates/oxc_linter/src/rule.rs b/crates/oxc_linter/src/rule.rs index c9a4cda7c0..4dea136e10 100644 --- a/crates/oxc_linter/src/rule.rs +++ b/crates/oxc_linter/src/rule.rs @@ -2,7 +2,10 @@ use std::borrow::Cow; use std::{fmt, hash::Hash}; -use schemars::{JsonSchema, SchemaGenerator, schema::Schema}; +use schemars::{ + JsonSchema, SchemaGenerator, + schema::{InstanceType, Schema, SchemaObject}, +}; use serde::{Deserialize, Serialize}; use oxc_semantic::AstTypesBitset; @@ -226,6 +229,116 @@ where } } +/// A wrapper type for deserializing ESLint-style mixed tuple rule configurations, where the first configuration object can be skipped. +/// +/// Some ESLint rules take configurations in tuple form, e.g. `["foo", "qux", { "bar": "baz" }]` +/// where the first argument is optional and the second argument is the actual configuration object. +/// This type deserializes the array as a tuple `(Option, Option) | (Option)`. +#[derive(Debug, Clone)] +pub struct MixedTupleRuleConfig(pub T1, pub T2); + +impl Default for MixedTupleRuleConfig { + fn default() -> Self { + Self(T1::default(), T2::default()) + } +} + +impl<'de, T1, T2> serde::Deserialize<'de> for MixedTupleRuleConfig +where + T1: serde::de::DeserializeOwned + Default, + T2: serde::de::DeserializeOwned + Default, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::Error; + let value = serde_json::Value::deserialize(deserializer)?; + + if let serde_json::Value::Array(arr) = value { + let config = match arr.len() { + 0 => Self(T1::default(), T2::default()), + 1 => { + // If there's only one element, we need to determine whether it's T1 or T2. + // We can try deserializing it as T2 first, and if that fails, try T1. + let first_value = &arr[0]; + if let Ok(t2) = T2::deserialize(first_value) { + Self(T1::default(), t2) + } else if let Ok(t1) = T1::deserialize(first_value) { + Self(t1, T2::default()) + } else { + return Err(D::Error::custom( + "Expected configuration to match either the first or second tuple type", + )); + } + } + 2 => { + let t1 = T1::deserialize(&arr[0]).map_err(|e| { + D::Error::custom(format!("Error deserializing first tuple element: {e}")) + })?; + let t2 = T2::deserialize(&arr[1]).map_err(|e| { + D::Error::custom(format!("Error deserializing second tuple element: {e}")) + })?; + Self(t1, t2) + } + _ => { + return Err(D::Error::custom( + "Expected at most 2 elements in the configuration array", + )); + } + }; + + Ok(config) + } else if value == serde_json::Value::Null { + // Missing configuration (null) is treated as default (no rule options provided) + Ok(Self(T1::default(), T2::default())) + } else { + Err(D::Error::custom("Expected array for rule configuration")) + } + } +} + +impl JsonSchema for MixedTupleRuleConfig +where + T1: JsonSchema, + T2: JsonSchema, +{ + fn schema_name() -> String { + "MixedTupleRuleConfig".to_string() + } + + fn is_referenceable() -> bool { + false + } + + fn json_schema(r#gen: &mut SchemaGenerator) -> Schema { + Schema::Object(SchemaObject { + subschemas: Some(Box::new(schemars::schema::SubschemaValidation { + any_of: Some(vec![ + SchemaObject { + instance_type: Some(InstanceType::Array.into()), + array: Some(Box::new(schemars::schema::ArrayValidation { + items: Some(schemars::schema::SingleOrVec::Vec(vec![ + r#gen.subschema_for::(), + r#gen.subschema_for::(), + ])), + min_items: Some(2), + max_items: Some(2), + ..Default::default() + })), + ..Default::default() + } + .into(), + r#gen.subschema_for::(), + r#gen.subschema_for::(), + ]), + ..Default::default() + })), + ..Default::default() + }) + } +} + pub trait RuleRunner: Rule { /// `AstType`s that this rule acts on, or `None` if the codegen /// can't figure it out and the linter should call `run` on every node. diff --git a/crates/oxc_linter/src/rules/eslint/func_name_matching.rs b/crates/oxc_linter/src/rules/eslint/func_name_matching.rs index 57fe17b8d0..a268ac4e09 100644 --- a/crates/oxc_linter/src/rules/eslint/func_name_matching.rs +++ b/crates/oxc_linter/src/rules/eslint/func_name_matching.rs @@ -1,8 +1,7 @@ use std::borrow::Cow; use schemars::JsonSchema; -use serde::{Deserialize, Serialize, de}; -use serde_json::Value; +use serde::{Deserialize, Serialize}; use oxc_ast::{ AstKind, @@ -19,7 +18,7 @@ use oxc_syntax::{identifier::is_identifier_name, keyword::is_reserved_keyword}; use crate::{ AstNode, context::LintContext, - rule::{Rule, TupleRuleConfig}, + rule::{MixedTupleRuleConfig, Rule}, }; fn func_name_matching_diagnostic( @@ -68,41 +67,9 @@ struct FuncNameMatchingConfig { include_common_js_module_exports: bool, } -#[derive(Debug, Default, Clone, Serialize, JsonSchema)] +#[derive(Debug, Default, Clone, Deserialize, JsonSchema)] /// This rule takes an optional string of `"always"` or `"never"` (when omitted, it defaults to `"always"`), and an optional options object with two properties `considerPropertyDescriptor` and `includeCommonJSModuleExports`. -pub struct FuncNameMatching(FuncNameMatchingMode, FuncNameMatchingConfig); - -impl<'de> Deserialize<'de> for FuncNameMatching { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let values = Vec::::deserialize(deserializer)?; - let mut mode = FuncNameMatchingMode::Always; - let mut options = FuncNameMatchingConfig::default(); - - match values.as_slice() { - [] => {} - [first] if first.is_string() => { - mode = serde_json::from_value(first.clone()).map_err(de::Error::custom)?; - } - [first] if first.is_object() => { - options = serde_json::from_value(first.clone()).map_err(de::Error::custom)?; - } - [first, second] if first.is_string() && second.is_object() => { - mode = serde_json::from_value(first.clone()).map_err(de::Error::custom)?; - options = serde_json::from_value(second.clone()).map_err(de::Error::custom)?; - } - _ => { - return Err(de::Error::custom( - r#"expected [], ["always"|"never"], [options], or ["always"|"never", options]"#, - )); - } - } - - Ok(Self(mode, options)) - } -} +pub struct FuncNameMatching(MixedTupleRuleConfig); declare_oxc_lint!( /// ### What it does @@ -221,14 +188,16 @@ declare_oxc_lint!( eslint, style, none, - config = FuncNameMatching, + config = MixedTupleRuleConfig, version = "1.62.0", short_description = "Requires function expression names to match the variable or property names they are assigned to, or disallows such matches with `\"never\"`.", ); impl Rule for FuncNameMatching { fn from_configuration(value: serde_json::Value) -> Result { - serde_json::from_value::>(value).map(TupleRuleConfig::into_inner) + serde_json::from_value::>( + value, + ).map(Self) } fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { @@ -250,7 +219,8 @@ impl Rule for FuncNameMatching { return; }; - if !self.1.include_common_js_module_exports && is_module_exports(&assign_expr.left) + if !self.0.1.include_common_js_module_exports + && is_module_exports(&assign_expr.left) { return; } @@ -274,7 +244,7 @@ impl Rule for FuncNameMatching { impl FuncNameMatching { fn should_warn(&self, name: &str, func_name: &str) -> bool { - match self.0 { + match self.0.0 { FuncNameMatchingMode::Always => name != func_name, FuncNameMatchingMode::Never => name == func_name, } @@ -292,7 +262,7 @@ impl FuncNameMatching { name, func_name.name, is_property, - self.0, + self.0.0, func_name.span, )); } @@ -310,7 +280,7 @@ impl FuncNameMatching { if property_key_is_identifier(&property.key) && !property.computed { let Some(property_name) = property.key.static_name() else { return }; - if self.1.consider_property_descriptor && property_name == "value" { + if self.0.1.consider_property_descriptor && property_name == "value" { match property_descriptor_name(node, ctx) { DescriptorName::Name(descriptor_name) => { self.report_if_should_warn( diff --git a/crates/oxc_linter/src/utils/schemars.rs b/crates/oxc_linter/src/utils/schemars.rs index d5dda0c102..0ee3b16c8d 100644 --- a/crates/oxc_linter/src/utils/schemars.rs +++ b/crates/oxc_linter/src/utils/schemars.rs @@ -13,22 +13,21 @@ use crate::rules::RuleEnum; /// These should return the DummyRule struct/schema instead of the actual rule struct/schema, /// until we verify that the rule's schema is valid and can be generated by schemars. #[cfg(feature = "ruledocs")] -const NO_VERIFIED_VALID_SCHEMA: [&str; 16] = [ - "eslint/func-name-matching", // second config can be on first position like [AllowWarnDeny, Config1, Config2] | [AllowWarnDeny, Config1] | [AllowWarnDeny, Config2] +const NO_VERIFIED_VALID_SCHEMA: [&str; 15] = [ "eslint/no-restricted-globals", // uses spread syntax like [AllowWarnDeny, ...Config] "eslint/no-restricted-imports", // uses spread syntax like [AllowWarnDeny, ...Config] "eslint/no-restricted-properties", // uses spread syntax like [AllowWarnDeny, ...Config] - "node/callback-return", // uses array syntax [AllowWarnDeny, string[]] - "import/extensions", // second config can be on first position like[AllowWarnDeny, Config1, Config2] | [AllowWarnDeny, Config1] | [AllowWarnDeny, Config2] - "jest/prefer-lowercase-title", // has options from other rule #23186 - "jest/valid-title", // has options from other rule #23186 + "node/callback-return", // uses array syntax [AllowWarnDeny, string[]] + "jest/prefer-lowercase-title", // has options from other rule #23186 + "jest/valid-title", // has options from other rule #23186 "vitest/prefer-lowercase-title", // has options from other rule #23186 - "vitest/valid-title", // has options from other rule #23186 - "jsdoc/require-param", // missing options #23356 - "unicorn/filename-case", // missing options #23248 + "vitest/valid-title", // has options from other rule #23186 + "jsdoc/require-param", // missing options #23356 + "unicorn/filename-case", // missing options #23248 "unicorn/numeric-separators-style", // missing options #23383 "jsx_a11y/no-noninteractive-element-interactions", // TS Generation generates ts 2411 error "eslint/prefer-destructuring", + "import/extensions", "react/jsx-no-script-url", ]; diff --git a/npm/oxlint/configuration_schema.json b/npm/oxlint/configuration_schema.json index b6b46442c0..cec6ef8dfc 100644 --- a/npm/oxlint/configuration_schema.json +++ b/npm/oxlint/configuration_schema.json @@ -2276,24 +2276,34 @@ "$ref": "#/definitions/RuleNoConfig" }, { - "type": "array", - "items": [ + "anyOf": [ { - "$ref": "#/definitions/AllowWarnDeny" - }, - { - "anyOf": [ + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, { "type": "number" + } + ], + "maxItems": 2, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" }, { "$ref": "#/definitions/ComplexityConfig" } - ] + ], + "maxItems": 2, + "minItems": 2 } - ], - "maxItems": 2, - "minItems": 2 + ] } ] }, @@ -2376,7 +2386,57 @@ "$ref": "#/definitions/RuleNoConfig" }, "func-name-matching": { - "$ref": "#/definitions/DummyRule" + "anyOf": [ + { + "$ref": "#/definitions/RuleNoConfig" + }, + { + "anyOf": [ + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, + { + "$ref": "#/definitions/FuncNameMatchingMode" + }, + { + "$ref": "#/definitions/FuncNameMatchingConfig" + } + ], + "maxItems": 3, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, + { + "$ref": "#/definitions/FuncNameMatchingMode" + } + ], + "maxItems": 2, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, + { + "$ref": "#/definitions/FuncNameMatchingConfig" + } + ], + "maxItems": 2, + "minItems": 2 + } + ] + } + ] }, "func-names": { "anyOf": [ @@ -3970,24 +4030,34 @@ "$ref": "#/definitions/RuleNoConfig" }, { - "type": "array", - "items": [ + "anyOf": [ { - "$ref": "#/definitions/AllowWarnDeny" - }, - { - "anyOf": [ + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, { "type": "number" + } + ], + "maxItems": 2, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" }, { "$ref": "#/definitions/MaxClassesPerFileConfig" } - ] + ], + "maxItems": 2, + "minItems": 2 } - ], - "maxItems": 2, - "minItems": 2 + ] } ] }, @@ -3997,24 +4067,34 @@ "$ref": "#/definitions/RuleNoConfig" }, { - "type": "array", - "items": [ + "anyOf": [ { - "$ref": "#/definitions/AllowWarnDeny" - }, - { - "anyOf": [ + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, { "type": "number" + } + ], + "maxItems": 2, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" }, { "$ref": "#/definitions/MaxDepth" } - ] + ], + "maxItems": 2, + "minItems": 2 } - ], - "maxItems": 2, - "minItems": 2 + ] } ] }, @@ -4024,24 +4104,34 @@ "$ref": "#/definitions/RuleNoConfig" }, { - "type": "array", - "items": [ + "anyOf": [ { - "$ref": "#/definitions/AllowWarnDeny" - }, - { - "anyOf": [ + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, { "type": "number" + } + ], + "maxItems": 2, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" }, { "$ref": "#/definitions/MaxLinesConfig" } - ] + ], + "maxItems": 2, + "minItems": 2 } - ], - "maxItems": 2, - "minItems": 2 + ] } ] }, @@ -4051,24 +4141,34 @@ "$ref": "#/definitions/RuleNoConfig" }, { - "type": "array", - "items": [ + "anyOf": [ { - "$ref": "#/definitions/AllowWarnDeny" - }, - { - "anyOf": [ + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, { "type": "number" + } + ], + "maxItems": 2, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" }, { "$ref": "#/definitions/MaxLinesPerFunctionConfig" } - ] + ], + "maxItems": 2, + "minItems": 2 } - ], - "maxItems": 2, - "minItems": 2 + ] } ] }, @@ -4078,24 +4178,34 @@ "$ref": "#/definitions/RuleNoConfig" }, { - "type": "array", - "items": [ + "anyOf": [ { - "$ref": "#/definitions/AllowWarnDeny" - }, - { - "anyOf": [ + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, { "type": "number" + } + ], + "maxItems": 2, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" }, { "$ref": "#/definitions/MaxNestedCallbacks" } - ] + ], + "maxItems": 2, + "minItems": 2 } - ], - "maxItems": 2, - "minItems": 2 + ] } ] }, @@ -4105,24 +4215,34 @@ "$ref": "#/definitions/RuleNoConfig" }, { - "type": "array", - "items": [ + "anyOf": [ { - "$ref": "#/definitions/AllowWarnDeny" - }, - { - "anyOf": [ + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, { "type": "number" + } + ], + "maxItems": 2, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" }, { "$ref": "#/definitions/MaxParamsConfig" } - ] + ], + "maxItems": 2, + "minItems": 2 } - ], - "maxItems": 2, - "minItems": 2 + ] } ] }, @@ -4132,24 +4252,34 @@ "$ref": "#/definitions/RuleNoConfig" }, { - "type": "array", - "items": [ + "anyOf": [ { - "$ref": "#/definitions/AllowWarnDeny" - }, - { - "anyOf": [ + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" + }, { "type": "number" + } + ], + "maxItems": 2, + "minItems": 2 + }, + { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AllowWarnDeny" }, { "$ref": "#/definitions/MaxStatementsConfig" } - ] + ], + "maxItems": 2, + "minItems": 2 } - ], - "maxItems": 2, - "minItems": 2 + ] } ] }, @@ -10671,6 +10801,31 @@ } ] }, + "FuncNameMatchingConfig": { + "type": "object", + "properties": { + "considerPropertyDescriptor": { + "description": "If `considerPropertyDescriptor` is set to `true`, the check will take into account the use of `Object.create`, `Object.defineProperty`, `Object.defineProperties`, and `Reflect.defineProperty`.", + "default": false, + "type": "boolean", + "markdownDescription": "If `considerPropertyDescriptor` is set to `true`, the check will take into account the use of `Object.create`, `Object.defineProperty`, `Object.defineProperties`, and `Reflect.defineProperty`." + }, + "includeCommonJSModuleExports": { + "description": "If `includeCommonJSModuleExports` is set to `true`, `module.exports` and `module[\"exports\"]` will be checked by this rule.", + "default": false, + "type": "boolean", + "markdownDescription": "If `includeCommonJSModuleExports` is set to `true`, `module.exports` and `module[\"exports\"]` will be checked by this rule." + } + }, + "additionalProperties": false + }, + "FuncNameMatchingMode": { + "type": "string", + "enum": [ + "always", + "never" + ] + }, "FuncNames": { "type": "array", "items": [