diff --git a/crates/oxc_linter/src/rules/eslint/for_direction.rs b/crates/oxc_linter/src/rules/eslint/for_direction.rs index b227ed8bc716c..648535d90e9f7 100644 --- a/crates/oxc_linter/src/rules/eslint/for_direction.rs +++ b/crates/oxc_linter/src/rules/eslint/for_direction.rs @@ -26,16 +26,55 @@ pub struct ForDirection; declare_oxc_lint!( /// ### What it does - /// Disallow "for" loop update causing the counter to move in the wrong direction. + /// Disallow `for` loop update causing the counter to move in the wrong direction. /// /// ### Why is this bad? - /// A for loop that is known to run infinitely or never run is considered a bug. + /// A `for` loop with a stop condition that can never be reached, such as one + /// with a counter that moves in the wrong direction, will run infinitely. + /// While there are occasions when an infinite loop is intended, the + /// convention is to construct such loops as `while` loops. More typically, an + /// infinite `for` loop is a bug. + /// + /// This rule forbids `for` loops where the counter variable changes in such a + /// way that the stop condition will never be met. For example, if the + /// counter variable is increasing (i.e. `i++``) and the stop condition tests + /// that the counter is greater than zero (`i >= 0``) then the loop will never + /// exit. /// /// ### Example - /// ```javascript - /// for (var i = 0; i < 10; i--) {} /// - /// for (var i = 10; i >= 0; i++) {} + /// Examples of **incorrect** code for this rule: + /// ```js + /// for (var i = 0; i < 10; i--) { + /// } + /// + /// for (var i = 10; i >= 0; i++) { + /// } + /// + /// for (var i = 0; i > 10; i++) { + /// } + /// + /// for (var i = 0; 10 > i; i--) { + /// } + /// + /// const n = -2; + /// for (let i = 0; i < 10; i += n) { + /// } + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// for (var i = 0; i < 10; i++) { + /// } + /// + /// for (var i = 0; 10 > i; i++) { // with counter "i" on the right + /// } + /// + /// for (let i = 10; i >= 0; i += this.step) { // direction unknown + /// } + /// + /// for (let i = MIN; i <= MAX; i -= 0) { // not increasing or decreasing + /// } /// ``` ForDirection, correctness, diff --git a/crates/oxc_linter/src/rules/eslint/no_caller.rs b/crates/oxc_linter/src/rules/eslint/no_caller.rs index e96265946d93c..9b0eb1934eeaf 100644 --- a/crates/oxc_linter/src/rules/eslint/no_caller.rs +++ b/crates/oxc_linter/src/rules/eslint/no_caller.rs @@ -17,15 +17,29 @@ pub struct NoCaller; declare_oxc_lint!( /// ### What it does /// - /// Disallow the use of arguments.caller or arguments.callee + /// Disallow the use of `arguments.caller` or `arguments.callee`. /// /// ### Why is this bad? /// - /// The use of arguments.caller and arguments.callee make several code optimizations impossible. - /// They have been deprecated in future versions of JavaScript and their use is forbidden in ECMAScript 5 while in strict mode. + /// The use of `arguments.caller` and `arguments.callee` make several code + /// optimizations impossible. They have been deprecated in future versions + /// of JavaScript and their use is forbidden in ECMAScript 5 while in strict + /// mode. + /// + /// ```js + /// function foo() { + /// var callee = arguments.callee; + /// } + /// ``` + /// + /// This rule is aimed at discouraging the use of deprecated and sub-optimal + /// code by disallowing the use of `arguments.caller` and `arguments.callee`. As + /// such, it will warn when `arguments.caller` and `arguments.callee` are used. /// /// ### Example - /// ```javascript + /// + /// Examples of **incorrect** code for this rule: + /// ```js /// function foo(n) { /// if (n <= 0) { /// return; @@ -38,6 +52,21 @@ declare_oxc_lint!( /// return !(n > 1) ? 1 : arguments.callee(n - 1) * n; /// }); /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// function foo(n) { + /// if (n <= 0) { + /// return; + /// } + /// + /// foo(n - 1); + /// } + /// + /// [1,2,3,4,5].map(function factorial(n) { + /// return !(n > 1) ? 1 : factorial(n - 1) * n; + /// }); + /// ``` NoCaller, correctness ); diff --git a/crates/oxc_linter/src/rules/eslint/no_const_assign.rs b/crates/oxc_linter/src/rules/eslint/no_const_assign.rs index 627a575ba1f43..db6f51f6221ba 100644 --- a/crates/oxc_linter/src/rules/eslint/no_const_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_const_assign.rs @@ -17,16 +17,30 @@ pub struct NoConstAssign; declare_oxc_lint!( /// ### What it does - /// Disallow reassigning const variables + /// Disallow reassigning `const` variables. /// /// ### Why is this bad? /// We cannot modify variables that are declared using const keyword. /// It will raise a runtime error. /// /// ### Example - /// ```javascript + /// + /// Examples of **incorrect** code for this rule: + /// ```js /// const a = 0; /// a = 1; + /// + /// const b = 0; + /// b += 1; + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// const a = 0; + /// console.log(a); + /// + /// var b = 0; + /// b += 1; /// ``` NoConstAssign, correctness diff --git a/crates/oxc_linter/src/rules/eslint/no_constant_binary_expression.rs b/crates/oxc_linter/src/rules/eslint/no_constant_binary_expression.rs index 3fde9dd6173ae..926bd1c703f5f 100644 --- a/crates/oxc_linter/src/rules/eslint/no_constant_binary_expression.rs +++ b/crates/oxc_linter/src/rules/eslint/no_constant_binary_expression.rs @@ -22,13 +22,13 @@ declare_oxc_lint!( /// Disallow expressions where the operation doesn't affect the value /// /// ### Why is this bad? - /// Comparisons which will always evaluate to true or false and logical expressions (||, &&, ??) which either always + /// Comparisons which will always evaluate to true or false and logical expressions (`||`, `&&`, `??`) which either always /// short-circuit or never short-circuit are both likely indications of programmer error. /// /// These errors are especially common in complex expressions where operator precedence is easy to misjudge. /// /// Additionally, this rule detects comparisons to newly constructed objects/arrays/functions/etc. - /// In JavaScript, where objects are compared by reference, a newly constructed object can never === any other value. + /// In JavaScript, where objects are compared by reference, a newly constructed object can never `===` any other value. /// This can be surprising for programmers coming from languages where objects are compared by value. /// /// ### Example diff --git a/crates/oxc_linter/src/rules/eslint/no_constant_condition.rs b/crates/oxc_linter/src/rules/eslint/no_constant_condition.rs index 2c16127c51676..e31dcac69fd61 100644 --- a/crates/oxc_linter/src/rules/eslint/no_constant_condition.rs +++ b/crates/oxc_linter/src/rules/eslint/no_constant_condition.rs @@ -23,14 +23,44 @@ declare_oxc_lint!( /// /// ### Why is this bad? /// - /// A constant expression (for example, a literal) as a test condition might be a typo or development trigger for a specific behavior. + /// A constant expression (for example, a literal) as a test condition might + /// be a typo or development trigger for a specific behavior. + /// + /// This rule disallows constant expressions in the test condition of: + /// + /// - `if`, `for`, `while`, or `do...while` statement + /// - `?`: ternary expression + /// /// /// ### Example /// - /// ```javascript + /// Examples of **incorrect** code for this rule: + /// ```js /// if (false) { /// doSomethingUnfinished(); /// } + /// + /// if (new Boolean(x)) { + /// doSomethingAlways(); + /// } + /// if (x ||= true) { + /// doSomethingAlways(); + /// } + /// + /// do { + /// doSomethingForever(); + /// } while (x = -1); + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// if (x === 0) { + /// doSomething(); + /// } + /// + /// while (typeof x === "undefined") { + /// doSomething(); + /// } /// ``` NoConstantCondition, correctness diff --git a/crates/oxc_linter/src/rules/eslint/no_delete_var.rs b/crates/oxc_linter/src/rules/eslint/no_delete_var.rs index 94799cf50f57f..cfea7b2696593 100644 --- a/crates/oxc_linter/src/rules/eslint/no_delete_var.rs +++ b/crates/oxc_linter/src/rules/eslint/no_delete_var.rs @@ -16,13 +16,17 @@ pub struct NoDeleteVar; declare_oxc_lint!( /// ### What it does /// - /// The purpose of the delete operator is to remove a property from an object. + /// The purpose of the `delete` operator is to remove a property from an + /// object. /// /// ### Why is this bad? /// - /// Using the delete operator on a variable might lead to unexpected behavior. + /// Using the `delete` operator on a variable might lead to unexpected + /// behavior. /// /// ### Example + /// + /// Examples of **incorrect** code for this rule: /// ```javascript /// var x; /// delete x; diff --git a/crates/oxc_linter/src/rules/eslint/no_empty_static_block.rs b/crates/oxc_linter/src/rules/eslint/no_empty_static_block.rs index 282a48827d940..5ead32168cc4f 100644 --- a/crates/oxc_linter/src/rules/eslint/no_empty_static_block.rs +++ b/crates/oxc_linter/src/rules/eslint/no_empty_static_block.rs @@ -19,17 +19,32 @@ declare_oxc_lint!( /// Disallows the usages of empty static blocks /// /// ### Why is this bad? - /// Empty block statements, while not technically errors, usually occur due to refactoring that wasn’t completed. - /// They can cause confusion when reading code. + /// Empty block statements, while not technically errors, usually occur due + /// to refactoring that wasn’t completed. They can cause confusion when + /// reading code. /// /// ### Example - /// ```javascript /// + /// Examples of **incorrect** code for this rule: + /// ```js /// class Foo { /// static { /// } /// } + /// ``` /// + /// Examples of **correct** code for this rule: + /// ```js + /// class Foo { + /// static { + /// // blocks with comments are allowed + /// } + /// } + /// class Bar { + /// static { + /// doSomething(); + /// } + /// } /// ``` NoEmptyStaticBlock, correctness diff --git a/crates/oxc_linter/src/rules/eslint/no_eq_null.rs b/crates/oxc_linter/src/rules/eslint/no_eq_null.rs index c78e712605bc7..1ae2dcf6af64e 100644 --- a/crates/oxc_linter/src/rules/eslint/no_eq_null.rs +++ b/crates/oxc_linter/src/rules/eslint/no_eq_null.rs @@ -19,15 +19,37 @@ pub struct NoEqNull; declare_oxc_lint!( /// ### What it does - /// Disallow null comparisons without type-checking operators. + /// Disallow `null` comparisons without type-checking operators. /// /// ### Why is this bad? - /// Comparing to null without a type-checking operator (== or !=), can have unintended results as the comparison will evaluate to true when comparing to not just a null, but also an undefined value. + /// Comparing to `null` without a type-checking operator (`==` or `!=`), can + /// have unintended results as the comparison will evaluate to `true` when + /// comparing to not just a `null`, but also an `undefined` value. /// /// ### Example - /// ```javascript + /// + /// Examples of **incorrect** code for this rule: + /// ```js /// if (foo == null) { - /// bar(); + /// bar(); + /// } + /// if (baz != null) { + /// bar(); + /// } + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// if (foo === null) { + /// bar(); + /// } + /// + /// if (baz !== null) { + /// bar(); + /// } + /// + /// if (bang === undefined) { + /// bar(); /// } /// ``` NoEqNull, diff --git a/crates/oxc_linter/src/rules/eslint/no_iterator.rs b/crates/oxc_linter/src/rules/eslint/no_iterator.rs index f3322ba61fe0e..2aeb515dbaf4a 100644 --- a/crates/oxc_linter/src/rules/eslint/no_iterator.rs +++ b/crates/oxc_linter/src/rules/eslint/no_iterator.rs @@ -16,20 +16,41 @@ pub struct NoIterator; declare_oxc_lint!( /// ### What it does - /// Disallow the use of the __iterator__ property + /// Disallow the use of the `__iterator__` property /// /// ### Why is this bad? - /// The __iterator__ property was a SpiderMonkey extension to JavaScript + /// The `__iterator__` property was a SpiderMonkey extension to JavaScript /// that could be used to create custom iterators that are compatible with /// JavaScript’s for in and for each constructs. However, this property is /// now obsolete, so it should not be used. Here’s an example of how this /// used to work: /// + /// ```js + /// Foo.prototype.__iterator__ = function() { + /// return new FooIterator(this); + /// } + /// ``` + /// /// ### Example + /// + /// Examples of **incorrect** code for this rule: /// ```javascript /// Foo.prototype.__iterator__ = function() { /// return new FooIterator(this); - /// } + /// }; + /// + /// foo.__iterator__ = function () {}; + /// + /// foo["__iterator__"] = function () {}; + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// const __iterator__ = 42; // not using the __iterator__ property + /// + /// Foo.prototype[Symbol.iterator] = function() { + /// return new FooIterator(this); + /// }; /// ``` NoIterator, restriction diff --git a/crates/oxc_linter/src/rules/eslint/no_label_var.rs b/crates/oxc_linter/src/rules/eslint/no_label_var.rs index 4ac1d74a7335b..a6bafb79e7147 100644 --- a/crates/oxc_linter/src/rules/eslint/no_label_var.rs +++ b/crates/oxc_linter/src/rules/eslint/no_label_var.rs @@ -29,7 +29,6 @@ declare_oxc_lint!( /// ### Example /// /// Examples of **incorrect** code for this rule: - /// /// ```js /// var x = foo; /// function bar() { @@ -39,8 +38,8 @@ declare_oxc_lint!( /// } /// } /// ``` - /// Examples of **correct** code for this rule: /// + /// Examples of **correct** code for this rule: /// ```js /// // The variable that has the same name as the label is not in scope. /// diff --git a/crates/oxc_linter/src/rules/eslint/no_new_native_nonconstructor.rs b/crates/oxc_linter/src/rules/eslint/no_new_native_nonconstructor.rs index ab665fc3640fe..ad2b0c602eaf6 100644 --- a/crates/oxc_linter/src/rules/eslint/no_new_native_nonconstructor.rs +++ b/crates/oxc_linter/src/rules/eslint/no_new_native_nonconstructor.rs @@ -15,21 +15,31 @@ pub struct NoNewNativeNonconstructor; declare_oxc_lint!( /// ### What it does /// - /// Disallow new operators with global non-constructor functions (Symbol, BigInt) + /// Disallow `new` operators with global non-constructor functions (`Symbol`, `BigInt`) /// /// ### Why is this bad? /// - /// Both new Symbol and new BigInt throw a type error because they are functions and not classes. - /// It is easy to make this mistake by assuming the uppercase letters indicate classes. + /// Both `new Symbol` and `new BigInt` throw a type error because they are + /// functions and not classes. It is easy to make this mistake by assuming + /// the uppercase letters indicate classes. /// /// ### Example - /// ```javascript + /// + /// Examples of **incorrect** code for this rule: + /// ```js /// // throws a TypeError /// let foo = new Symbol("foo"); /// /// // throws a TypeError /// let result = new BigInt(9007199254740991); /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// let foo = Symbol("foo"); + /// + /// let result = BigInt(9007199254740991); + /// ``` NoNewNativeNonconstructor, correctness, ); diff --git a/crates/oxc_linter/src/rules/eslint/no_new_wrappers.rs b/crates/oxc_linter/src/rules/eslint/no_new_wrappers.rs index bd01a88250018..b216584203d3f 100644 --- a/crates/oxc_linter/src/rules/eslint/no_new_wrappers.rs +++ b/crates/oxc_linter/src/rules/eslint/no_new_wrappers.rs @@ -17,17 +17,33 @@ pub struct NoNewWrappers; declare_oxc_lint!( /// ### What it does /// - /// Disallow new operators with the String, Number, and Boolean objects + /// Disallow `new` operators with the `String`, `Number`, and `Boolean` objects /// /// ### Why is this bad? /// - /// The first problem is that primitive wrapper objects are, in fact, objects. That means typeof will return "object" instead of "string", "number", or "boolean". - /// The second problem comes with boolean objects. Every object is truthy, that means an instance of Boolean always resolves to true even when its actual value is false. + /// The first problem is that primitive wrapper objects are, in fact, + /// objects. That means typeof will return `"object"` instead of `"string"`, + /// `"number"`, or `"boolean"`. The second problem comes with boolean + /// objects. Every object is truthy, that means an instance of `Boolean` + /// always resolves to `true` even when its actual value is `false`. + /// /// https://eslint.org/docs/latest/rules/no-new-wrappers /// /// ### Example - /// ```javascript + /// + /// Examples of **incorrect** code for this rule: + /// ```js /// var stringObject = new String('Hello world'); + /// var numberObject = new Number(33); + /// var booleanObject = new Boolean(false); + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// var stringObject = 'Hello world'; + /// var stringObject2 = String(value); + /// var numberObject = Number(value); + /// var booleanObject = Boolean(value); /// ``` NoNewWrappers, pedantic diff --git a/crates/oxc_linter/src/rules/eslint/no_unused_vars/mod.rs b/crates/oxc_linter/src/rules/eslint/no_unused_vars/mod.rs index 7c25868447d1f..46d7393f1c5f1 100644 --- a/crates/oxc_linter/src/rules/eslint/no_unused_vars/mod.rs +++ b/crates/oxc_linter/src/rules/eslint/no_unused_vars/mod.rs @@ -27,7 +27,8 @@ pub struct NoUnusedVars(Box); declare_oxc_lint!( /// ### What it does /// - /// Disallows variable declarations or imports that are not used in code. + /// Disallows variable declarations, imports, or type declarations that are + /// not used in code. /// /// ### Why is this bad? /// @@ -35,18 +36,45 @@ declare_oxc_lint!( /// likely an error due to incomplete refactoring. Such variables take up /// space in the code and can lead to confusion by readers. /// + /// ```ts + /// // `b` is unused; this indicates a bug. + /// function add(a: number, b: number) { + /// return a; + /// } + /// console.log(add(1, 2)); + /// ``` + /// /// A variable `foo` is considered to be used if any of the following are /// true: /// /// * It is called (`foo()`) or constructed (`new foo()`) /// * It is read (`var bar = foo`) - /// * It is passed into a function as an argument (`doSomething(foo)`) + /// * It is passed into a function or constructor as an argument (`doSomething(foo)`) /// * It is read inside of a function that is passed to another function /// (`doSomething(function() { foo(); })`) + /// * It is exported (`export const foo = 42`) + /// * It is used as an operand to TypeScript's `typeof` operator (`const bar: + /// typeof foo = 4`) /// /// A variable is _not_ considered to be used if it is only ever declared /// (`var foo = 5`) or assigned to (`foo = 7`). /// + /// #### Types + /// This rule has full support for TypeScript types, interfaces, enums, and + /// namespaces. + /// + /// A type or interface `Foo` is considered to be used if it is used in any + /// of the following ways: + /// - It is used in the definition of another type or interface. + /// - It is used as a type annotation or as part of a function signature. + /// - It is used in a cast or `satisfies` expression. + /// + /// A type or interface is _not_ considered to be used if it is only ever + /// used in its own definition, e.g. `type Foo = Array`. + /// + /// Enums and namespaces are treated the same as variables, classes, + /// functions, etc. + /// /// #### Ignored Files /// This rule ignores `.d.ts` files and `.vue` files entirely. Variables, /// classes, interfaces, and types declared in `.d.ts` files are generally @@ -100,8 +128,18 @@ declare_oxc_lint!( /// } /// ``` /// + /// ```ts + /// type A = Array; + /// + /// enum Color { + /// Red, + /// Green, + /// Blue + /// } + /// ``` + /// /// Examples of **correct** code for this rule: - /// ```javascript + /// ```js /// /*eslint no-unused-vars: "error"*/ /// /// var x = 10; @@ -128,8 +166,19 @@ declare_oxc_lint!( /// } /// ``` /// + /// ```ts + /// export const x = 1; + /// const y = 1; + /// export { y }; + /// + /// type A = Record; + /// type B = T extends Record ? K : never; + /// const x = 'foo' as B; + /// console.log(x); + /// ``` + /// /// Examples of **incorrect** code for `/* exported variableName */` operation: - /// ```javascript + /// ```js /// /* exported global_var */ /// /// // Not respected, use ES6 modules instead.