Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

☂️ Proposed lint rules, from other sources #2741

Closed
1 of 90 tasks
ematipico opened this issue Jun 20, 2022 · 2 comments
Closed
1 of 90 tasks

☂️ Proposed lint rules, from other sources #2741

ematipico opened this issue Jun 20, 2022 · 2 comments
Labels
A-Linter Area: linter umbrella Issue to track a collection of other issues

Comments

@ematipico
Copy link
Contributor

ematipico commented Jun 20, 2022

Note

The teams decided that they prefer to tackle this rules only after #2642 is closed

Description

These are proposed lint rules that come from other sources. They are proposed, they might require a brief discussion for the following reasons:

  • they might come from eslint, which have a "configuration" per rule. Rome doesn't have a configuration per rule, which means that we might not be able to implement it of we might need to write a default version of that rule, that's why a discussion/decision might be needed;
  • they might come from a different language, where some cases might not apply to TS/JS. So it requires to understand the rule and try to apply it to JS/TS

If you want to contribute

  1. make sure you understand the requirements of the rule you would like to implement;
  2. comment on this very issue telling saying which rule you would like to implement;
  3. create a new task issue and link to this very umbrella issue (a member of the team will eventually assign it to you);
  4. open a PR;

Note: please make sure to comment the issue saying which rule you'd like to implement, this would allow better coordination between contributors. Failing to do so would penalize yourselves against contributors that had followed these simple guildelines

Note: follow the naming convention guidelines: https://github.com/rome/tools/blob/archived-js/CONTRIBUTING.md#naming-patterns

ESLint

  • feat(rome_analyze): implement the validTypeof rule #2649
    Enforces comparing typeof expressions against valid strings
    Can provide auto-fixes if the result of typeof is being compared to a well-known constant
    Example fixes:
    typeof a === String -> typeof a === "string"
    typeof a === undefined -> typeof a === "undefined"
  • dot-notation
    Enforces dot notation instead of square bracket notation for member access with static names
    Example fix:
    foo["bar"] -> foo.bar
  • no-else-return
    Disallow else blocks for if statements ending with a return
    Example fix:
    if (a) { return 1; } else { return 2; } -> if (a) { return 1; } return 2;
  • no-extra-bind
    Disallow calling .bind() on functions that never access this
  • no-extra-label
    Disallow using single-level deep labelled breaks
    Example fix:
    label: while(true) { break label; } -> while(true) { break; }
  • no-implicit-coercion
    Disallow shorthand type conversions
    Example fixes:
    !!cond -> Boolean(cond)
    +num -> Number(num)
  • no-lonely-if
    Disallow if statements as the only statement in an else block
    Example fix:
    if (a) {} else { if (b) {} } -> if (a) {} else if (b) {}
  • no-unneeded-ternary
    Disallow ternary expressions when a simpler alternative exists
    Example fixes:
    cond === 4 ? true : false -> cond === 4
    value ? value : 4 -> value || 4
  • no-unused-labels
    Enforces labeled statements are referenced by a labelled break
  • no-useless-computed-key
    Disallow computed keys with literals in object expressions
    Example fix:
    { ["a"]: "b" } -> { a: "b" }
  • no-useless-rename
    Disallow aliasing a symbol to the same identifier in object patterns and import / export statements
    Example fixes:
    const { a: a } = obj; -> const { a } = obj;
    import { a as a } from "source"; -> import { a } from "source";
    export { a as a }; -> export { a };
  • no-useless-return
    Disallow returning undefined as the terminating statement of a function
    Example fix:
    function foo() { stmt(); return; } -> function foo() { stmt(); }
  • object-shorthand
    Enforce shorthand syntax in object expressions
    Example fixes:
    const obj = { a: a }; -> const obj = { a };
    const obj = { a: function() {} }; -> const obj = { a() {} };
  • operator-assignment
    Enforces the use of shorthand operator assignment
    Example fix:
    a = a + b; -> a += b;
  • prefer-arrow-callback
    Prefer arrow functions to function expressions
    Example fix:
    .then(function (res) {}) -> .then((res) => {})
  • prefer-destructuring
    Prefer destructuring patterns for array and objects
    Example fix:
    const a = array[0]; -> const [a] = array;
    const a = object.a; -> const { a } = object;
  • prefer-exponentiation-operator
    Prefer using the exponentiation operator to calling Math.pow
    Example fix:
    Math.pow(a, b) -> a ** b
  • prefer-numeric-literals
    Disallow calling parseInt with string literals
    Example fixes:
    parseInt("23") -> 23
    parseInt("10111", 2) -> 0b10111
    parseInt("27", 8) -> 0o27
    parseInt("17", 16) -> 0x17
  • prefer-object-has-own
    Prefer Object.hasOwn() over Object.prototype.hasOwnProperty.call()
    Example fix:
    Object.prototype.hasOwnProperty.call(obj, "a") -> Object.hasOwn(obj, "a")
  • prefer-object-spread
    Prefer object spread members to calling Object.assign
    Example fix:
    Object.assign({}, foo, { bar: 'baz' }) -> { ..foo, bar: 'baz' }
  • prefer-regex-literals
    Disallow calling the RegExp constructor with string literals
    Example fix:
    new RegExp("abc", "u") -> /abc/u
  • yoda
    Enforces literals are in the right hand side of comparison operations
    Example fix:
    if ("red" === color) {} -> if (color === "red") {}

ESLint Typescript

  • ban-types
    Disallow the uppercase primitive types
    Example fixes:
    let foo: String; -> let foo: string;
    let foo: Boolean; -> let foo: boolean;
    Example errors:
    let foo: Function;
    let foo: Object;
  • no-confusing-non-null-assertion
    Disallows non-null assertion in locations that may be confusing
    Example fix:
    a! == b -> (a!) == b
  • no-empty-interface
    Disallows the declaration of empty interfaces
    Example fixes:
    interface Foo {} -> type Foo = {};
    interface Bar extends Foo {} -> type Bar = Foo;
  • no-explicit-any
    Disallows the any type
    Example error:
    const age: any = 'seventeen';
  • no-extra-non-null-assertion
    Disallows extra non-null assertion
    Example fix:
    foo!!!.bar -> foo!.bar
  • no-inferrable-types
    Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean
    Example fix:
    const a: number = 10; -> const a = 10;
  • no-useless-empty-export
    Disallows empty exports that don't change anything in a module file
    Example fix:
    export const value = 'Hello, world!'; export {}; -> export const value = 'Hello, world!';
  • prefer-as-const
    Enforces the use of as const over literal type
    Example fix:
    let foo = 'bar' as 'bar'; -> let foo = 'bar' as const;
  • prefer-function-type
    Enforces using function types instead of interfaces with call signatures
    Example fix:
    interface Foo { (): string; } -> type Foo = () => string;
  • prefer-namespace-keyword
    Requires using namespace keyword over module keyword to declare custom TypeScript modules

Clippy

  • collapsible_if
    Checks for nested if statements that can be collapsed by combining their conditions
    Example fix:
    if (a) { if (b) {} } -> if (a && b) {}
  • double_comparison
    Check for comparison operation that could be combined
    Example fix:
    a == b || a < b -> a <= b
  • flat_map_identity
    Check for usage of pass-through functions with flatMap
    Example fix:
    .flatMap(x => x) -> .flat()
  • int_plus_one
    Check for comparisons against plus-one or minus-one operations
    Example fix:
    a >= b + 1 -> a > b
  • let_and_return
    Check for variable declarations that are immediately returned
    Example fix:
    let a = "value"; return a; -> return "value";
  • map_flatten
    Check for calls to map followed by a call to flat
    Example fix:
    .map(func).flat() -> .flatMap(func)
  • match_str_case_mismatch
    Check for comparison operation against literals with mismatched case
    Example fix:
    a.toLowerCase() === "Test" -> .toLowerCase() === "test"
    switch(a.toLowerCase()) { case "Test": break; } -> switch(a.toLowerCase()) { case "test": break; }
  • needless_for_each
    Check for usage of forEach that could be written as for loops
    Example fix:
    array.forEach(elem => {}) -> for(const elem of array) {}
  • neg_multiply
    Checks for multiplication by -1 as a form of negation
    Example fix:
    foo * -1 -> -foo
  • question_mark
    Checks for expressions that could be replaced with optional chaining operations
    Example fix:
    if(a && a.b) { a.b(); } -> a?.b?.();
  • redundant_closure
    Check for closures that just call another function with the same signature
    Example fix:
    .map(item => foo(item)) -> .map(foo)
  • search_is_some
    Search for iterator or string search followed by a comparison to -1
    Example fix:
    .indexOf(value) !== -1 -> .includes(value)
    .findIndex(func) !== -1 -> .some(func)
  • short_circuit_statement
    Checks for the use of short circuit boolean conditions as a statement
    Example fix:
    a() && b(); -> if (a()) { b(); }
  • single_element_loop
    Checks whether a for loop has a single element
    Example fix:
    for(const item of [item1]) {} -> const item = item1;
  • suboptimal_flops
    Checks for floating-point operations that can be expressed using built-in functions
    Example fixes:
    Math.E ** value -> Math.exp(value)
    value ** 0.5 -> Math.sqrt(value)
    value < 0 ? -value : value -> Math.abs(value)
  • unnecessary_fold
    Checks for use of reduce when a more succinct alternative exists
    Example fix:
    .reduce((acc, item) => acc || item > 2, false) -> .some(item => item > 2)
    .reduce((acc, item) => acc && item > 2, true) -> .every(item => item > 2)

Other Recommended Rules

ESLint

  • constructor-super
    Verify super() is called in constructors of derived classes, and not called in constructor of non-derived classes (this rule also tries to check if the extends reference is a valid class but this is better left to a typechecker)
    Example errors:
    class A extends B { constructor() {} }
    class A { constructor() { super(); } }
  • for-direction
    Check the condition and update of for loops to detect infinite loops
    Example error:
    for (let i = 0; i < 10; i--) {}
    for (let i = 0; i > 10; i++) {}
  • getter-return
    Enforce that getter functions have a return statement on all exit paths
    Example error:
    const obj = { get prop() {} };
  • no-async-promise-executor
    Disallow async functions as Promise executors
    Example error:
    new Promise(async (resolve, reject) => {})
  • no-class-assign
    Disallow assigning to the variable created by a class declaration
    Example error:
    class A {}; A = 0;
  • no-cond-assign
    Disallow assignment expression in conditions
    Example error:
    if(a = "b") {}
  • no-const-assign
    Disallow assigning to constant bindings
    Example error:
    const a = 10; a = 0;
  • no-dupe-args
    Disallow multiple arguments of the same function from having the same name
    Example error:
    function (a, b, a) {}
  • no-dupe-class-members
    Disallow multiple members of the same class from having the same name
    Example error:
    class A { foo() {}; foo() {} }
  • no-dupe-else-if
    Disallow multiple if statements in the same chain from having the same condition
    Example errors:
    if (a) {} else if (b) {} else if (a) {}
  • no-dupe-keys
    Disallow multiple members in the same object expression from having the same name
    Example error:
    const obj = { foo: 'bar', foo: 'baz' };
  • no-duplicate-case
    Disallow multiple case clauses in the same switch statement from having the same condition
    Example error:
    switch(a) { case 1: break; case 2: break; case 1: break; }
  • no-empty-character-class
    Disallow empty character classes in RegExp literals
    Example error:
    /abc[]/
  • no-empty-pattern
    Disallow empty destructuring patterns
    Example errors:
    const {} = object;
    const [] = array;
  • no-ex-assign
    Disallow assigning to the exception binding in a catch clause
    Example error:
    try {} catch (err) { err = 10; }
  • no-fallthrough
    Disallow fallthrough between case clauses in switch statements
    Example error:
    switch (a) { case 1: stmt(); case 2: stmt(); }
  • no-func-assign
    Disallow assigning to the variable created by a function declaration
    Example error:
    function a() {}; a = 0;
  • no-import-assign
    Disallow assigning to the binding created by an import
    Example error:
    import { a } from "source"; a = 0;
  • no-inner-declarations
    Disallow function declarations in nested statements
    Example error:
    if (a) { function foo() {} }
  • no-irregular-whitespace
    Disallow all whitespace characters that are not spaces or tabulations
  • no-loss-of-precision
    Disallow numeric literals whose value cannot be accurately represented by a double precision float
    Example error:
    5123000000000000000000000000001
  • no-misleading-character-class
    Disallows characters which are made with multiple code points in character class syntax
    Example error:
    /[❇️]/
  • no-new-symbol
    Disallows calling the Symbol function as a constructor
    Example error:
    new Symbol("foo")
  • no-obj-calls
    Disallows calling global builtin objects as functions (this might be better suited for a typechecker ?)
    Example errors:
    Math()
    JSON()
  • no-prototype-builtins
    Disallow calling methods from Object.prototype directly on object instances
    Example error:
    foo.hasOwnProperty("bar")
  • no-self-assign
    Disallow assigning a variable to itself
    Example error:
    foo = foo;
  • no-setter-return
    Disallow returning a value in a setter
    Example error:
    const obj = { set prop(value) { this._value = value; return value; } };
  • no-this-before-super
    Disallow using this before calling super in a derived class
    Example error:
    class A extends B { constructor() { this.foo = "bar"; super(); } }
  • no-undef
    Disallow the use of undeclared variables
  • no-unreachable
    Disallow code that is statically known to be never reached by control flow
    Example error:
    function foo() { return; stmt(); }
  • no-unsafe-finally
    Disallow control flow statement in finally blocks
    Example error:
    try {} finally { return; }
  • no-unsafe-optional-chaining
    Disallows optional chaining in contexts where undefined is not allowed (this might be better suited for a typechecker ?)
    Example errors:
    "key" in obj?.foo
    inst instanceof obj?.foo
    (obj?.foo)()
    (obj?.foo).bar
  • no-unused-vars
    Disallow unused variables
  • no-useless-backreference
    Disallows useless backreferences in regular expressions
  • use-isnan
    Requires calling isNaN when comparing to NaN
    Example error:
    foo == NaN

ESLint React Hooks

  • rules-of-hooks
    Checks that React Hooks are not called in non-constant control flow
    Example error:
    function Component({ prop }) { if(prop) { useEffect(); } }
  • exhaustive-deps
    Checks the dependencies array of React Hooks contains all referenced bindings
    Example error:
    function Component({ prop }) { useEffect(() => { prop(); }, []); }

Clippy

  • logic_bug
    Check for redundant or constant terminals in binary expressions
    Example error:
    a && b || a
  • never_loop
    Check for loops that never actually loop
    Example error:
    while (true) { break; }
  • while_immutable_condition
    Check for loops that never mutate their condition
    Example error:
    let i = 0; while (i < 10) { stmt(); }
  • min_max
    Check for nested min-max calls where the values used for clamping are swapped
    Example error:
    Math.min(Math.max(value, 1), 0)
  • out_of_bounds_indexing
    Check for constant out-of-bounds indices
    Example error:
    const array = [1, 2]; array[8];
@ematipico ematipico added umbrella Issue to track a collection of other issues A-Linter Area: linter labels Jun 20, 2022
@github-actions
Copy link

This issue is stale because it has been open 14 days with no activity.

@github-actions
Copy link

github-actions bot commented Oct 4, 2022

This issue is stale because it has been open 14 days with no activity.

@ematipico ematipico removed the S-Stale label Oct 4, 2022
@rome rome locked and limited conversation to collaborators Oct 7, 2022
@ematipico ematipico converted this issue into discussion #3357 Oct 7, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
A-Linter Area: linter umbrella Issue to track a collection of other issues
Projects
Status: Done
Development

No branches or pull requests

1 participant