Coder Social home page Coder Social logo

sindresorhus / eslint-plugin-unicorn Goto Github PK

View Code? Open in Web Editor NEW
3.9K 24.0 353.0 4.58 MB

More than 100 powerful ESLint rules

License: MIT License

JavaScript 99.84% EJS 0.16%
unicorns eslint-rules eslint-plugin eslint eslint-config linting-rules xo javascript nodejs

eslint-plugin-unicorn's Introduction

eslint-plugin-unicorn Coverage Status npm version

Unicorn

More than 100 powerful ESLint rules

You might want to check out XO, which includes this plugin.

Propose or contribute a new rule ➡

Install

npm install --save-dev eslint eslint-plugin-unicorn

Usage (eslint.config.js)

Requires ESLint >=8.23.0.

Use a preset config or configure each rule in eslint.config.js.

If you don't use the preset, ensure you use the same languageOptions config as below.

ES Module (Recommended)

import eslintPluginUnicorn from 'eslint-plugin-unicorn';
import * as eslintrc from '@eslint/eslintrc';

export default [
	{
		languageOptions: {
			globals: eslintrc.Legacy.environments.get('es2024'),
		},
		plugins: {
			unicorn: eslintPluginUnicorn,
		},
		rules: {
			'unicorn/better-regex': 'error',
			'unicorn/…': 'error',
		},
	},
	// …
];

CommonJS

'use strict';
const eslintPluginUnicorn = require('eslint-plugin-unicorn');
const eslintrc = require('@eslint/eslintrc');

module.exports = [
	{
		languageOptions: {
			globals: eslintrc.Legacy.environments.get('es2024'),
		},
		plugins: {
			unicorn: eslintPluginUnicorn,
		},
		rules: {
			'unicorn/better-regex': 'error',
			'unicorn/…': 'error',
		},
	},
	// …
];

Usage (legacy: .eslintrc.* or package.json)

Use a preset config or configure each rule in package.json.

If you don't use the preset, ensure you use the same env and parserOptions config as below.

{
	"name": "my-awesome-project",
	"eslintConfig": {
		"env": {
			"es2024": true
		},
		"parserOptions": {
			"ecmaVersion": "latest",
			"sourceType": "module"
		},
		"plugins": [
			"unicorn"
		],
		"rules": {
			"unicorn/better-regex": "error",
			"unicorn/…": "error"
		}
	}
}

Rules

💼 Configurations enabled in.
✅ Set in the recommended configuration.
🔧 Automatically fixable by the --fix CLI option.
💡 Manually fixable by editor suggestions.

Name                                    Description 💼 🔧 💡
better-regex Improve regexes by making them shorter, consistent, and safer. 🔧
catch-error-name Enforce a specific parameter name in catch clauses. 🔧
consistent-destructuring Use destructured variables over properties. 🔧 💡
consistent-function-scoping Move function definitions to the highest possible scope.
custom-error-definition Enforce correct Error subclassing. 🔧
empty-brace-spaces Enforce no spaces between braces. 🔧
error-message Enforce passing a message value when creating a built-in error.
escape-case Require escape sequences to use uppercase values. 🔧
expiring-todo-comments Add expiration conditions to TODO comments.
explicit-length-check Enforce explicitly comparing the length or size property of a value. 🔧 💡
filename-case Enforce a case style for filenames.
import-style Enforce specific import styles per module.
new-for-builtins Enforce the use of new for all builtins, except String, Number, Boolean, Symbol and BigInt. 🔧
no-abusive-eslint-disable Enforce specifying rules to disable in eslint-disable comments.
no-anonymous-default-export Disallow anonymous functions and classes as the default export. 💡
no-array-callback-reference Prevent passing a function reference directly to iterator methods. 💡
no-array-for-each Prefer for…of over the forEach method. 🔧 💡
no-array-method-this-argument Disallow using the this argument in array methods. 🔧 💡
no-array-push-push Enforce combining multiple Array#push() into one call. 🔧 💡
no-array-reduce Disallow Array#reduce() and Array#reduceRight().
no-await-expression-member Disallow member access from await expression. 🔧
no-await-in-promise-methods Disallow using await in Promise method parameters. 💡
no-console-spaces Do not use leading/trailing space between console.log parameters. 🔧
no-document-cookie Do not use document.cookie directly.
no-empty-file Disallow empty files.
no-for-loop Do not use a for loop that can be replaced with a for-of loop. 🔧 💡
no-hex-escape Enforce the use of Unicode escapes instead of hexadecimal escapes. 🔧
no-instanceof-array Require Array.isArray() instead of instanceof Array. 🔧
no-invalid-remove-event-listener Prevent calling EventTarget#removeEventListener() with the result of an expression.
no-keyword-prefix Disallow identifiers starting with new or class.
no-lonely-if Disallow if statements as the only statement in if blocks without else. 🔧
no-negated-condition Disallow negated conditions. 🔧
no-nested-ternary Disallow nested ternary expressions. 🔧
no-new-array Disallow new Array(). 🔧 💡
no-new-buffer Enforce the use of Buffer.from() and Buffer.alloc() instead of the deprecated new Buffer(). 🔧 💡
no-null Disallow the use of the null literal. 🔧 💡
no-object-as-default-parameter Disallow the use of objects as default parameters.
no-process-exit Disallow process.exit().
no-single-promise-in-promise-methods Disallow passing single-element arrays to Promise methods. 🔧 💡
no-static-only-class Disallow classes that only have static members. 🔧
no-thenable Disallow then property.
no-this-assignment Disallow assigning this to a variable.
no-typeof-undefined Disallow comparing undefined using typeof. 🔧 💡
no-unnecessary-await Disallow awaiting non-promise values. 🔧
no-unnecessary-polyfills Enforce the use of built-in methods instead of unnecessary polyfills.
no-unreadable-array-destructuring Disallow unreadable array destructuring. 🔧
no-unreadable-iife Disallow unreadable IIFEs.
no-unused-properties Disallow unused object properties.
no-useless-fallback-in-spread Disallow useless fallback when spreading in object literals. 🔧
no-useless-length-check Disallow useless array length check. 🔧
no-useless-promise-resolve-reject Disallow returning/yielding Promise.resolve/reject() in async functions or promise callbacks 🔧
no-useless-spread Disallow unnecessary spread. 🔧
no-useless-switch-case Disallow useless case in switch statements. 💡
no-useless-undefined Disallow useless undefined. 🔧
no-zero-fractions Disallow number literals with zero fractions or dangling dots. 🔧
number-literal-case Enforce proper case for numeric literals. 🔧
numeric-separators-style Enforce the style of numeric separators by correctly grouping digits. 🔧
prefer-add-event-listener Prefer .addEventListener() and .removeEventListener() over on-functions. 🔧
prefer-array-find Prefer .find(…) and .findLast(…) over the first or last element from .filter(…). 🔧 💡
prefer-array-flat Prefer Array#flat() over legacy techniques to flatten arrays. 🔧
prefer-array-flat-map Prefer .flatMap(…) over .map(…).flat(). 🔧
prefer-array-index-of Prefer Array#{indexOf,lastIndexOf}() over Array#{findIndex,findLastIndex}() when looking for the index of an item. 🔧 💡
prefer-array-some Prefer .some(…) over .filter(…).length check and .{find,findLast}(…). 🔧 💡
prefer-at Prefer .at() method for index access and String#charAt(). 🔧 💡
prefer-blob-reading-methods Prefer Blob#arrayBuffer() over FileReader#readAsArrayBuffer(…) and Blob#text() over FileReader#readAsText(…).
prefer-code-point Prefer String#codePointAt(…) over String#charCodeAt(…) and String.fromCodePoint(…) over String.fromCharCode(…). 💡
prefer-date-now Prefer Date.now() to get the number of milliseconds since the Unix Epoch. 🔧
prefer-default-parameters Prefer default parameters over reassignment. 🔧 💡
prefer-dom-node-append Prefer Node#append() over Node#appendChild(). 🔧
prefer-dom-node-dataset Prefer using .dataset on DOM elements over calling attribute methods. 🔧
prefer-dom-node-remove Prefer childNode.remove() over parentNode.removeChild(childNode). 🔧 💡
prefer-dom-node-text-content Prefer .textContent over .innerText. 💡
prefer-event-target Prefer EventTarget over EventEmitter.
prefer-export-from Prefer export…from when re-exporting. 🔧 💡
prefer-includes Prefer .includes() over .indexOf() and Array#some() when checking for existence or non-existence. 🔧 💡
prefer-json-parse-buffer Prefer reading a JSON file as a buffer. 🔧
prefer-keyboard-event-key Prefer KeyboardEvent#key over KeyboardEvent#keyCode. 🔧
prefer-logical-operator-over-ternary Prefer using a logical operator over a ternary. 💡
prefer-math-trunc Enforce the use of Math.trunc instead of bitwise operators. 🔧 💡
prefer-modern-dom-apis Prefer .before() over .insertBefore(), .replaceWith() over .replaceChild(), prefer one of .before(), .after(), .append() or .prepend() over insertAdjacentText() and insertAdjacentElement(). 🔧
prefer-modern-math-apis Prefer modern Math APIs over legacy patterns. 🔧
prefer-module Prefer JavaScript modules (ESM) over CommonJS. 🔧 💡
prefer-native-coercion-functions Prefer using String, Number, BigInt, Boolean, and Symbol directly. 🔧
prefer-negative-index Prefer negative index over .length - index when possible. 🔧
prefer-node-protocol Prefer using the node: protocol when importing Node.js builtin modules. 🔧
prefer-number-properties Prefer Number static properties over global ones. 🔧 💡
prefer-object-from-entries Prefer using Object.fromEntries(…) to transform a list of key-value pairs into an object. 🔧
prefer-optional-catch-binding Prefer omitting the catch binding parameter. 🔧
prefer-prototype-methods Prefer borrowing methods from the prototype instead of the instance. 🔧
prefer-query-selector Prefer .querySelector() over .getElementById(), .querySelectorAll() over .getElementsByClassName() and .getElementsByTagName(). 🔧
prefer-reflect-apply Prefer Reflect.apply() over Function#apply(). 🔧
prefer-regexp-test Prefer RegExp#test() over String#match() and RegExp#exec(). 🔧 💡
prefer-set-has Prefer Set#has() over Array#includes() when checking for existence or non-existence. 🔧 💡
prefer-set-size Prefer using Set#size instead of Array#length. 🔧
prefer-spread Prefer the spread operator over Array.from(…), Array#concat(…), Array#{slice,toSpliced}() and String#split(''). 🔧 💡
prefer-string-replace-all Prefer String#replaceAll() over regex searches with the global flag. 🔧
prefer-string-slice Prefer String#slice() over String#substr() and String#substring(). 🔧
prefer-string-starts-ends-with Prefer String#startsWith() & String#endsWith() over RegExp#test(). 🔧 💡
prefer-string-trim-start-end Prefer String#trimStart() / String#trimEnd() over String#trimLeft() / String#trimRight(). 🔧
prefer-switch Prefer switch over multiple else-if. 🔧
prefer-ternary Prefer ternary expressions over simple if-else statements. 🔧
prefer-top-level-await Prefer top-level await over top-level promises and async function calls. 💡
prefer-type-error Enforce throwing TypeError in type checking conditions. 🔧
prevent-abbreviations Prevent abbreviations. 🔧
relative-url-style Enforce consistent relative URL style. 🔧 💡
require-array-join-separator Enforce using the separator argument with Array#join(). 🔧
require-number-to-fixed-digits-argument Enforce using the digits argument with Number#toFixed(). 🔧
require-post-message-target-origin Enforce using the targetOrigin argument with window.postMessage(). 💡
string-content Enforce better string content. 🔧 💡
switch-case-braces Enforce consistent brace style for case clauses. 🔧
template-indent Fix whitespace-insensitive template indentation. 🔧
text-encoding-identifier-case Enforce consistent case for text encoding identifiers. 🔧 💡
throw-new-error Require new when throwing an error. 🔧

Deprecated Rules

See docs/deprecated-rules.md

Preset configs (eslint.config.js)

See the ESLint docs for more information about extending config files.

Note: Preset configs will also enable the correct language options.

Recommended config

This plugin exports a recommended config that enforces good practices.

ES Module (Recommended)

import eslintPluginUnicorn from 'eslint-plugin-unicorn';

export default [
		// …
		eslintPluginUnicorn.configs['flat/recommended'],
		{
			rules: {
				'unicorn/better-regex': 'warn',
			},
		},
];

CommonJS

'use strict';
const eslintPluginUnicorn = require('eslint-plugin-unicorn');

module.exports = [
		// …
		eslintPluginUnicorn.configs['flat/recommended'],
		{
			rules: {
				'unicorn/better-regex': 'warn',
			},
		},
];

All config

This plugin exports an all config that makes use of all rules (except for deprecated ones).

ES Module (Recommended)

import eslintPluginUnicorn from 'eslint-plugin-unicorn';

export default [
		// …
		eslintPluginUnicorn.configs['flat/all'],
		{
			rules: {
				'unicorn/better-regex': 'warn',
			},
		},
];

CommonJS

'use strict';
const eslintPluginUnicorn = require('eslint-plugin-unicorn');

module.exports = [
		// …
		eslintPluginUnicorn.configs['flat/all'],
		{
			rules: {
				'unicorn/better-regex': 'warn',
			},
		},
];

Preset configs (.eslintrc.* or package.json)

See the ESLint docs for more information about extending config files.

Note: Preset configs will also enable the correct parser options and environment.

Recommended config

This plugin exports a recommended config that enforces good practices.

{
	"name": "my-awesome-project",
	"eslintConfig": {
		"extends": "plugin:unicorn/recommended",
		"rules": {
			"unicorn/better-regex": "warn"
		}
	}
}

All config

This plugin exports an all config that makes use of all rules (except for deprecated ones).

{
	"name": "my-awesome-project",
	"eslintConfig": {
		"extends": "plugin:unicorn/all"
	}
}

Maintainers

Former

eslint-plugin-unicorn's People

Contributors

amedora avatar ariperkkio avatar bmish avatar brettz9 avatar evilebottnawi avatar fisker avatar fregante avatar futpib avatar jfmengels avatar jounqin avatar kachkaev avatar karaggeorge avatar lubien avatar manovotny avatar medusalix avatar mmkal avatar mrhen avatar noftaly avatar richienb avatar samverschueren avatar sindresorhus avatar st-ddt avatar stroncium avatar sudo-suhas avatar tristanhessell avatar voxpelli avatar willheslam avatar wu-s-john avatar xhmikosr avatar yash-singh1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eslint-plugin-unicorn's Issues

Exceptions to `no-process-exit` rule

Sometimes it does make sense to use process.exit():

process.on('uncaughtException', err => {
    console.error('Exception:', err);
    process.exit(1);
});
process.on('SIGINT', () => {
    console.log('Got SIGINT');
    process.exit(1);
});

I think we should make an exception when it's inside a process event listener.

Rule proposal: `no-for-loop`

Issuehunt badges

There's no reason to use normal for loops anymore for the common case.

The following:

const arr = ['foo', 'bar'];

for (let i = 0; i < arr.length; i++) {
  const el = arr[i];
  console.log(i, el);
}

Can now be written as:

const arr = ['foo', 'bar'];

for (const [i, el] of arr.entries()) {
  console.log(i, el);
}

Off-by-one errors is one of the most common bugs in software. Swift actually removed this completely from the language.

We could probably ignore reverse loops and other cases, but the common case like above is better written in the latter form.

@kevva @SamVerschueren @jfmengels @jamestalmage Thoughts?

futpib earned $100.00 by resolving this issue!

Import naming rule

I like the practice of assigning imports to variables that are camel-cased versions of the package name:

var objectAssign = require('object-assign');
var mapObj = require('map-obj');

We've been pretty consistent about using it in AVA, and I like knowing which package to lookup on npm without scrolling to the top (and I am disappointed when that doesn't work out).

There are exceptions though (perhaps so many it makes an enforcement rule impossible):

// shortening really long name
var throwsHelper = require('babel-plugin-throws-helper');

// reordering? maybe this only makes sense for packages with enforced prefixes.
var throwsHelperPlugin = require('babel-plugin-throws-helper');

// widely understood conventions
var _ = require('lodash');

Maybe the default should just be a warning?

Maybe there are just too many valid exceptions to make this worth it?

Maybe we could encourage a preferredVariableName section to package.json?

{
  "name": "lodash",
  "version": "x.x.x",
  "preferredVariableName": ["_", "lodash"]
}

As for handling ES2015 module imports: only apply to default imports.

A better `no-nested-ternary` rule

Issuehunt badges

Since it was denied in ESLint: eslint/eslint#3480

I think it would be better with a new rule that only errors on nested ternaries that are not wrapped in parens. For example: parens-wrapped-nested-ternary (a mouthful, but very descriptive).

Thoughts?


IssueHunt Summary

karaggeorge karaggeorge has been rewarded.

Backers (Total: $82.00)

Submitted pull Requests


Tips


IssueHunt has been backed by the following sponsors. Become a sponsor

`number-literal-case` rule

JS has different number literals. Casing is of course not enforced, because why would you want consistency or readable numbers?...

This rule should enforce lowercase literal identifier and uppercase value.

No option for this as none of the failing cases makes sense.

Should be auto-fixable.

Fail

0XFF
0xff
0Xff

0B11

0O10

Pass

0xFF

0b11

0o10

Prevent using `Error` when doing type-checking

I often forget to use a TypeError when doing type-checking in a module.

Example:

if (Array.isArray(foo)) {
    throw new Error('Expected an array');
}

Would be nice to error the conditional only does type-checking and prevent the use of Error. Custom errors should be allowed.

New to making ESLint rules? Check out this quick guide on how to get started.

Enforce `Buffer.from` instead of `new Buffer`

Since new Buffer() is being deprecated since Node.js >= 6, it might be nice if we could enforce this some day in the future. Not sure if it makes sense to already create this rule because ESLint can't target specific Node.js versions, right?

Allow disabling of `xo/no-abusive-eslint-disable` via a comment

Issuehunt badges

I don't think it's possible currently.


IssueHunt Summary

[
<
i
m
g

s
r
c

'
h
t
t
p
s
:
/
/
a
v
a
t
a
r
s
3
.
g
i
t
h
u
b
u
s
e
r
c
o
n
t
e
n
t
.
c
o
m
/
u
/
5
7
3
1
1
7
6
?
v

4
'

a
l
t

'
t
i
a
g
o
d
a
n
i
n
'

w
i
d
t
h

2
4

h
e
i
g
h
t

2
4

t
i
a
g
o
d
a
n
i
n
]
(
h
t
t
p
s
:
/
/
i
s
s
u
e
h
u
n
t
.
i
o
/
u
/
t
i
a
g
o
d
a
n
i
n
)

h
a
s

b
e
e
n

r
e
w
a
r
d
e
d
.

Backers (Total: $40.00)

Submitted pull Requests


Tips


IssueHunt has been backed by the following sponsors. Become a sponsor

`prefer-string-slice` rule

I prefer .slice() over .substr() and .substring(). .slice() has clearer behavior and has a counterpart with arrays. Also better to be consistent. Anything you do with .substr() or .substring() can be done with .slice().

Read more: http://stackoverflow.com/questions/2243824/what-is-the-difference-between-string-slice-and-string-substring

I'm aware we can't do type checking, but I think we can just assume a string when we see .substr() and .substring(). Worth the risk I think.

Thoughts?

`filename-case` rule false positive

spec/iss47-spec.js:9:1
  ✖   9:1   Filename is not in kebab case. Rename it to iss-47-spec.js  xo/filename-case

Should we maybe make an exception here? I don't see why we would enforce the number to be independent.

FileName is not in kebab case for gulpFile

Hey there,

I am using gulp-xo a gulp plugin for 'xo' which is essentially using eslint-plugin-xo and i am seeing following error when i tried to use gulp-xo.

This error is related to rule checking for kebab case and it seems like you guys are doing it and its from your end that this mistake is still there.

capture

Tell me what needs to be fixed so that i can go ahead with my work and FYI i cant rename gulpFile to gulp-file 🎋

Explicit length check

I want to enforce doing if (arr.length > 0) { over just if (arr.length) {. Same with !arr.length. I think we can safely assume .length is a number. I generally favor explicitness. Should be autofixable.

Rule proposal: no-labeled-statement

In JavaScript, there is a little known feature called labels, which allows to do the equivalent of gotos.

The reason I want to forbid this is two-fold:

  1. gotos are bad, and they should not be used
  2. But mostly, it has become really easy to write these labeled statements instead of writing objects, with the introduction of arrow functions.
const foo = value => { foo: value };

The previous excerpt does not return an object with a key foo, but returns a code block that will be executed and not do much.

The following should have been used instead, where we explicitly return an expression (due to the parentheses) that contains an object expression:

const foo = value => ({ foo: value });

I propose to write a rule, named samething like either no-labeled-statement or no-confusing-arrow-label (hint to the existing no-confusing-arrow) where the error message would warn against using labels in arrow functions, and maybe advising to wrap the returned block. Depending on the name we choose, this will forbid labeled statements altogether (they are bad anyway) or just those underneath an arrow function.

Unfortunately, this rule would still not be able to help with the following...

const foo = value => { value };

PS: I think we should have a GitHub label for rule proposals yet to be accepted. Sounds good?

`escape-case` rule

In JS you can write escapes with either uppercase or lowercase value. Would be useful to have a rule to enforce the value to be uppercase. Don't want an option for this as lowercase is a bad practice.

For example \xa9 and \xA9 are equivalent, but the latter is clearer. \ud834\udf06 and \uD834\uDF06 are too.

The following should be supported (the values are just there as an example):

  • \xA9
  • \uD834
  • \u{1D306}
  • \cA

Suggestions for a better rule name?

Alternative: uppercase-escape

Would be useful if it works in a regex too, though not essential for the first version: https://github.com/sindresorhus/filename-reserved-regex/blob/af9c88cd73ba944ec27c64173aa9017ec80e7d2a/index.js#L4

Should also be possible to auto-fix it, right?

`filename-case` rule

Enforce a case style for file names

Enforces all linted files to have their names in a certain case style.

  • camelCase: fooBar.js (default)
  • snakeCase: foo_bar.js
  • kebabCase: foo-bar.js

Options

You can set the option in configuration like this:

"stuff/filename-case": ["error", {"case": "camelCase"}]

I have just written it, thinking I would put it in a new random stuff plugin, but if you guys are interested in putting this in XO, I don't mind adding it here (I'm starting to have way too many plugins in my dev folder anyway...).

I'm thinking of adding an option to check the folder names up to the package.json too.

What do you think?

Rule proposal: `no-unnecessary-polyfills`

Issuehunt badges

A rule that examines the engine argument of package.json, and keeps a list of poly/ponyfills and which Node version makes them obsolete.

For instance, if you're using object-assign, but only targeting Node 4 and higher, just use native Object.assign. Many others.


IssueHunt Summary

mesteery mesteery has been rewarded.

Backers (Total: $120.00)

Submitted pull Requests


Tips

NPM package out of date

Hi @sindresorhus! Just noticed that the NPM package does not contain all of the rules present in the repo at the time of writing this. Is it possible to slate a new release with the new features?

Thanks for putting this together. It's a great little module 🍻

Publish 1.0.0?

Shall we publish v1.0.0?
I noticed explicit-length-check was added a month and a half ago, but still not published. (I tried adding it to one of my projects, that's how I noticed)
There are some breaking changes, so it's a good opportunity to bump the major version.
Or do you want to wait until #43 is done?

Enforce error message style

avajs/ava#835 (comment)

I want to say: This is a failure, you should use a blimp

Which of the following should it be:

  • This is a failure, you should use a blimp
  • This is a failure. You should use a blimp
  • This is a failure. You should use a blimp.

Keep in mind that if we go for the last one, which looks the best, it becomes inconsistent with one sentence error messages, which usually don't end in a dot.

Rule proposal: Disallow switch cases with multiple options

What I'd wish to disallow is the following:

switch (foo): {
  case 1:
  case 2:
    return bar()
  case 3:
  default:
    baz()
}

in favor of

switch (foo): {
  case 1:
    return bar();
  case 2:
    return bar();
  case 3:
    baz();
    break;
  default:
    baz();
}

I agree that the former version is better, but there is one case where the second is better, and that is code coverage.

Current coverage tools put markers on every statement / branches, and when the code passes through it, it considers that line/branch as reached and increments the code coverage. Kind of like this:

switch (foo): {
  case 1:
    incrementCodeCoverageForLine(1);
  case 2:
    incrementCodeCoverageForLine(2);
    return bar();
  case 3:
    incrementCodeCoverageForLine(3);
  default:
    incrementCodeCoverageForLine(4);
    baz();
}

The problem is how that works when you have switch statements with multiple "conditions". If we take this example (equal to the example that I'd like to disallow), if foo equals 1, then we'd pass through both incrementCodeCoverageForLine(1) and incrementCodeCoverageForLine(2) statements, and the coverage is cheated. If we separated the conditions and enforced having either a return or break statement in each case, then the code coverage is a lot more reliable.

I noticed this when working on this file where I noticed that (before fixing it) a lot of cases were actually not covered.

If we do this, we should probably mention that this should only be used when 100% code coverage is important, and discourage it otherwise.

Enforce import index style

I want to enforce require('.'); and from '.';. Before Node.js 4 you had to do './'. In Node.js 4 you can do: '.'.

Should catch the following cases:

  • './'
  • './index'
  • './index.js'

Should be easy to implement auto-fixing for this rule.

Should we even care what the type of the Error is?

See here: https://github.com/sindresorhus/eslint-plugin-xo/blob/master/rules/throw-new-error.js#L3-L11

We filter on only that list of Errors. Shouldn't we just be asking that they either:

  1. Rethrow an error that was passed in.
  2. Use new

All these should be an error, right:

throw 'foo';
throw {};
var x = [];
throw x;

That last one might be hard to detect. So maybe throwing an identifier is just allowed, and we don't try static analysis.

I guess it would prevent this:

throw utils.buildError()

But I think that's an odd construct.

Rule proposal: Enforce correct Error subclassing

There are many things people do wrong when subclassing an error. We only care about the class syntax in this rule.

Useless this.message assignment:

class CustomError extends Error {
	constructor(message) {
		super(message);
		this.message = message;
		this.name = this.constructor.name;
	}
}

Could just be:

class CustomError extends Error {
	constructor(message) {
		super(message);
		this.name = this.constructor.name;
	}
}

Forgetting to set this.name

class CustomError extends Error {
	constructor(message) {
		super(message);
	}
}

Without it just displays Error when thrown. Should be:

class CustomError extends Error {
	constructor(message) {
		super(message);
		this.name = this.constructor.name;
	}
}

Forgetting to pass message to super()

class CustomError extends Error {
	constructor(message) {
		super();
		this.message = message;
		this.name = this.constructor.name;
	}
}

Should be:

class CustomError extends Error {
	constructor(message) {
		super(message);
		this.name = this.constructor.name;
	}
}

Use this.constructor.name

class CustomError extends Error {
	constructor() {
		super();
		this.name = this.constructor.name;
	}
}

instead of manually writing the name:

class CustomError extends Error {
	constructor() {
		super();
		this.name = 'CustomError';
	}
}

Less chance for a typo/inconsistency between them.


Should be auto-fixable.


Thoughts? Any other things we should include? Name suggestion?

Enforce error name in `catch`

I want to enforce the use of err as the error name in try/catch and promises:

try {} catch (err) {}
foo.catch(err => {});

Should be easy to make it fixable.

Rule proposal: No variable named after special name

In my codebase at work, I often see variables/params named as module which is kind of dangerous in my opinion.

I'd like to propose a rule that forbids the use of "reserved" variables, or at least the "special" variables, such as: module, exports, global, window (?), ...

I'd also like to see the same thing but for node core modules, like fs, path, that would forbid the following for instance

var path = '/foo/bar';

Not sure if we'd want that in a new rule or behind a flag. I'm leaning towards the latter.

Enforce length check style in the `explicit-length-check` rule

explicit-length-check checks that length properties get compared to a value instead of checking the truthiness of the property.

In avajs/eslint-plugin-ava#149 (review), we remembered that there are some opinions on how that value then gets compared 😅

For instance:

a.length === 0
// vs
a.length < 1 // not sure I've ever seen this one TBH

a.length !== 0
// vs
a.length > 0
// vs
a.length >= 1

// + some I might have forgotten

It could be nice to be able to specify how you want your comparisons to be made, and make that consistent across your project.

I'm not sure what the options would look like. At the top of my head, I'm thinking:

{
  "unicorn/explicit-length-check": ["error", {
    "empty": ["eq", 0] | ["lt", 1], // one or the other
    "not-empty": ["ne", 0] | ["gt", 0] | ["gte", 1]
  }]
}

Should one be omitted (empty for instance), then you'd simply get no errors reports on how that one gets checked (both a.length < 1 a.length === 0 would be fine).

This sounds pretty complicated at the moment (especially if we want to support == too), so I'm not too fond of it at the moment, especially it would not make sense to have empty: ["equal", 1200] as the config. Maybe we could simplify it to

{
  "unicorn/explicit-length-check": ["error", {
    "empty": "eq" | "lt",
    "not-empty": "ne" | "gt" | "gte"
  }]
}

and then we have predefined values associated to each of those operators. We could also have longer names for the operators, but you'd then get greater-than-or-equal (which is okay, but pretty long).

I'm kind of proposing this system so that we could have the same system for a different rule checking the indexOf uses. It might be nice to think of a similar "API" for it.

Oh, and obviously, this should not report any check for specific indices: a.length === 2 and a.length == 2 should always be fine, whatever the settings may be.

prefer-starts-ends-with crashes

I've tried new rule from eslint-plugin-unicorn, but it crashes.

Cannot read property 'name' of undefined
TypeError: Cannot read property 'name' of undefined
    at EventEmitter.CallExpression (/Users/dikmax/workspace/project/app/node_modules/eslint-plugin-unicorn/rules/prefer-starts-ends-with.js:16:23)
    at emitOne (events.js:82:20)
    at EventEmitter.emit (events.js:169:7)
    at NodeEventGenerator.enterNode (/Users/dikmax/workspace/project/app/node_modules/eslint/lib/util/node-event-generator.js:39:22)
    at CodePathAnalyzer.enterNode (/Users/dikmax/workspace/project/app/node_modules/eslint/lib/code-path-analysis/code-path-analyzer.js:607:23)
    at CommentEventGenerator.enterNode (/Users/dikmax/workspace/project/app/node_modules/eslint/lib/util/comment-event-generator.js:98:23)
    at Controller.enter (/Users/dikmax/workspace/project/app/node_modules/eslint/lib/eslint.js:928:36)
    at Controller.__execute (/Users/dikmax/workspace/project/app/node_modules/eslint/node_modules/estraverse/estraverse.js:397:31)
    at Controller.traverse (/Users/dikmax/workspace/project/app/node_modules/eslint/node_modules/estraverse/estraverse.js:501:28)
    at Controller.Traverser.controller.traverse (/Users/dikmax/workspace/project/app/node_modules/eslint/lib/util/traverser.js:36:33)

Link to line with error

It could be because of babel-eslint parser. But anyway rule should not crash.

`func-style` like rule

See: http://eslint.org/docs/rules/func-style

My personal preference is to prefer declaration style, as it allows hoisting (and just looks better to me). The only issue is when you want to reassign:

var func = function () {

}

if (someCondition) {
  func = wrap(func);
}

ESLint's func-style rule does not accommodate the above exception when preferring declarations, so it is impractical to enforce.


Note:

You can get around ELint's rule by doing this:

var func; // don't initialize variable here, do it on the next line

func = function () {

}

But that feels impractical.


Do we feel it's worth enforcing func-style in XO? Should we use the builtin plugin to do so, or make our own that is a bit more permissive.

`prefer-includes` rule

Issuehunt badges

Prefer .includes() over .indexOf() when checking for existence. Since ESLint has no type analysis we'll have to assume all properties named .indexOf() have a .includes() counterpart. This is luckily true for all builtins: String#includes, Array#includes, TypedArray#includes, Buffer#includes.

See eslint/eslint#4209 for more.

.includes() cases:

  • 'foobar'.indexOf('foo') !== -1
  • 'foobar'.indexOf('foo') != -1
  • 'foobar'.indexOf('foo') > -1
  • 'foobar'.indexOf('foo') >= 0

New to making ESLint rules? Check out this quick guide on how to get started.

prbart earned $42.00 by resolving this issue!

Enforce "must use new" check inside constructor functions.

ES2015 Classes throw an error if you don't use new to instantiate them.

We have begun performing the same check manually in non-es2015 constructors, using a simple if(!(this instance of ...)) check. It would be good to enforce that check if the function name was capitalized.

New to making ESLint rules? Check out this quick guide on how to get started.

`no-useless-template` rule

I would like to prevent use of template literals when not needed. It's only needed when it contains an expansion ${} or literal newlines.

We could also consider supporting the case of using template literal to reduce escaping when you for example enforce single-quotes, but the string also contains single-quotes. This would have to be an option where to user specifics the preferred quote type as we're not allowed to read it from the quotes rule.

Should be fixable.

Thoughts? (Anyone)


Example of when it would have been useful: #67 (comment)

callback-error rule

I was wondering if we could have no-callback-literal rule to correspond with the no-throw-literal rule.

Basically, if you're using the callback pattern this should never be okay:

callback('error')

instead you should do something more like this:

callback(new Error('error'))

You can see the code here:
standard/eslint-plugin-standard#15

`prefer-starts-ends-with` rule

.startsWith instead of:

  • foo.indexOf('bar') === 0
  • foo[0] === 'b'
  • foo.charAt(0) === 'b' (and foo.charAt())
  • foo.slice(0, 2) === 'bar' (and .substring & .substr)
  • /^bar/.test(foo) (and .match())

.endsWith instead of:

  • .lastIndexOf
  • foo[foo.length - 1] === 'r'
  • foo.charAt(foo.length - 1) === 'b'
  • foo.slice(0, -3) === 'bar' (and .substring & .substr)
  • /bar$/.test(foo) (and .match())

The regex case is especially useful as I've seen a lot of regexes used in this scenario.

New to making ESLint rules? Check out this quick guide on how to get started.

`return-early` rule

As discussed in sindresorhus/execa#15 (diff). How I think when coding is to handle errors and exceptions as soon as possible and return early. If we take a look at the two examples below, the latter one makes more sense to me. foobar() in this case is the "real" body while the code in the if statements deal with exceptions. When using the style in the former one, this isn't as clear to me.

if (conditon) {
    someFn();
} else if (someOtherCondition) {
    someOtherFn();
} else {
    foobar();
}
if (condition) {
    someFn();
    return;
}

if (someOtherCondition) {
    someOtherFn();
    return;
}

foobar();

This might be worth reading too http://blog.timoxley.com/post/47041269194/avoid-else-return-early.

Node module specific rules

Would be cool to enforce some best practices and prevention of common pitfalls on the most popular Node.js modules.

For example, with meow I want to enforce using a template literal instead of a normal string as the first argument.

I'm thinking we can activate the rule if we detect an import of the specific module.

Any requests? Common pitfalls you've seen? Best practices?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.