test(linter): ensure rule docs have valid syntax (#4644)

Adds tests for rule documentation by
1. Compiling doc markdown into HTML, which ensures docs use valid markdown syntax
2. Converts the generated HTML into JSX and parses the results with the parser, ensuring the generated HTML is valid

Has the added benefit of adding a lot of JSX test cases to the parser. I've also fixed all violations for these tests in this PR.
This commit is contained in:
DonIsaac 2024-08-10 05:03:09 +00:00
parent b3c3125138
commit 8f2a566f9f
112 changed files with 1193 additions and 343 deletions

342
Cargo.lock generated
View file

@ -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",
]

View file

@ -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" }

View file

@ -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());
}
}
}

View file

@ -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,

View file

@ -24,8 +24,8 @@ declare_oxc_lint!(
/// ### Example
/// ```javascript
/// for (key in foo) {
// doSomething(key);
// }
/// doSomething(key);
/// }
/// ```
GuardForIn,
style

View file

@ -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 whats 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 whats 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
);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -25,11 +25,11 @@ declare_oxc_lint!(
///
/// ### Example
/// ```javascript
// try {
// // code
// } catch (e) {
// e = 10;
// }
/// try {
/// // code
/// } catch (e) {
/// e = 10;
/// }
/// ```
NoExAssign,
correctness

View file

@ -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";

View file

@ -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,

View file

@ -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,

View file

@ -36,7 +36,7 @@ declare_oxc_lint!(
///
/// ### Example
/// ```javascript
/// var a = 123;"
/// var a = 123;
/// ```
UnicodeBom,
restriction,

View file

@ -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

View file

@ -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),

View file

@ -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,

View file

@ -34,6 +34,9 @@ declare_oxc_lint!(
///
/// ### Example
/// ```javascript
/// test('one', () => {
/// return expect(1).toBe(1);
/// });
/// ```
NoTestReturnStatement,
style,

View file

@ -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', () => {});
/// });
/// });
/// ```
///

View file

@ -119,12 +119,15 @@ declare_oxc_lint!(
/// text that describes the element's content or purpose.
///
/// ### Example
/// ```javascript
/// // Bad
/// <img src="flower.jpg">
///
/// // Good
/// <img src="flower.jpg" alt="A close-up of a white daisy">
/// Examples of **incorrect** code for this rule:
/// ```jsx
/// <img src="flower.jpg" alt="A close-up of a white daisy" />
/// ```
///
/// Examples of **correct** code for this rule:
/// ```jsx
/// <img src="flower.jpg" />
/// ```
AltText,
correctness

View file

@ -57,9 +57,11 @@ declare_oxc_lint!(
/// Consider the following:
///
/// ```jsx
/// <a href="javascript:void(0)" onClick={foo}>Perform action</a>
/// <a href="#" onClick={foo}>Perform action</a>
/// <a onClick={foo}>Perform action</a>
/// <>
/// <a href="javascript:void(0)" onClick={foo}>Perform action</a>
/// <a href="#" onClick={foo}>Perform action</a>
/// <a onClick={foo}>Perform action</a>
/// </>
/// ````
///
/// 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
/// <a href={`https://www.javascript.com`}>navigate here</a>
/// <a href={somewhere}>navigate here</a>
/// <a {...spread}>navigate here</a>
/// <>
/// <a href={`https://www.javascript.com`}>navigate here</a>
/// <a href={somewhere}>navigate here</a>
/// <a {...spread}>navigate here</a>
/// </>
/// ```
///
/// #### Invalid
///
/// ```jsx
/// <a href={null}>navigate here</a>
/// <a href={undefined}>navigate here</a>
/// <a href>navigate here</a>
/// <a href="javascript:void(0)">navigate here</a>
/// <a href="https://example.com" onClick={something}>navigate here</a>
/// <>
/// <a href={null}>navigate here</a>
/// <a href={undefined}>navigate here</a>
/// <a href>navigate here</a>
/// <a href="javascript:void(0)">navigate here</a>
/// <a href="https://example.com" onClick={something}>navigate here</a>
/// </>
/// ```
///
/// ### Reference

View file

@ -32,25 +32,25 @@ declare_oxc_lint!(
///
/// ### Example
/// ```jsx
/// // Good
/// <CustomComponent />
/// <CustomComponent aria-activedescendant={someID} />
/// <CustomComponent aria-activedescendant={someID} tabIndex={0} />
/// <CustomComponent aria-activedescendant={someID} tabIndex={-1} />
/// <div />
/// <input />
/// <div tabIndex={0} />
/// <div aria-activedescendant={someID} tabIndex={0} />
/// <div aria-activedescendant={someID} tabIndex="0" />
/// <div aria-activedescendant={someID} tabIndex={1} />
/// <div aria-activedescendant={someID} tabIndex={-1} />
/// <div aria-activedescendant={someID} tabIndex="-1" />
/// <input aria-activedescendant={someID} />
/// <input aria-activedescendant={someID} tabIndex={0} />
/// <input aria-activedescendant={someID} tabIndex={-1} />
/// const Good = <>
/// <CustomComponent />
/// <CustomComponent aria-activedescendant={someID} />
/// <CustomComponent aria-activedescendant={someID} tabIndex={0} />
/// <CustomComponent aria-activedescendant={someID} tabIndex={-1} />
/// <div />
/// <input />
/// <div tabIndex={0} />
/// <div aria-activedescendant={someID} tabIndex={0} />
/// <div aria-activedescendant={someID} tabIndex="0" />
/// <div aria-activedescendant={someID} tabIndex={1} />
/// <div aria-activedescendant={someID} tabIndex={-1} />
/// <div aria-activedescendant={someID} tabIndex="-1" />
/// <input aria-activedescendant={someID} />
/// <input aria-activedescendant={someID} tabIndex={0} />
/// <input aria-activedescendant={someID} tabIndex={-1} />
/// </>
///
/// // Bad
/// <div aria-activedescendant={someID} />
/// const Bad = <div aria-activedescendant={someID} />
/// ```
AriaActivedescendantHasTabindex,
correctness

View file

@ -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
/// <input aria-labeledby="address_label" />
/// ```
///
/// // Good
/// Examples of **correct** code for this rule:
/// ```jsx
/// <input aria-labelledby="address_label" />
/// ```
AriaProps,

View file

@ -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
/// <div role="datepicker"></div> <!-- Bad: "datepicker" is not an ARIA role -->
/// <div role="range"></div> <!-- Bad: "range" is an _abstract_ ARIA role -->
/// <div role=""></div> <!-- Bad: An empty ARIA role is not allowed -->
/// <Foo role={role}></Foo> <!-- Bad: ignoreNonDOM is set to false or not set -->
/// ```
///
/// Examples of **correct** code for this rule:
/// ```jsx
/// <div role="button"></div> <!-- Good: "button" is a valid ARIA role -->
/// <div role={role}></div> <!-- Good: role is a variable & cannot be determined until runtime. -->
/// <div></div> <!-- Good: No ARIA role -->
/// <Foo role={role}></Foo> <!-- Good: ignoreNonDOM is set to true -->
/// ```
///
/// // bad
/// ```javascript
/// <div role="datepicker"></div> <!-- Bad: "datepicker" is not an ARIA role -->
/// <div role="range"></div> <!-- Bad: "range" is an _abstract_ ARIA role -->
/// <div role=""></div> <!-- Bad: An empty ARIA role is not allowed -->
/// <Foo role={role}></Foo> <!-- Bad: ignoreNonDOM is set to false or not set -->
/// ```
AriaRole,
correctness
);

View file

@ -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
/// <input autocomplete="invalid-value" />
///

View file

@ -49,7 +49,7 @@ declare_oxc_lint!(
/// from accessing information on the page's structure.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <h1 />
///

View file

@ -41,7 +41,7 @@ declare_oxc_lint!(
///
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <html />
///

View file

@ -37,7 +37,7 @@ declare_oxc_lint!(
/// This rule checks for title property on iframe element.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <iframe />
/// <iframe {...props} />

View file

@ -79,7 +79,7 @@ declare_oxc_lint!(
/// `<img>` and the components which you define in options.components with the exception of components which is hidden from screen reader.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <img src="foo" alt="Photo of foo being weird." />
/// <img src="bar" alt="Image of me at a bar!" />

View file

@ -26,7 +26,7 @@ declare_oxc_lint!(
/// Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create accessibility complications so to avoid complications, access keys should not be used.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <div accessKey="h" />
///

View file

@ -30,7 +30,7 @@ declare_oxc_lint!(
/// `aria-hidden="true"` on focusable elements can lead to confusion or unexpected behavior for screen reader users.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <div aria-hidden="true" tabIndex="0" />
///

View file

@ -24,12 +24,16 @@ pub struct NoAutofocus {
declare_oxc_lint!(
/// ### What it does
/// Enforce that autoFocus prop is not used on elements. Autofocusing elements can cause usability issues for sighted and non-sighted users, alike.
///
/// Enforce that `autoFocus` prop is not used on elements. Autofocusing
/// elements can cause usability issues for sighted and non-sighted users,
/// alike.
///
/// ### Rule Option
///
/// This rule takes one optional object argument of type object:
///
/// ```
/// ```json
/// {
/// "rules": {
/// "jsx-a11y/no-autofocus": [ 2, {
@ -39,24 +43,25 @@ declare_oxc_lint!(
/// }
/// ```
///
/// 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
/// <div />
/// ```
/// Examples of **incorrect** code for this rule:
///
/// // bad
///
/// ```
/// ```jsx
/// <div autoFocus />
/// <div autoFocus="true" />
/// <div autoFocus="false" />
/// <div autoFocus={undefined} />
/// ```
///
/// Examples of **correct** code for this rule:
///
/// ```jsx
/// <div />
/// ```
NoAutofocus,
correctness,
fix

View file

@ -27,13 +27,15 @@ pub struct NoRedundantRoles;
declare_oxc_lint!(
/// ### What it does
/// Enforces that the explicit role property is not the same as implicit/default role property on element.
///
/// Enforces that the explicit `role` property is not the same as
/// implicit/default role property on element.
///
/// ### Why is this bad?
/// Redundant roles can lead to confusion and verbosity in the codebase.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <nav role="navigation" />
///

View file

@ -32,7 +32,7 @@ declare_oxc_lint!(
/// Using semantic HTML tags can improve accessibility and readability of the code.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <div role="button" />
///

View file

@ -19,13 +19,17 @@ fn role_has_required_aria_props_diagnostic(span: Span, role: &str, props: &str)
pub struct RoleHasRequiredAriaProps;
declare_oxc_lint!(
/// ### What it does
/// Enforces that elements with ARIA roles must have all required attributes for that role.
///
/// Enforces that elements with ARIA roles must have all required attributes
/// for that role.
///
/// ### Why is this bad?
/// Certain ARIA roles require specific attributes to express necessary semantics for assistive technology.
///
/// Certain ARIA roles require specific attributes to express necessary
/// semantics for assistive technology.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <div role="checkbox" />
///

View file

@ -21,13 +21,19 @@ pub struct TabindexNoPositive;
declare_oxc_lint!(
/// ### What it does
/// Enforces that positive values for the tabIndex attribute are not used in JSX.
///
/// Enforces that positive values for the `tabIndex` attribute are not used
/// in JSX.
///
/// ### Why is this bad?
/// Using tabIndex values greater than 0 can make navigation and interaction difficult for keyboard and assistive technology users, disrupting the logical order of content.
///
/// Using `tabIndex` values greater than `0` can make navigation and
/// interaction difficult for keyboard and assistive technology users,
/// disrupting the logical order of content.
///
/// ### Example
/// ```javascript
///
/// ```jsx
/// // Bad
/// <span tabIndex="1">foo</span>
///

View file

@ -30,13 +30,50 @@ pub struct GoogleFontDisplay;
declare_oxc_lint!(
/// ### What it does
///
/// Enforce font-display behavior with Google Fonts.
///
/// ### Why is this bad?
///
/// Specifying display=optional minimizes the risk of invisible text or
/// layout shift. If swapping to the custom font after it has loaded is
/// important to you, then use `display=swap`` instead.
///
/// ### Example
/// ```javascript
///
/// Examples of **incorrect** code for this rule:
///
/// ```jsx
/// import Head from "next/head";
///
/// export default Test = () => {
/// return (
/// <Head>
/// <link
/// href="https://fonts.googleapis.com/css2?family=Krona+One"
/// rel="stylesheet"
/// />
/// </Head>
/// );
/// };
/// ```
///
/// Examples of **correct** code for this rule:
///
/// ```jsx
/// import Head from "next/head";
///
/// export default Test = () => {
/// return (
/// <Head>
/// <link
/// href="https://fonts.googleapis.com/css2?family=Krona+One&display=optional"
/// rel="stylesheet"
/// />
/// </Head>
/// );
/// };
/// ```
///
GoogleFontDisplay,
correctness
);
@ -155,16 +192,16 @@ fn test() {
let fail = vec![
r#"import Head from "next/head";
export default Test = () => {
return (
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Krona+One"
rel="stylesheet"
/>
</Head>
);
};
export default Test = () => {
return (
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Krona+One"
rel="stylesheet"
/>
</Head>
);
};
"#,
r#"import Head from "next/head";

View file

@ -21,14 +21,21 @@ pub struct ApproxConstant;
declare_oxc_lint!(
/// ### What it does
///
/// Disallows the use of approximate constants, instead preferring the use of the constants in the `Math` object.
/// Disallows the use of approximate constants, instead preferring the use
/// of the constants in the `Math` object.
///
/// ### Why is this bad?
///
/// Approximate constants are not as accurate as the constants in the `Math` object.
///
/// ### Example
///
/// ```javascript
/// // Bad
/// let log10e = 0.434294
///
/// // Good
/// let log10e = Math.LOG10E
/// ```
ApproxConstant,
suspicious

View file

@ -27,11 +27,11 @@ declare_oxc_lint!(
/// Their use can lead to import nonexistent values (because const enums are erased).
///
/// ### Example
/// ```javascript
/// ```ts
/// const enum Color {
/// Red,
/// Green,
/// Blue
/// Red,
/// Green,
/// Blue
/// }
/// ```
NoConstEnum,

View file

@ -35,10 +35,10 @@ declare_oxc_lint!(
/// It increase cognitive complexity and may impact performance.
///
/// ### Example
/// ```javascript
/// ```ts
/// // Bad - the argument `b` is only used in recursive calls
/// function f(a: number, b: number): number {
/// if a == 0 {
/// if (a == 0) {
/// return 1
/// } else {
/// return f(a - 1, b + 1)
@ -47,7 +47,7 @@ declare_oxc_lint!(
///
/// // Good - the argument `b` is omitted
/// function f(a: number): number {
/// if a == 0 {
/// if (a == 0) {
/// return 1
/// } else {
/// return f(a - 1)

View file

@ -23,7 +23,7 @@ declare_oxc_lint!(
///
/// ### Example
/// ```javascript
/// new Promise((resolve, reject) => { ... });
/// new Promise((resolve, reject) => { /* ... */ });
/// ```
AvoidNew,
restriction,

View file

@ -50,8 +50,8 @@ declare_oxc_lint!(
///
/// ### Example
/// ```javascript
/// new Promise(function (reject, resolve) { ... }) // incorrect order
/// new Promise(function (ok, fail) { ... }) // non-standard parameter names
/// new Promise(function (reject, resolve) { /* ... */ }) // incorrect order
/// new Promise(function (ok, fail) { /* ... */ }) // non-standard parameter names
/// ```
ParamNames,
style,

View file

@ -48,10 +48,12 @@ declare_oxc_lint!(
///
/// ### Why is this bad?
///
/// The default value of `type` attribute for `button` HTML element is `"submit"` which is often not the desired behavior and may lead to unexpected page reloads.
/// The default value of `type` attribute for `button` HTML element is
/// `"submit"` which is often not the desired behavior and may lead to
/// unexpected page reloads.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <button />
/// <button type="foo" />

View file

@ -37,7 +37,7 @@ declare_oxc_lint!(
/// It also warns when checked and defaultChecked properties are used together.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <input type="checkbox" checked />
/// <input type="checkbox" checked defaultChecked />

View file

@ -55,7 +55,7 @@ declare_oxc_lint!(
/// Enforce a consistent boolean attribute style in your code.
///
/// ### Example
/// ```javascript
/// ```jsx
/// const Hello = <Hello personal={true} />;
/// ```
JsxBooleanValue,

View file

@ -36,7 +36,7 @@ declare_oxc_lint!(
/// Enforce `key` prop for elements in array
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// [1, 2, 3].map(x => <App />);
/// [1, 2, 3]?.map(x => <BabelEslintApp />)

View file

@ -25,7 +25,7 @@ declare_oxc_lint!(
/// In JSX, any text node that is not wrapped in curly braces is considered a literal string to be rendered. This can lead to unexpected behavior when the text contains a comment.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Incorrect:
///
/// const Hello = () => {

View file

@ -29,7 +29,7 @@ declare_oxc_lint!(
/// Creating JSX elements with duplicate props can cause unexpected behavior in your application.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <App a a />;
/// <App foo={2} bar baz foo={3} />;

View file

@ -102,7 +102,7 @@ declare_oxc_lint!(
/// target='_blank' attributes with rel='noreferrer'.
///
/// ### Example
/// ```javascript
/// ```jsx
/// /// correct
/// var Hello = <p target="_blank"></p>
/// var Hello = <a target="_blank" rel="noreferrer" href="https://example.com"></a>

View file

@ -36,7 +36,7 @@ declare_oxc_lint!(
/// Fragments are a useful tool when you need to group multiple children without adding a node to the DOM tree. However, sometimes you might end up with a fragment with a single child. When this child is an element, string, or expression, it's not necessary to use a fragment.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <>foo</>
/// <div><>foo</></div>

View file

@ -27,7 +27,7 @@ declare_oxc_lint!(
/// When not using JSX, the children should be passed as additional arguments to `React.createElement`.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <div children='Children' />
///

View file

@ -29,10 +29,26 @@ declare_oxc_lint!(
///
/// ### Why is this bad?
///
/// `dangerouslySetInnerHTML` is a way to inject HTML into your React component. This is dangerous because it can easily lead to XSS vulnerabilities.
/// `dangerouslySetInnerHTML` is a way to inject HTML into your React
/// component. This is dangerous because it can easily lead to XSS
/// vulnerabilities.
///
/// ### Example
/// ```javascript
///
/// Examples of **incorrect** code for this rule:
///
/// ```jsx
/// import React from "react";
///
/// const Hello = <div dangerouslySetInnerHTML={{ __html: "Hello World" }}></div>;
/// ```
///
/// Examples of **correct** code for this rule:
///
/// ```jsx
/// import React from "react";
///
/// const Hello = <div>Hello World</div>;
/// ```
NoDanger,
restriction

View file

@ -34,7 +34,7 @@ declare_oxc_lint!(
/// calling setState() afterwards may replace the mutation you made
///
/// ### Example
/// ```javascript
/// ```jsx
/// // error
/// var Hello = createReactClass({
/// componentDidMount: function() {

View file

@ -24,7 +24,7 @@ declare_oxc_lint!(
/// [It has been deprecated in `StrictMode`.](https://legacy.reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage)
///
/// ### Example
/// ```javascript
/// ```jsx
/// class MyComponent extends Component {
/// componentDidMount() {
/// findDOMNode(this).scrollIntoView();

View file

@ -25,7 +25,7 @@ declare_oxc_lint!(
/// and it is on its way to being officially deprecated.///
///
/// ### Example
/// ```javascript
/// ```jsx
/// class Hello extends React.Component {
/// someMethod() {
/// if (!this.isMounted()) {

View file

@ -20,7 +20,7 @@ declare_oxc_lint!(
/// This rule will warn you if you try to use the ReactDOM.render() return value.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// vaa inst =ReactDOM.render(<App />, document.body);
/// function render() {

View file

@ -30,7 +30,7 @@ declare_oxc_lint!(
/// state should rarely be necessary in such cases.
///
/// ### Example
/// ```javascript
/// ```jsx
/// var Hello = createReactClass({
/// getInitialState: function() {
/// return {

View file

@ -39,7 +39,7 @@ declare_oxc_lint!(
/// This rule prevents using string literals in ref attributes.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// var Hello = createReactClass({
/// render: function() {

View file

@ -34,7 +34,7 @@ declare_oxc_lint!(
/// This rule enforces a consistent React class style.
///
/// ### Example
/// ```javascript
/// ```jsx
/// var Hello = createReactClass({
/// render: function() {
/// return <div>Hello {this.props.name}</div>;

View file

@ -21,10 +21,11 @@ declare_oxc_lint!(
///
/// ### Why is this bad?
///
/// When using JSX, `<a />` expands to `React.createElement("a")`. Therefore the `React` variable must be in scope.
/// When using JSX, `<a />` expands to `React.createElement("a")`. Therefore
/// the `React` variable must be in scope.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// var a = <a />;
///

View file

@ -31,7 +31,7 @@ declare_oxc_lint!(
/// When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the return statement is missing.
///
/// ### Example
/// ```javascript
/// ```jsx
/// var Hello = createReactClass({
/// render() {
/// <div>Hello</div>;

View file

@ -29,7 +29,7 @@ declare_oxc_lint!(
/// This rule checks that children are not passed to void DOM elements.
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <br>Children</br>
/// <br children='Children' />

View file

@ -13,7 +13,7 @@ declare_oxc_lint!(
/// Prevent JSX that are local to the current method from being used as values of JSX props
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <Item jsx={<SubItem />} />
/// <Item jsx={this.props.jsx || <SubItem />} />

View file

@ -17,10 +17,10 @@ declare_oxc_lint!(
/// Prevent Arrays that are local to the current method from being used as values of JSX props
///
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <Item list={[]} />
///
/// <Item list={new Array()} />
/// <Item list={Array()} />
/// <Item list={this.props.list || []} />

View file

@ -16,7 +16,7 @@ declare_oxc_lint!(
///
/// Prevent Functions that are local to the current method from being used as values of JSX props
/// ### Example
/// ```javascript
/// ```jsx
/// // Bad
/// <Item callback={new Function(...)} />
/// <Item callback={this.props.callback || function() {}} />

View file

@ -16,7 +16,7 @@ declare_oxc_lint!(
///
/// Prevent Objects that are local to the current method from being used as values of JSX props
///
/// ```javascript
/// ```jsx
/// // Bad
/// <Item config={{}} />
/// <Item config={new Object()} />

View file

@ -102,7 +102,7 @@ declare_oxc_lint!(
/// reduces the effectiveness of TypeScript overall.
///
/// ### Example
/// ```javascript
/// ```ts
/// if (false) {
/// // @ts-ignore: Unreachable code error
/// console.log('hello');

View file

@ -22,7 +22,7 @@ declare_oxc_lint!(
/// removed, this rule helps locate TSLint annotations
///
/// ### Example
/// ```javascript
/// ```ts
/// // tslint:disable-next-line
/// someCode();
/// ```

View file

@ -36,7 +36,7 @@ declare_oxc_lint!(
/// ### Example
/// With "record":
///
/// ```javascript
/// ```ts
/// // bad
/// interface Foo {
/// [key: string]: unknown;
@ -48,7 +48,7 @@ declare_oxc_lint!(
///
/// With "index-signature":
///
/// ```javascript
/// ```ts
/// // bad
/// type Foo = Record<string, unknown>;
/// ```

View file

@ -95,7 +95,7 @@ declare_oxc_lint!(
/// inconsistent usage of type imports can make the code harder to read and understand.
///
/// ### Example
/// ```javascript
/// ```ts
/// import { Foo } from 'Foo';
/// type T = Foo;
///

View file

@ -47,14 +47,63 @@ impl std::ops::Deref for ExplicitFunctionReturnType {
declare_oxc_lint!(
/// ### What it does
///
/// This rule enforces that functions do have an explicit return type annotation.
///
/// ### Why is this bad?
/// Explicit return types do make it visually more clear what type is returned by a function.
/// They can also speed up TypeScript type checking performance in large codebases with many large functions.
///
/// Explicit return types do make it visually more clear what type is
/// returned by a function. They can also speed up TypeScript type checking
/// performance in large codebases with many large functions.
///
/// ### Example
/// ```javascript
///
/// Examples of **incorrect** code for this rule:
///
/// ```ts
/// // Should indicate that no value is returned (void)
/// function test() {
/// return
/// }
///
/// // Should indicate that a number is returned
/// var fn = function () {
/// return 1
/// }
///
/// // Should indicate that a string is returned
/// var arrowFn = () => 'test'
///
/// class Test {
/// // Should indicate that no value is returned (void)
/// method() {
/// return
/// }
/// }
/// ```
///
/// Examples of **correct** code for this rule:
///
/// ```ts
/// // No return value should be expected (void)
/// function test(): void {
/// return
/// }
///
/// // A return value of type number
/// var fn = function (): number {
/// return 1
/// }
///
/// // A return value of type string
/// var arrowFn = (): string => 'test'
///
/// class Test {
/// // No return value should be expected (void)
/// method(): void {
/// return
/// }
/// }
/// ```
ExplicitFunctionReturnType,
restriction,

View file

@ -20,7 +20,7 @@ declare_oxc_lint!(
/// Using a non-null assertion (!) next to an assign or equals check (= or == or ===) creates code that is confusing as it looks similar to a not equals check (!= !==).
///
/// ### Example
/// ```javascript
/// ```ts
/// a! == b; // a non-null assertions(`!`) and an equals test(`==`)
/// a !== b; // not equals test(`!==`)
/// a! === b; // a non-null assertions(`!`) and an triple equals test(`===`)

View file

@ -20,14 +20,16 @@ declare_oxc_lint!(
/// Disallow duplicate enum member values.
///
/// ### Why is this bad?
/// Although TypeScript supports duplicate enum member values, people usually expect members to have unique values within the same enum. Duplicate values can lead to bugs that are hard to track down.
/// Although TypeScript supports duplicate enum member values, people
/// usually expect members to have unique values within the same enum.
/// Duplicate values can lead to bugs that are hard to track down.
///
/// ### Example
/// ```javascript
/// ```ts
/// enum E {
// A = 0,
// B = 0,
// }
/// A = 0,
/// B = 0,
/// }
/// ```
NoDuplicateEnumValues,
pedantic

View file

@ -19,7 +19,7 @@ declare_oxc_lint!(
/// Consider using a Map or Set if youre using an object as a key-value collection.
///
/// ### Example
/// ```javascript
/// ```ts
/// const container: { [i: string]: 0 } = {};
/// delete container['aa' + 'b'];
/// ```

View file

@ -32,7 +32,7 @@ declare_oxc_lint!(
/// This rule aims to ensure that only meaningful interfaces are declared in the code.
///
/// ### Example
/// ```javascript
/// ```ts
/// interface Foo {}
/// interface Bar extends Foo {}
/// ```

View file

@ -21,7 +21,7 @@ declare_oxc_lint!(
/// The `!` non-null assertion operator in TypeScript is used to assert that a value's type does not include null or undefined. Using the operator any more than once on a single value does nothing.
///
/// ### Example
/// ```javascript
/// ```ts
/// const foo: { bar: number } | null = null;
/// const bar = foo!!!.bar;
/// ```

View file

@ -41,7 +41,7 @@ declare_oxc_lint!(
/// when they're all on the class (see: Finding dead code (and dead types) in TypeScript).
///
/// ### Example
/// ```javascript
/// ```ts
/// class StaticConstants {
/// static readonly version = 42;
///

View file

@ -20,31 +20,37 @@ pub struct NoImportTypeSideEffects;
declare_oxc_lint!(
/// ### What it does
///
/// Enforce the use of top-level import type qualifier when an import only has specifiers with inline type qualifiers.
/// Enforce the use of top-level `import type` qualifier when an import only
/// has specifiers with inline type qualifiers.
///
/// ### Why is this bad?
///
/// The `--verbatimModuleSyntax` compiler option causes TypeScript to do simple and predictable transpilation on import declarations.
/// Namely, it completely removes import declarations with a top-level type qualifier, and it removes any import specifiers with an inline type qualifier.
/// The `--verbatimModuleSyntax` compiler option causes TypeScript to do
/// simple and predictable transpilation on import declarations. Namely, it
/// completely removes import declarations with a top-level type qualifier,
/// and it removes any import specifiers with an inline type qualifier.
///
/// The latter behavior does have one potentially surprising effect in that in certain cases TS can leave behind a "side effect" import at runtime:
/// ```javascript
/// The latter behavior does have one potentially surprising effect in that
/// in certain cases TS can leave behind a "side effect" import at runtime:
///
/// ```ts
/// import { type A, type B } from 'mod';
/// ```
///
/// is transpiled to
///
/// ```javascript
/// ```ts
/// import {} from 'mod';
/// which is the same as
/// // which is the same as
/// import 'mod';
/// ```
/// For the rare case of needing to import for side effects, this may be desirable - but for most cases you will not want to leave behind an unnecessary side effect import.
///
/// For the rare case of needing to import for side effects, this may be
/// desirable - but for most cases you will not want to leave behind an
/// unnecessary side effect import.
///
/// ### Example
/// ```javascript
/// ```ts
/// import { type A } from 'mod';
/// import { type A as AA } from 'mod';
/// import { type A, type B } from 'mod';

View file

@ -32,21 +32,22 @@ declare_oxc_lint!(
///
/// JavaScript classes may define a constructor method that runs
/// when a class instance is newly created.
/// TypeScript allows interfaces that describe a static class object to define
/// a new() method (though this is rarely used in real world code).
///
/// TypeScript allows interfaces that describe a static class object to
/// define a `new()` method (though this is rarely used in real world code).
/// Developers new to JavaScript classes and/or TypeScript interfaces may
/// sometimes confuse when to use constructor or new.
///
/// ### Example
/// ```typescript
// declare class C {
// new(): C;
// }
// interface I {
// new (): I;
// constructor(): void;
// }
/// declare class C {
/// new(): C;
/// }
///
/// interface I {
/// new (): I;
/// constructor(): void;
/// }
/// ```
NoMisusedNew,
correctness

View file

@ -17,7 +17,7 @@ declare_oxc_lint!(
/// The ?? nullish coalescing runtime operator allows providing a default value when dealing with null or undefined. Using a ! non-null assertion type operator in the left operand of a nullish coalescing operator is redundant, and likely a sign of programmer error or confusion over the two operators.
///
/// ### Example
/// ```javascript
/// ```ts
/// foo! ?? bar;
///
/// let x: string;

View file

@ -29,7 +29,7 @@ declare_oxc_lint!(
/// Most of the time, either the object was not nullable and did not need the `?.` for its property lookup, or the `!` is incorrect and introducing a type safety hole.
///
/// ### Example
/// ```javascript
/// ```ts
/// foo?.bar!;
/// foo?.bar()!;
/// ```

View file

@ -16,7 +16,7 @@ declare_oxc_lint!(
/// TypeScript's ! non-null assertion operator asserts to the type system that an expression is non-nullable, as in not null or undefined. Using assertions to tell the type system new information is often a sign that code is not fully type-safe. It's generally better to structure program logic so that TypeScript understands when values may be nullable.
///
/// ### Example
/// ```javascript
/// ```ts
/// x!;
/// x!.y;
/// x.y!;

View file

@ -26,7 +26,7 @@ declare_oxc_lint!(
/// The TypeScript compiler doesn't check whether properties are initialized, which can cause lead to TypeScript not detecting code that will cause runtime errors.
///
/// ### Example
/// ```javascript
/// ```ts
/// interface Foo {}
/// class Foo {}
/// ```

View file

@ -22,13 +22,13 @@ declare_oxc_lint!(
/// ### Example
///
/// ### Bad
/// ```javascript
/// ```ts
/// export const value = 'Hello, world!';
/// export {};
/// ```
///
/// ### Good
/// ```javascript
/// ```ts
/// export const value = 'Hello, world!';
/// ```
///

View file

@ -30,7 +30,7 @@ declare_oxc_lint!(
/// This rule reports when an as with an explicit literal type can be replaced with an as const.
///
/// ### Example
/// ```javascript
/// ```ts
/// let bar: 2 = 2;
/// let foo = { bar: 'baz' as 'baz' };
/// ```

View file

@ -33,7 +33,7 @@ declare_oxc_lint!(
/// eliminate the need for an index variable and manual array access.
///
/// ### Example
/// ```javascript
/// ```ts
/// // Bad
/// for (let i = 0; i < arr.length; i++) {
/// console.log(arr[i]);

View file

@ -30,7 +30,7 @@ declare_oxc_lint!(
/// This rule suggests using a function type instead of an interface or object type literal with a single call signature.
///
/// ### Example
/// ```javascript
/// ```ts
/// // error
/// interface Example {
/// (): string;

View file

@ -28,7 +28,7 @@ declare_oxc_lint!(
/// However, because enums create their own scope whereby each enum member becomes a variable in that scope, developers are often surprised at the resultant values.
///
/// ### Example
/// ```javascript
/// ```ts
/// const imOutside = 2;
/// const b = 2;
/// enum Foo {

View file

@ -27,7 +27,7 @@ declare_oxc_lint!(
/// This is dangerous, as if a new error arises on that line it'll be suppressed by the forgotten about @ts-ignore, and so be missed.
///
/// ### Example
/// ```javascript
/// ```ts
/// // @ts-ignore
/// const str: string = 1;
///

View file

@ -61,7 +61,7 @@ declare_oxc_lint!(
/// Use of triple-slash reference type directives is generally discouraged in favor of ECMAScript Module imports.
///
/// ### Example
/// ```javascript
/// ```ts
/// /// <reference lib="code" />
/// globalThis.value;
/// ```

View file

@ -43,6 +43,8 @@ declare_oxc_lint!(
///
/// ### Example
/// ```javascript
/// array.reduce(reducer, initialValue);
/// array.reduceRight(reducer, initialValue);
/// ```
NoArrayReduce,
restriction

View file

@ -26,11 +26,13 @@ declare_oxc_lint!(
///
/// ### Example
/// ```javascript
/// // Bad
/// const secondElement = (await getArray())[1];
/// async function bad() {
/// const secondElement = (await getArray())[1];
/// }
///
/// // Good
/// const [, secondElement] = await getArray();
/// async function good() {
/// const [, secondElement] = await getArray();
/// }
/// ```
NoAwaitExpressionMember,
style

View file

@ -21,25 +21,31 @@ declare_oxc_lint!(
///
/// ### Why is this bad?
///
/// Using `await` on promises passed as arguments to `Promise.all()`, `Promise.allSettled()`, `Promise.any()`, or `Promise.race()` is likely a mistake.
/// Using `await` on promises passed as arguments to `Promise.all()`,
/// `Promise.allSettled()`, `Promise.any()`, or `Promise.race()` is likely a
/// mistake.
///
/// ### Example
/// Bad
///
/// ```js
/// Promise.all([await promise, anotherPromise]);
/// Promise.allSettled([await promise, anotherPromise]);
/// Promise.any([await promise, anotherPromise]);
/// Promise.race([await promise, anotherPromise]);
/// async function foo() {
/// Promise.all([await promise, anotherPromise]);
/// Promise.allSettled([await promise, anotherPromise]);
/// Promise.any([await promise, anotherPromise]);
/// Promise.race([await promise, anotherPromise]);
/// }
/// ```
///
/// Good
///
/// ```js
/// Promise.all([promise, anotherPromise]);
/// Promise.allSettled([promise, anotherPromise]);
/// Promise.any([promise, anotherPromise]);
/// Promise.race([promise, anotherPromise]);
/// async function foo() {
/// Promise.all([promise, anotherPromise]);
/// Promise.allSettled([promise, anotherPromise]);
/// Promise.any([promise, anotherPromise]);
/// Promise.race([promise, anotherPromise]);
/// }
/// ```
NoAwaitInPromiseMethods,
correctness

View file

@ -23,11 +23,17 @@ pub struct NoDocumentCookie;
declare_oxc_lint!(
/// ### What it does
///
/// Disallow direct use of [`document.cookie`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie).
/// Disallow direct use of
/// [`document.cookie`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie).
///
/// ### Why is this bad?
///
/// It's not recommended to use [`document.cookie`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie) directly as it's easy to get the string wrong. Instead, you should use the [Cookie Store API](https://developer.mozilla.org/en-US/docs/Web/API/Cookie_Store_API) or a [cookie library](https://www.npmjs.com/search?q=cookie).
/// It's not recommended to use
/// [`document.cookie`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie)
/// directly as it's easy to get the string wrong. Instead, you should use
/// the [Cookie Store
/// API](https://developer.mozilla.org/en-US/docs/Web/API/Cookie_Store_API)
/// or a [cookie library](https://www.npmjs.com/search?q=cookie).
///
/// ### Example
/// ```javascript
@ -40,12 +46,14 @@ declare_oxc_lint!(
/// '; Secure';
///
/// // good
/// await cookieStore.set({
/// name: 'foo',
/// value: 'bar',
/// expires: Date.now() + 24 * 60 * 60 * 1000,
/// domain: 'example.com'
/// });
/// async function storeCookies() {
/// await cookieStore.set({
/// name: 'foo',
/// value: 'bar',
/// expires: Date.now() + 24 * 60 * 60 * 1000,
/// domain: 'example.com'
/// });
/// }
/// ```
NoDocumentCookie,
correctness

View file

@ -28,8 +28,10 @@ declare_oxc_lint!(
///
/// // Good
/// if (problem) throw new Error("message");
/// ```
///
/// #! /usr/bin/env node
/// ```
/// #!/usr/bin/env node
/// if (problem) process.exit(1);
/// ```
NoProcessExit,

View file

@ -27,26 +27,31 @@ declare_oxc_lint!(
///
/// ### Why is this bad?
///
/// Passing a single-element array to `Promise.all()`, `Promise.any()`, or `Promise.race()` is likely a mistake.
/// Passing a single-element array to `Promise.all()`, `Promise.any()`, or
/// `Promise.race()` is likely a mistake.
///
///
/// ### Example
///
/// Bad
/// ```js
/// const foo = await Promise.all([promise]);
/// const foo = await Promise.any([promise]);
/// const foo = await Promise.race([promise]);
/// const promise = Promise.all([nonPromise]);
/// async function bad() {
/// const foo = await Promise.all([promise]);
/// const foo = await Promise.any([promise]);
/// const foo = await Promise.race([promise]);
/// const promise = Promise.all([nonPromise]);
/// }
/// ```
///
/// Good
/// ```js
/// const foo = await promise;
/// const promise = Promise.resolve(nonPromise);
/// const foo = await Promise.all(promises);
/// const foo = await Promise.any([promise, anotherPromise]);
/// const [{ value: foo, reason: error }] = await Promise.allSettled([promise]);
/// async function good() {
/// const foo = await promise;
/// const promise = Promise.resolve(nonPromise);
/// const foo = await Promise.all(promises);
/// const foo = await Promise.any([promise, anotherPromise]);
/// const [{ value: foo, reason: error }] = await Promise.allSettled([promise]);
/// }
/// ```
///
NoSinglePromiseInPromiseMethods,

View file

@ -44,14 +44,16 @@ declare_oxc_lint!(
///
/// ### Example
/// ```javascript
/// const foo = {
/// unicorn: 1,
/// then() {},
/// };
/// async function example() {
/// const foo = {
/// unicorn: 1,
/// then() {},
/// };
///
/// const {unicorn} = await foo;
/// const { unicorn } = await foo;
///
/// console.log('after'); //<- This will never execute
/// console.log('after'); //<- This will never execute
/// }
/// ```
NoThenable,
correctness

View file

@ -22,8 +22,11 @@ declare_oxc_lint!(
/// The `await` operator should only be used on `Promise` values.
///
/// ### Example
///
/// ```javascript
/// await await promise;
/// async function bad() {
/// await await promise;
/// }
/// ```
NoUnnecessaryAwait,
correctness,

Some files were not shown because too many files have changed in this diff Show more