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
49 changes: 12 additions & 37 deletions crates/oxc_linter/src/rules/eslint/prefer_destructuring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use oxc_ast::{
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{AstNode, context::LintContext, rule::Rule};
Expand All @@ -21,7 +23,8 @@ fn prefer_array_destructuring(span: Span) -> OxcDiagnostic {
.with_label(span)
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, JsonSchema, Deserialize, Serialize)]
#[serde(rename_all = "camelCase", default)]
struct Config {
array: bool,
object: bool,
Expand All @@ -33,10 +36,16 @@ impl Default for Config {
}
}

#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, JsonSchema, Deserialize, Serialize)]
#[serde(rename_all = "camelCase", default)]
pub struct PreferDestructuring {
/// Configuration for destructuring in variable declarations, configured for arrays and objects independently.
#[serde(rename = "VariableDeclarator")]
variable_declarator: Config,
/// Configuration for destructuring in assignment expressions, configured for arrays and objects independently.
#[serde(rename = "AssignmentExpression")]
assignment_expression: Config,
/// Determines whether the object destructuring rule applies to renamed variables.
enforce_for_renamed_properties: bool,
}

Expand Down Expand Up @@ -74,45 +83,11 @@ declare_oxc_lint!(
/// const { baz } = object;
/// const obj = object.bar;
/// ```
///
/// ### Options
///
/// This rule takes two arguments, both of which are objects.
/// The first object parameter determines what types of destructuring the rule applies to.
/// In the first object, there are two properties, array and object,
/// that can be used to turn on or off the destructuring requirement for each of those types independently.
/// By default, both are true.
///
/// ```json
/// {
/// "prefer-destructuring": ["error", { "array": true, "object": true }]
/// }
/// ```
///
/// Alternatively, you can use separate configurations for different assignment types.
/// The first argument accepts two other keys instead of array and object.
/// One key is VariableDeclarator and the other is AssignmentExpression,
/// which can be used to control the destructuring requirement for each of those types independently
///
/// ```json
/// {
/// "prefer-destructuring": ["error", { "VariableDeclarator": { "array": true, "object": true }, "AssignmentExpression": { "array": true, "object": true } }]
/// }
/// ```
///
/// #### enforceForRenamedProperties
/// The rule has a second object argument with a single key,
/// enforceForRenamedProperties, which determines whether the object destructuring applies to renamed variables.
///
/// ```json
/// {
/// "prefer-destructuring": ["error", { "array": true, "object": true }, { "enforceForRenamedProperties": true }]
/// }
/// ```
PreferDestructuring,
eslint,
style,
pending,
config = PreferDestructuring,
);

impl Rule for PreferDestructuring {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use oxc_ast::{AstKind, ast::JSXAttributeValue};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{CompactStr, GetSpan, Span};
use schemars::JsonSchema;

use crate::{
AstNode,
Expand All @@ -26,9 +27,12 @@ fn miss_on_blur(span: Span, attr_name: &str) -> OxcDiagnostic {
#[derive(Debug, Default, Clone)]
pub struct MouseEventsHaveKeyEvents(Box<MouseEventsHaveKeyEventsConfig>);

#[derive(Debug, Clone)]
#[derive(Debug, Clone, JsonSchema)]
#[serde(rename_all = "camelCase", default)]
pub struct MouseEventsHaveKeyEventsConfig {
/// List of hover-in mouse event handlers that require corresponding keyboard event handlers.
hover_in_handlers: Vec<CompactStr>,
/// List of hover-out mouse event handlers that require corresponding keyboard event handlers.
hover_out_handlers: Vec<CompactStr>,
}

Expand All @@ -44,12 +48,12 @@ impl Default for MouseEventsHaveKeyEventsConfig {
declare_oxc_lint!(
/// ### What it does
///
/// Enforce onmouseover/onmouseout are accompanied by onfocus/onblur.
/// Enforce onMouseOver/onMouseOut are accompanied by onFocus/onBlur.
///
/// ### Why is this bad?
///
/// Coding for the keyboard is important for users with physical disabilities who cannot use a mouse,
/// AT compatibility, and screenreader users.
/// AT compatibility, and screen reader users.
///
/// ### Examples
///
Expand All @@ -64,7 +68,8 @@ declare_oxc_lint!(
/// ```
MouseEventsHaveKeyEvents,
jsx_a11y,
correctness
correctness,
config = MouseEventsHaveKeyEventsConfig,
);

impl Rule for MouseEventsHaveKeyEvents {
Expand Down
17 changes: 14 additions & 3 deletions crates/oxc_linter/src/rules/react/jsx_no_target_blank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use oxc_ast::{
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{CompactStr, GetSpan, Span};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::{
AstNode,
Expand All @@ -35,17 +37,25 @@ fn explicit_props_in_spread_attributes(span: Span) -> OxcDiagnostic {
.with_label(span)
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, JsonSchema, Deserialize, Serialize)]
#[serde(rename_all = "camelCase", default)]
pub struct JsxNoTargetBlank {
/// Whether to enforce dynamic links or enforce static links.
enforce_dynamic_links: EnforceDynamicLinksEnum,
/// Whether to warn when spread attributes are used.
warn_on_spread_attributes: bool,
/// Whether to allow referrers.
allow_referrer: bool,
/// Whether to check link elements.
links: bool,
/// Whether to check form elements.
forms: bool,
}

#[derive(Debug, Clone)]
#[derive(Debug, Default, Clone, JsonSchema, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
enum EnforceDynamicLinksEnum {
#[default]
Always,
Never,
}
Expand Down Expand Up @@ -129,7 +139,8 @@ declare_oxc_lint!(
/// [`noopener` docs]: https://html.spec.whatwg.org/multipage/links.html#link-type-noopener
JsxNoTargetBlank,
react,
correctness
correctness,
config = JsxNoTargetBlank,
);

impl Rule for JsxNoTargetBlank {
Expand Down
96 changes: 23 additions & 73 deletions crates/oxc_linter/src/rules/react/only_export_components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use oxc_macros::declare_oxc_lint;
use oxc_semantic::NodeId;
use oxc_span::{GetSpan, Span};
use rustc_hash::FxHashSet;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::{context::LintContext, rule::Rule};
Expand Down Expand Up @@ -67,14 +68,33 @@ pub struct OnlyExportComponentsConfig {
check_js: bool,
}

#[derive(Debug, Deserialize, Serialize)]
// NOTE: Ensure this is always kept in sync with OnlyExportComponentsConfig
#[derive(Debug, Default, Deserialize, Serialize, JsonSchema)]
#[serde(default)]
struct OnlyExportComponentsOptionsJson {
/// Treat specific named exports as HMR-safe (useful for frameworks that hot-replace
/// certain exports). For example, in Remix:
/// `{ "allowExportNames": ["meta", "links", "headers", "loader", "action"] }`
#[serde(rename = "allowExportNames")]
allow_export_names: Option<Vec<String>>,
/// Allow exporting primitive constants (string/number/boolean/template literal)
/// alongside component exports without triggering a violation. Recommended when your
/// bundler’s Fast Refresh integration supports this (enabled by the plugin’s `vite`
/// preset).
///
/// ```jsx
/// // Allowed when allowConstantExport: true
/// export const VERSION = "3";
/// export const Foo = () => null;
/// ```
#[serde(rename = "allowConstantExport")]
allow_constant_export: Option<bool>,
/// If you export components wrapped in custom higher-order components, list their
/// identifiers here to avoid false positives.
#[serde(rename = "customHOCs")]
custom_hocs: Option<Vec<String>>,
/// Check `.js` files that contain JSX (in addition to `.tsx`/`.jsx`). To reduce
/// false positives, only files that import React are checked when this is enabled.
#[serde(rename = "checkJS")]
check_js: Option<bool>,
}
Expand Down Expand Up @@ -153,80 +173,10 @@ declare_oxc_lint!(
/// import { App } from "./App";
/// createRoot(document.getElementById("root")).render(<App />);
/// ```
///
/// ### Options (or not)
///
/// #### allowExportNames
///
/// `{ type: string[], default: [] }`
///
/// Treat specific named exports as HMR-safe (useful for frameworks that hot-replace
/// certain exports). For example, in Remix:
///
/// ```json
/// {
/// "react/only-export-components": [
/// "error",
/// { "allowExportNames": ["meta", "links", "headers", "loader", "action"] }
/// ]
/// }
/// ```
///
/// #### allowConstantExport
///
/// `{ type: boolean, default: false }`
///
/// Allow exporting primitive constants (string/number/boolean/template literal)
/// alongside component exports without triggering a violation. Recommended when your
/// bundler’s Fast Refresh integration supports this (enabled by the plugin’s `vite`
/// preset).
///
/// ```json
/// {
/// "react/only-export-components": [
/// "error",
/// { "allowConstantExport": true }
/// ]
/// }
/// ```
///
/// ```jsx
/// // Allowed when allowConstantExport: true
/// export const VERSION = "3";
/// export const Foo = () => null;
/// ```
///
/// #### customHOCs
///
/// `{ type: string[], default: [] }`
///
/// If you export components wrapped in custom higher-order components, list their
/// identifiers here to avoid false positives:
///
/// ```json
/// {
/// "react/only-export-components": [
/// "error",
/// { "customHOCs": ["observer", "withAuth"] }
/// ]
/// }
/// ```
///
/// #### checkJS
///
/// `{ type: boolean, default: false }`
///
/// Check `.js` files that contain JSX (in addition to `.tsx`/`.jsx`). To reduce
/// false positives, only files that import React are checked when this is enabled.
///
/// ```json
/// {
/// "react/only-export-components": ["error", { "checkJS": true }]
/// }
/// ```
OnlyExportComponents,
react,
restriction
restriction,
config = OnlyExportComponentsOptionsJson,
);

static DEFAULT_REACT_HOCS: &[&str] = &["memo", "forwardRef"];
Expand Down
Loading