docs(linter): improve documentation for several rules (#4997)

This commit is contained in:
DonIsaac 2024-08-20 00:55:48 +00:00
parent cca7440d4b
commit e331ca0a9d
13 changed files with 290 additions and 42 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 wasnt completed.
/// They can cause confusion when reading code.
/// Empty block statements, while not technically errors, usually occur due
/// to refactoring that wasnt 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

View file

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

View file

@ -16,21 +16,42 @@ 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
/// JavaScripts for in and for each constructs. However, this property is
/// now obsolete, so it should not be used. Heres an example of how this
/// used to work:
///
/// ### Example
/// ```javascript
/// ```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
);

View file

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

View file

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

View file

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

View file

@ -27,7 +27,8 @@ pub struct NoUnusedVars(Box<NoUnusedVarsOptions>);
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<Foo>`.
///
/// 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<A>;
///
/// 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<string, unknown>;
/// type B<T> = T extends Record<infer K, any> ? K : never;
/// const x = 'foo' as B<A>;
/// console.log(x);
/// ```
///
/// Examples of **incorrect** code for `/* exported variableName */` operation:
/// ```javascript
/// ```js
/// /* exported global_var */
///
/// // Not respected, use ES6 modules instead.