diff --git a/Cargo.lock b/Cargo.lock index fdbf6286dd174..4e5d5417394a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,6 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -192,6 +193,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.6.0" @@ -388,6 +395,29 @@ dependencies = [ "typenum", ] +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "ctor" version = "0.2.8" @@ -440,6 +470,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.10.7" @@ -450,6 +491,21 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + [[package]] name = "dunce" version = "1.0.4" @@ -462,6 +518,12 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +[[package]] +name = "ego-tree" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" + [[package]] name = "either" version = "1.13.0" @@ -559,6 +621,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.30" @@ -648,6 +720,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -658,6 +739,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -762,6 +852,20 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "httparse" version = "1.9.4" @@ -937,7 +1041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -997,6 +1101,35 @@ dependencies = [ "url", ] +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markdown" +version = "1.0.0-alpha.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e61c5c85b392273c4d4ea546e6399ace3e3db172ab01b6de8f3d398d1dbd2ec" +dependencies = [ + "unicode-id", +] + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + [[package]] name = "memchr" version = "2.7.4" @@ -1147,6 +1280,12 @@ dependencies = [ "libloading", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nom" version = "7.1.3" @@ -1437,7 +1576,7 @@ dependencies = [ "oxc_span", "oxc_tasks_common", "oxc_transformer", - "phf", + "phf 0.11.2", "pico-args", "project-root", "rayon", @@ -1525,6 +1664,7 @@ dependencies = [ "json-strip-comments", "language-tags", "lazy_static", + "markdown", "memchr", "mime_guess", "once_cell", @@ -1540,7 +1680,7 @@ dependencies = [ "oxc_semantic", "oxc_span", "oxc_syntax", - "phf", + "phf 0.11.2", "project-root", "rayon", "regex", @@ -1728,7 +1868,7 @@ dependencies = [ "oxc_parser", "oxc_span", "oxc_syntax", - "phf", + "phf 0.11.2", "rustc-hash", "serde", "serde_json", @@ -1773,7 +1913,7 @@ dependencies = [ "oxc_ast_macros", "oxc_index", "oxc_span", - "phf", + "phf 0.11.2", "rustc-hash", "ryu-js", "serde", @@ -1980,6 +2120,15 @@ dependencies = [ "indexmap", ] +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + [[package]] name = "phf" version = "0.11.2" @@ -1987,7 +2136,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_macros", - "phf_shared", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", ] [[package]] @@ -1996,7 +2175,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ - "phf_shared", + "phf_shared 0.11.2", "rand", ] @@ -2006,13 +2185,22 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.2", + "phf_shared 0.11.2", "proc-macro2", "quote", "syn", ] +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "phf_shared" version = "0.11.2" @@ -2066,6 +2254,21 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "prettyplease" version = "0.2.20" @@ -2119,6 +2322,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -2127,6 +2342,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "rayon" @@ -2374,6 +2592,41 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags 2.6.0", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + [[package]] name = "semver" version = "1.0.23" @@ -2463,6 +2716,15 @@ dependencies = [ "syn", ] +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "sha2" version = "0.10.8" @@ -2541,6 +2803,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -2553,6 +2821,32 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9557cb6521e8d009c51a8666f09356f4b817ba9ba0981a305bd86aee47bd35c" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + [[package]] name = "subtle" version = "2.6.1" @@ -2592,6 +2886,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "textwrap" version = "0.16.1" @@ -2879,6 +3184,12 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +[[package]] +name = "unicode-id" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" + [[package]] name = "unicode-id-start" version = "1.2.0" @@ -2953,6 +3264,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "valuable" version = "0.1.0" @@ -3067,10 +3384,16 @@ dependencies = [ "bpaf", "handlebars", "insta", + "markdown", + "oxc_allocator", + "oxc_diagnostics", "oxc_linter", + "oxc_parser", + "oxc_span", "oxlint", "pico-args", "schemars", + "scraper", "serde", "serde_json", ] @@ -3257,6 +3580,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] diff --git a/crates/oxc_linter/Cargo.toml b/crates/oxc_linter/Cargo.toml index fd82b48b5e359..e25ac5120ec00 100644 --- a/crates/oxc_linter/Cargo.toml +++ b/crates/oxc_linter/Cargo.toml @@ -57,3 +57,4 @@ schemars = { workspace = true, features = ["indexmap2"] } static_assertions = { workspace = true } insta = { workspace = true } project-root = { workspace = true } +markdown = { version = "1.0.0-alpha.18" } diff --git a/crates/oxc_linter/src/rule.rs b/crates/oxc_linter/src/rule.rs index 3fb081fb1315d..287bd40a9bfe3 100644 --- a/crates/oxc_linter/src/rule.rs +++ b/crates/oxc_linter/src/rule.rs @@ -235,12 +235,22 @@ impl RuleWithSeverity { #[cfg(test)] mod test { use crate::rules::RULES; + use markdown::{to_html_with_options, Options}; #[test] fn ensure_documentation() { assert!(!RULES.is_empty()); + let options = Options::gfm(); + for rule in RULES.iter() { - assert!(rule.documentation().is_some_and(|s| !s.is_empty()), "{}", rule.name()); + let name = rule.name(); + assert!( + rule.documentation().is_some_and(|s| !s.is_empty()), + "Rule '{name}' is missing documentation." + ); + // will panic if provided invalid markdown + let html = to_html_with_options(rule.documentation().unwrap(), &options).unwrap(); + assert!(!html.is_empty()); } } } diff --git a/crates/oxc_linter/src/rules/eslint/for_direction.rs b/crates/oxc_linter/src/rules/eslint/for_direction.rs index 13dd1219f629a..b227ed8bc716c 100644 --- a/crates/oxc_linter/src/rules/eslint/for_direction.rs +++ b/crates/oxc_linter/src/rules/eslint/for_direction.rs @@ -35,7 +35,7 @@ declare_oxc_lint!( /// ```javascript /// for (var i = 0; i < 10; i--) {} /// - /// for (var = 10; i >= 0; i++) {} + /// for (var i = 10; i >= 0; i++) {} /// ``` ForDirection, correctness, diff --git a/crates/oxc_linter/src/rules/eslint/guard_for_in.rs b/crates/oxc_linter/src/rules/eslint/guard_for_in.rs index 71d33322ee07e..0a487c4c0d233 100644 --- a/crates/oxc_linter/src/rules/eslint/guard_for_in.rs +++ b/crates/oxc_linter/src/rules/eslint/guard_for_in.rs @@ -24,8 +24,8 @@ declare_oxc_lint!( /// ### Example /// ```javascript /// for (key in foo) { - // doSomething(key); - // } + /// doSomething(key); + /// } /// ``` GuardForIn, style diff --git a/crates/oxc_linter/src/rules/eslint/max_lines.rs b/crates/oxc_linter/src/rules/eslint/max_lines.rs index 3159d077ed00c..9aae4a5925380 100644 --- a/crates/oxc_linter/src/rules/eslint/max_lines.rs +++ b/crates/oxc_linter/src/rules/eslint/max_lines.rs @@ -37,16 +37,15 @@ impl Default for MaxLinesConfig { declare_oxc_lint!( /// ### What it does - /// Enforce a maximum number of lines per file + /// Enforce a maximum number of lines per file. /// /// ### Why is this bad? /// - /// Some people consider large files a code smell. Large files tend to do a lot of things and can make it hard following what’s going. - /// While there is not an objective maximum number of lines considered acceptable in a file, most people would agree it should not be in the thousands. Recommendations usually range from 100 to 500 lines. - /// - /// ### Example - /// ```javascript - /// ``` + /// Some people consider large files a code smell. Large files tend to do a + /// lot of things and can make it hard following what’s going. While there + /// is not an objective maximum number of lines considered acceptable in a + /// file, most people would agree it should not be in the thousands. + /// Recommendations usually range from 100 to 500 lines. MaxLines, pedantic ); diff --git a/crates/oxc_linter/src/rules/eslint/no_await_in_loop.rs b/crates/oxc_linter/src/rules/eslint/no_await_in_loop.rs index e2622c5c0195b..b142dd6ab966b 100644 --- a/crates/oxc_linter/src/rules/eslint/no_await_in_loop.rs +++ b/crates/oxc_linter/src/rules/eslint/no_await_in_loop.rs @@ -18,7 +18,7 @@ pub struct NoAwaitInLoop; declare_oxc_lint!( /// ### What it does /// - /// This rule disallows the use of await within loop bodies. (for, for-in, for-of, while, do-while). + /// This rule disallows the use of `await` within loop bodies. (for, for-in, for-of, while, do-while). /// /// ### Why is this bad? /// @@ -28,14 +28,18 @@ declare_oxc_lint!( /// ### Example /// Bad: /// ```javascript - /// for (const user of users) { - /// const userRecord = await getUserRecord(user); + /// async function bad() { + /// for (const user of users) { + /// const userRecord = await getUserRecord(user); + /// } /// } /// ``` /// /// Good: /// ```javascript - /// await Promise.all(users.map(user => getUserRecord(user))); + /// async function good() { + /// await Promise.all(users.map(user => getUserRecord(user))); + /// } /// ``` NoAwaitInLoop, perf diff --git a/crates/oxc_linter/src/rules/eslint/no_case_declarations.rs b/crates/oxc_linter/src/rules/eslint/no_case_declarations.rs index d654c7f24f8e7..b2ad9e9792746 100644 --- a/crates/oxc_linter/src/rules/eslint/no_case_declarations.rs +++ b/crates/oxc_linter/src/rules/eslint/no_case_declarations.rs @@ -26,19 +26,19 @@ declare_oxc_lint!( /// /// ### Example /// ```javascript - // switch (foo) { - // case 1: - // let x = 1; - // break; - // case 2: - // const y = 2; - // break; - // case 3: - // function f() {} - // break; - // default: - // class C {} - // } + /// switch (foo) { + /// case 1: + /// let x = 1; + /// break; + /// case 2: + /// const y = 2; + /// break; + /// case 3: + /// function f() {} + /// break; + /// default: + /// class C {} + /// } /// ``` NoCaseDeclarations, pedantic diff --git a/crates/oxc_linter/src/rules/eslint/no_cond_assign.rs b/crates/oxc_linter/src/rules/eslint/no_cond_assign.rs index 8a649b3d638cc..ea35fa436ad9d 100644 --- a/crates/oxc_linter/src/rules/eslint/no_cond_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_cond_assign.rs @@ -29,12 +29,24 @@ enum NoCondAssignConfig { declare_oxc_lint!( /// ### What it does /// + /// Disallow assignment operators in conditional expressions /// /// ### Why is this bad? /// + /// In conditional statements, it is very easy to mistype a comparison + /// operator (such as `==`) as an assignment operator (such as `=`). + /// + /// There are valid reasons to use assignment operators in conditional + /// statements. However, it can be difficult to tell whether a specific + /// assignment was intentional. /// /// ### Example - /// ```javascript + /// + /// ```js + /// // Check the user's job title + /// if (user.jobTitle = "manager") { + /// // user.jobTitle is now incorrect + /// } /// ``` NoCondAssign, correctness diff --git a/crates/oxc_linter/src/rules/eslint/no_continue.rs b/crates/oxc_linter/src/rules/eslint/no_continue.rs index dcca60785e98d..4c41048972703 100644 --- a/crates/oxc_linter/src/rules/eslint/no_continue.rs +++ b/crates/oxc_linter/src/rules/eslint/no_continue.rs @@ -24,15 +24,15 @@ declare_oxc_lint!( /// ### Example /// ```javascript /// var sum = 0, - // i; - // - // for(i = 0; i < 10; i++) { - // if(i >= 5) { - // continue; - // } - // - // sum += i; - // } + /// i; + /// + /// for(i = 0; i < 10; i++) { + /// if(i >= 5) { + /// continue; + /// } + /// + /// sum += i; + /// } /// ``` NoContinue, style diff --git a/crates/oxc_linter/src/rules/eslint/no_debugger.rs b/crates/oxc_linter/src/rules/eslint/no_debugger.rs index af14da3d0fe3c..d61b7a5f24be2 100644 --- a/crates/oxc_linter/src/rules/eslint/no_debugger.rs +++ b/crates/oxc_linter/src/rules/eslint/no_debugger.rs @@ -21,10 +21,13 @@ declare_oxc_lint!( /// They're most commonly an accidental debugging leftover. /// /// ### Example + /// /// ```javascript - /// const data = await getData(); - /// const result = complexCalculation(data); - /// debugger; + /// async function main() { + /// const data = await getData(); + /// const result = complexCalculation(data); + /// debugger; + /// } /// ``` NoDebugger, correctness, diff --git a/crates/oxc_linter/src/rules/eslint/no_ex_assign.rs b/crates/oxc_linter/src/rules/eslint/no_ex_assign.rs index 8ed18e65692c6..5629ceaeb2389 100644 --- a/crates/oxc_linter/src/rules/eslint/no_ex_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_ex_assign.rs @@ -25,11 +25,11 @@ declare_oxc_lint!( /// /// ### Example /// ```javascript - // try { - // // code - // } catch (e) { - // e = 10; - // } + /// try { + /// // code + /// } catch (e) { + /// e = 10; + /// } /// ``` NoExAssign, correctness diff --git a/crates/oxc_linter/src/rules/eslint/no_undefined.rs b/crates/oxc_linter/src/rules/eslint/no_undefined.rs index 213fcd6021ddd..ea860a512d45d 100644 --- a/crates/oxc_linter/src/rules/eslint/no_undefined.rs +++ b/crates/oxc_linter/src/rules/eslint/no_undefined.rs @@ -29,15 +29,14 @@ declare_oxc_lint!( /// var undefined = "foo"; /// /// if (foo === undefined) { - /// ... + /// // ... /// } /// /// function baz(undefined) { - /// ... + /// // ... /// } /// /// bar(undefined, "lorem"); - /// /// ``` /// /// ### Example of good code @@ -47,7 +46,7 @@ declare_oxc_lint!( /// var Undefined = "foo"; /// /// if (typeof foo === "undefined") { - /// ... + /// // ... /// } /// /// global.undefined = "foo"; diff --git a/crates/oxc_linter/src/rules/eslint/no_useless_escape.rs b/crates/oxc_linter/src/rules/eslint/no_useless_escape.rs index ffda849250af2..1d9bc5a978b3d 100644 --- a/crates/oxc_linter/src/rules/eslint/no_useless_escape.rs +++ b/crates/oxc_linter/src/rules/eslint/no_useless_escape.rs @@ -23,7 +23,45 @@ declare_oxc_lint!( /// /// /// ### Example + /// + /// Examples of **incorrect** code for this rule: + /// + /// ```javascript + /// /*eslint no-useless-escape: "error"*/ + /// + /// "\'"; + /// '\"'; + /// "\#"; + /// "\e"; + /// `\"`; + /// `\"${foo}\"`; + /// `\#{foo}`; + /// /\!/; + /// /\@/; + /// /[\[]/; + /// /[a-z\-]/; + /// ``` + /// + /// Examples of **correct** code for this rule: + /// /// ```javascript + /// /*eslint no-useless-escape: "error"*/ + /// + /// "\""; + /// '\''; + /// "\x12"; + /// "\u00a9"; + /// "\371"; + /// "xs\u2111"; + /// `\``; + /// `\${${foo}}`; + /// `$\{${foo}}`; + /// /\\/g; + /// /\t/g; + /// /\w\$\*\^\./; + /// /[[]/; + /// /[\]]/; + /// /[a-z-]/; /// ``` NoUselessEscape, correctness, diff --git a/crates/oxc_linter/src/rules/eslint/no_void.rs b/crates/oxc_linter/src/rules/eslint/no_void.rs index 0785114107417..931c20891dab7 100644 --- a/crates/oxc_linter/src/rules/eslint/no_void.rs +++ b/crates/oxc_linter/src/rules/eslint/no_void.rs @@ -30,9 +30,9 @@ declare_oxc_lint!( /// var foo = void 0; /// /// // success - /// "var foo = bar()", - /// "foo.void()", - /// "foo.void = bar", + /// "var foo = bar()"; + /// "foo.void()"; + /// "foo.void = bar"; /// ``` NoVoid, restriction, diff --git a/crates/oxc_linter/src/rules/eslint/unicode_bom.rs b/crates/oxc_linter/src/rules/eslint/unicode_bom.rs index d0d7596f361bf..a8591fef24750 100644 --- a/crates/oxc_linter/src/rules/eslint/unicode_bom.rs +++ b/crates/oxc_linter/src/rules/eslint/unicode_bom.rs @@ -36,7 +36,7 @@ declare_oxc_lint!( /// /// ### Example /// ```javascript - /// var a = 123;" + /// var a = 123; /// ``` UnicodeBom, restriction, diff --git a/crates/oxc_linter/src/rules/import/named.rs b/crates/oxc_linter/src/rules/import/named.rs index 6142745b4497c..9ae1dd0c19134 100644 --- a/crates/oxc_linter/src/rules/import/named.rs +++ b/crates/oxc_linter/src/rules/import/named.rs @@ -18,10 +18,55 @@ pub struct Named; declare_oxc_lint!( /// ### What it does /// + /// Verifies that all named imports are part of the set of named exports in + /// the referenced module. + /// + /// For `export`, verifies that all named exports exist in the referenced + /// module. + /// + /// Note: for packages, the plugin will find exported names from + /// `jsnext:main` (deprecated) or `module`, if present in `package.json`. + /// Redux's npm module includes this key, and thereby is lintable, for + /// example. + /// + /// A module path that is ignored or not unambiguously an ES module will not + /// be reported when imported. Note that type imports and exports, as used + /// by Flow, are always ignored. + /// /// ### Why is this bad? /// /// ### Example - /// ```javascript + /// Given + /// ```js + /// // ./foo.js + /// export const foo = "I'm so foo" + /// ``` + /// + /// The following is considered valid: + /// + /// ```js + /// // ./bar.js + /// import { foo } from './foo' + /// + /// // ES7 proposal + /// export { foo as bar } from './foo' + /// + /// // node_modules without jsnext:main are not analyzed by default + /// // (import/ignore setting) + /// import { SomeNonsenseThatDoesntExist } from 'react' + /// ``` + /// + /// ...and the following are reported: + /// + /// ```js + /// // ./baz.js + /// import { notFoo } from './foo' + /// + /// // ES7 proposal + /// export { notFoo as defNotBar } from './foo' + /// + /// // will follow 'jsnext:main', if available + /// import { dontCreateStore } from 'redux' /// ``` Named, correctness diff --git a/crates/oxc_linter/src/rules/jest/no_conditional_expect.rs b/crates/oxc_linter/src/rules/jest/no_conditional_expect.rs index 7d4427f4900b4..e6e028b883569 100644 --- a/crates/oxc_linter/src/rules/jest/no_conditional_expect.rs +++ b/crates/oxc_linter/src/rules/jest/no_conditional_expect.rs @@ -47,8 +47,8 @@ declare_oxc_lint!( /// }); /// /// it('throws an error', async () => { - // await foo().catch(error => expect(error).toBeInstanceOf(error)); - // }); + /// await foo().catch(error => expect(error).toBeInstanceOf(error)); + /// }); /// ``` /// /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-conditional-expect.md), diff --git a/crates/oxc_linter/src/rules/jest/no_restricted_matchers.rs b/crates/oxc_linter/src/rules/jest/no_restricted_matchers.rs index 893478c7c40d7..a66aac45882fb 100644 --- a/crates/oxc_linter/src/rules/jest/no_restricted_matchers.rs +++ b/crates/oxc_linter/src/rules/jest/no_restricted_matchers.rs @@ -53,7 +53,7 @@ declare_oxc_lint!( /// ```javascript /// /// it('is false', () => { - /// if this has a modifier (i.e. `not.toBeFalsy`), it would be considered fine + /// // if this has a modifier (i.e. `not.toBeFalsy`), it would be considered fine /// expect(a).toBeFalsy(); /// }); /// @@ -68,6 +68,7 @@ declare_oxc_lint!( /// expect(uploadFileMock).not.toHaveBeenCalledWith('file.name'); /// }); /// }); + /// ``` /// NoRestrictedMatchers, style, diff --git a/crates/oxc_linter/src/rules/jest/no_test_return_statement.rs b/crates/oxc_linter/src/rules/jest/no_test_return_statement.rs index e76130faf9235..b9ea8f912b683 100644 --- a/crates/oxc_linter/src/rules/jest/no_test_return_statement.rs +++ b/crates/oxc_linter/src/rules/jest/no_test_return_statement.rs @@ -34,6 +34,9 @@ declare_oxc_lint!( /// /// ### Example /// ```javascript + /// test('one', () => { + /// return expect(1).toBe(1); + /// }); /// ``` NoTestReturnStatement, style, diff --git a/crates/oxc_linter/src/rules/jest/require_top_level_describe.rs b/crates/oxc_linter/src/rules/jest/require_top_level_describe.rs index a80c2b6cc1d91..432baf458d3b2 100644 --- a/crates/oxc_linter/src/rules/jest/require_top_level_describe.rs +++ b/crates/oxc_linter/src/rules/jest/require_top_level_describe.rs @@ -57,20 +57,24 @@ declare_oxc_lint!( /// /// ```javascript /// // invalid - /// Above a describe block + /// + /// // Above a describe block /// test('my test', () => {}); /// describe('test suite', () => { /// it('test', () => {}); /// }); + /// /// // Below a describe block /// describe('test suite', () => {}); /// test('my test', () => {}); + /// /// // Same for hooks /// beforeAll('my beforeAll', () => {}); /// describe('test suite', () => {}); /// afterEach('my afterEach', () => {}); /// /// //valid + /// /// // Above a describe block /// // In a describe block /// describe('test suite', () => { @@ -80,9 +84,9 @@ declare_oxc_lint!( /// // In a nested describe block /// describe('test suite', () => { /// test('my test', () => {}); - /// describe('another test suite', () => { - /// test('my other test', () => {}); - /// }); + /// describe('another test suite', () => { + /// test('my other test', () => {}); + /// }); /// }); /// ``` /// diff --git a/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs b/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs index 27b6544d85d12..6d65d68b917a9 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs @@ -119,12 +119,15 @@ declare_oxc_lint!( /// text that describes the element's content or purpose. /// /// ### Example - /// ```javascript - /// // Bad - /// /// - /// // Good - /// A close-up of a white daisy + /// Examples of **incorrect** code for this rule: + /// ```jsx + /// A close-up of a white daisy + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```jsx + /// /// ``` AltText, correctness diff --git a/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs b/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs index 5818637998967..bad859069fb99 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs @@ -57,9 +57,11 @@ declare_oxc_lint!( /// Consider the following: /// /// ```jsx - /// Perform action - /// Perform action - /// Perform action + /// <> + /// Perform action + /// Perform action + /// Perform action + /// /// ```` /// /// All these anchor implementations indicate that the element is only used to execute JavaScript code. All the above should be replaced with: @@ -79,19 +81,23 @@ declare_oxc_lint!( /// #### Valid /// /// ```jsx - /// navigate here - /// navigate here - /// navigate here + /// <> + /// navigate here + /// navigate here + /// navigate here + /// /// ``` /// /// #### Invalid /// /// ```jsx - /// navigate here - /// navigate here - /// navigate here - /// navigate here - /// navigate here + /// <> + /// navigate here + /// navigate here + /// navigate here + /// navigate here + /// navigate here + /// /// ``` /// /// ### Reference diff --git a/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs b/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs index 5d7962c3d8f62..0ccaef174e63a 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs @@ -32,25 +32,25 @@ declare_oxc_lint!( /// /// ### Example /// ```jsx - /// // Good - /// - /// - /// - /// - ///
- /// - ///
- ///
- ///
- ///
- ///
- ///
- /// - /// - /// + /// const Good = <> + /// + /// + /// + /// + ///
+ /// + ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// + /// + /// + /// /// - /// // Bad - ///
+ /// const Bad =
/// ``` AriaActivedescendantHasTabindex, correctness diff --git a/crates/oxc_linter/src/rules/jsx_a11y/aria_props.rs b/crates/oxc_linter/src/rules/jsx_a11y/aria_props.rs index f11b525d75550..de5256653031f 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/aria_props.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/aria_props.rs @@ -33,11 +33,13 @@ declare_oxc_lint!( /// This rule includes fixes for some common typos. /// /// ### Example - /// ```javascript - /// // Bad + /// Examples of **incorrect** code for this rule: + /// ```jsx /// + /// ``` /// - /// // Good + /// Examples of **correct** code for this rule: + /// ```jsx /// /// ``` AriaProps, diff --git a/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs b/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs index 2efa65b987a7d..1cdc0145707cb 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs @@ -39,23 +39,40 @@ impl std::ops::Deref for AriaRole { declare_oxc_lint!( /// ### What it does - /// Elements with ARIA roles must use a valid, non-abstract ARIA role. A reference to role definitions can be found at [WAI-ARIA](https://www.w3.org/TR/wai-aria/#role_definitions) site. - + /// + /// Elements with ARIA roles must use a valid, non-abstract ARIA role. A + /// reference to role definitions can be found at + /// [WAI-ARIA](https://www.w3.org/TR/wai-aria/#role_definitions) site. + /// /// /// ### Why is this bad? - /// The intent of this Success Criterion is to ensure that Assistive Technologies (AT) can gather information about, - /// activate (or set) and keep up to date on the status of user interface controls in the content(such as screen readers, screen magnifiers, and speech recognition software, used by people with disabilities). /// - /// When standard controls from accessible technologies are used, this process is straightforward. If the user interface elements are used according to specification the conditions of this provision will be met. + /// The intent of this Success Criterion is to ensure that Assistive + /// Technologies (AT) can gather information about, activate (or set) and + /// keep up to date on the status of user interface controls in the + /// content(such as screen readers, screen magnifiers, and speech + /// recognition software, used by people with disabilities). /// - /// If custom controls are created, however, or interface elements are programmed (in code or script) to have a different role and/or function than usual, - /// then additional measures need to be taken to ensure that the controls provide important information to assistive technologies and allow themselves to be controlled by assistive technologies. - /// A particularly important state of a user interface control is whether or not it has focus. The focus state of a control can be programmatically determined, and notifications about change of focus are sent to user agents and assistive technology. - /// Other examples of user interface control state are whether or not a checkbox or radio button has been selected, or whether or not a collapsible tree or list node is expanded or collapsed. + /// When standard controls from accessible technologies are used, this + /// process is straightforward. If the user interface elements are used + /// according to specification the conditions of this provision will be met. + /// + /// If custom controls are created, however, or interface elements are + /// programmed (in code or script) to have a different role and/or function + /// than usual, then additional measures need to be taken to ensure that the + /// controls provide important information to assistive technologies and + /// allow themselves to be controlled by assistive technologies. A + /// particularly important state of a user interface control is whether or + /// not it has focus. The focus state of a control can be programmatically + /// determined, and notifications about change of focus are sent to user + /// agents and assistive technology. Other examples of user interface + /// control state are whether or not a checkbox or radio button has been + /// selected, or whether or not a collapsible tree or list node is expanded + /// or collapsed. /// /// ### Rule options /// This rule takes one optional object argument of type object: - /// ``` + /// ```json /// { /// "rules": { /// "jsx-a11y/aria-role": [ 2, { @@ -65,26 +82,31 @@ declare_oxc_lint!( /// } /// } /// ``` - /// allowedInvalidRules is an optional string array of custom roles that should be allowed in addition to the ARIA spec, such as for cases when you need to use a non-standard role. + /// `allowedInvalidRules` is an optional string array of custom roles that + /// should be allowed in addition to the ARIA spec, such as for cases when + /// you need to use a non-standard role. /// - /// For the ignoreNonDOM option, this determines if developer created components are checked. + /// For the `ignoreNonDOM` option, this determines if developer created + /// components are checked. /// /// ### Example - /// // good - /// ```javascript + /// + /// Examples of **incorrect** code for this rule: + /// + /// ```jsx + ///
+ ///
+ ///
+ /// + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```jsx ///
///
///
/// /// ``` - /// - /// // bad - /// ```javascript - ///
- ///
- ///
- /// - /// ``` AriaRole, correctness ); diff --git a/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs b/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs index 04423446950a7..70a8169362946 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs @@ -32,7 +32,7 @@ declare_oxc_lint!( /// Incorrectly using the autocomplete attribute may decrease the accessibility of the website for users. /// /// ### Example - /// ```javascript + /// ```jsx /// // Bad /// /// diff --git a/crates/oxc_linter/src/rules/jsx_a11y/heading_has_content.rs b/crates/oxc_linter/src/rules/jsx_a11y/heading_has_content.rs index 6d07561ecca2c..ba1ac9c040c23 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/heading_has_content.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/heading_has_content.rs @@ -49,7 +49,7 @@ declare_oxc_lint!( /// from accessing information on the page's structure. /// /// ### Example - /// ```javascript + /// ```jsx /// // Bad ///

/// diff --git a/crates/oxc_linter/src/rules/jsx_a11y/html_has_lang.rs b/crates/oxc_linter/src/rules/jsx_a11y/html_has_lang.rs index f4812f6c50f66..ed4612045f0e2 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/html_has_lang.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/html_has_lang.rs @@ -41,7 +41,7 @@ declare_oxc_lint!( /// /// /// ### Example - /// ```javascript + /// ```jsx /// // Bad /// /// diff --git a/crates/oxc_linter/src/rules/jsx_a11y/iframe_has_title.rs b/crates/oxc_linter/src/rules/jsx_a11y/iframe_has_title.rs index 23833b414cde9..3564d49898bb1 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/iframe_has_title.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/iframe_has_title.rs @@ -37,7 +37,7 @@ declare_oxc_lint!( /// This rule checks for title property on iframe element. /// /// ### Example - /// ```javascript + /// ```jsx /// // Bad ///