Skip to content

Commit

Permalink
Merge e7e49ec into ae983e2
Browse files Browse the repository at this point in the history
  • Loading branch information
pull[bot] committed Mar 11, 2020
2 parents ae983e2 + e7e49ec commit b19da20
Show file tree
Hide file tree
Showing 20 changed files with 716 additions and 63 deletions.
11 changes: 6 additions & 5 deletions docs/rules/catch-error-name.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# Enforce a specific parameter name in catch clauses

Applies to both `try/catch` clauses and `promise.catch(...)` handlers.
Applies to both `try/catch` clauses and `promise.catch()` handlers.

The desired name is configurable, but defaults to `error`.

This rule is fixable unless the reported code was destructuring an error.


## Fail

```js
Expand All @@ -21,7 +20,6 @@ try {
somePromise.catch(e => {})
```


## Pass

```js
Expand Down Expand Up @@ -74,7 +72,6 @@ somePromise.catch(_ => {
});
```


## Options

### name
Expand All @@ -101,7 +98,7 @@ You can set the `name` option like this:
]
```

This option lets you specify a regex pattern for matches to ignore. The default is `^_$`.
This option lets you specify a regex pattern for matches to ignore. The default allows `_` and descriptive names like `networkError`.

With `^unicorn$`, this would fail:

Expand All @@ -122,3 +119,7 @@ try {
//
}
```

## Tip

In order to avoid shadowing in nested catch clauses, the auto-fix rule appends underscores to the identifier name. Since this might be hard to read, the default setting for `caughtErrorsIgnorePattern` allows the use of descriptive names instead, for example, `fsError` or `authError`.
78 changes: 78 additions & 0 deletions docs/rules/string-content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Enforce better string content

Enforce certain things about the contents of strings. For example, you can enforce using `` instead of `'` to avoid escaping. Or you could block some words. The possibilities are endless.

This rule is fixable.

*It only reports one pattern per AST node at the time.*

## Fail

```js
const foo = 'Someone\'s coming!';
```

## Pass

```js
const foo = 'Someone’s coming!';
```

## Options

Type: `object`

### patterns

Type: `object`

Extend [default patterns](#default-pattern).

The example below:

- Disables the default `'``` replacement.
- Adds a custom `unicorn``🦄` replacement.
- Adds a custom `awesome``😎` replacement and a custom message.
- Adds a custom `cool``😎` replacement, but disables auto fix.

```json
{
"unicorn/string-content": [
"error",
{
"patterns": {
"'": false,
"unicorn": "🦄",
"awesome": {
"suggest": "😎",
"message": "Please use `😎` instead of `awesome`."
},
"cool": {
"suggest": "😎",
"fix": false
}
}
}
]
}
```

The key of `patterns` is treated as a regex, so you must escape special characters.

For example, if you want to enforce `...```:

```json
{
"patterns": {
"\\.\\.\\.": ""
}
}
```

## Default Pattern

```json
{
"'": ""
}
```
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ module.exports = {
'unicorn/prefer-trim-start-end': 'error',
'unicorn/prefer-type-error': 'error',
'unicorn/prevent-abbreviations': 'error',
'unicorn/string-content': 'off',
'unicorn/throw-new-error': 'error'
}
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-unicorn",
"version": "16.1.1",
"version": "17.1.0",
"description": "Various awesome ESLint rules",
"license": "MIT",
"repository": "sindresorhus/eslint-plugin-unicorn",
Expand Down
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Configure it in `package.json`.
"unicorn/prefer-trim-start-end": "error",
"unicorn/prefer-type-error": "error",
"unicorn/prevent-abbreviations": "error",
"unicorn/string-content": "off",
"unicorn/throw-new-error": "error"
}
}
Expand Down Expand Up @@ -132,6 +133,7 @@ Configure it in `package.json`.
- [prefer-trim-start-end](docs/rules/prefer-trim-start-end.md) - Prefer `String#trimStart()` / `String#trimEnd()` over `String#trimLeft()` / `String#trimRight()`. *(fixable)*
- [prefer-type-error](docs/rules/prefer-type-error.md) - Enforce throwing `TypeError` in type checking conditions. *(fixable)*
- [prevent-abbreviations](docs/rules/prevent-abbreviations.md) - Prevent abbreviations. *(partly fixable)*
- [string-content](docs/rules/string-content.md) - Enforce better string content. *(fixable)*
- [throw-new-error](docs/rules/throw-new-error.md) - Require `new` when throwing an error. *(fixable)*

## Deprecated Rules
Expand Down
8 changes: 4 additions & 4 deletions rules/better-regex.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ const create = context => {
const newPattern = cleanRegexp(oldPattern, flags);

if (oldPattern !== newPattern) {
// Escape backslash
const fixed = quoteString(newPattern.replace(/\\/g, '\\\\'));

context.report({
node,
message,
data: {
original: oldPattern,
optimized: newPattern
},
fix: fixer => fixer.replaceText(patternNode, fixed)
fix: fixer => fixer.replaceText(
patternNode,
quoteString(newPattern)
)
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion rules/catch-error-name.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const create = context => {

const options = {
name: 'error',
caughtErrorsIgnorePattern: '^_$',
caughtErrorsIgnorePattern: /^_$|^[\dA-Za-z]+(e|E)rror$/.source,
...context.options[0]
};

Expand Down
44 changes: 38 additions & 6 deletions rules/consistent-function-scoping.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use strict';
const getDocumentationUrl = require('./utils/get-documentation-url');

const MESSAGE_ID_ARROW = 'ArrowFunctionExpression';
const MESSAGE_ID_FUNCTION = 'FunctionDeclaration';
const MESSAGE_ID_NAMED = 'named';
const MESSAGE_ID_ANONYMOUS = 'anonymous';

const getReferences = scope => scope.references.concat(
...scope.childScopes.map(scope => getReferences(scope))
Expand All @@ -12,7 +12,22 @@ const isSameScope = (scope1, scope2) =>
scope1 && scope2 && (scope1 === scope2 || scope1.block === scope2.block);

function checkReferences(scope, parent, scopeManager) {
const hitReference = references => references.some(reference => isSameScope(parent, reference.from));
const hitReference = references => references.some(reference => {
if (isSameScope(parent, reference.from)) {
return true;
}

const {resolved} = reference;
const [definition] = resolved.defs;

// Skip recursive function name
if (definition && definition.type === 'FunctionName' && resolved.name === definition.name.name) {
return false;
}

return isSameScope(parent, resolved.scope);
});

const hitDefinitions = definitions => definitions.some(definition => {
const scope = scopeManager.acquire(definition.node);
return isSameScope(parent, scope);
Expand Down Expand Up @@ -110,9 +125,26 @@ const create = context => {
},
':matches(ArrowFunctionExpression, FunctionDeclaration):exit': node => {
if (!hasJsx && !checkNode(node, scopeManager)) {
const functionType = node.type === 'ArrowFunctionExpression' ? 'arrow function' : 'function';
let functionName = '';
if (node.id) {
functionName = node.id.name;
} else if (
node.parent &&
node.parent.type === 'VariableDeclarator' &&
node.parent.id &&
node.parent.id.type === 'Identifier'
) {
functionName = node.parent.id.name;
}

context.report({
node,
messageId: node.type
messageId: functionName ? MESSAGE_ID_NAMED : MESSAGE_ID_ANONYMOUS,
data: {
functionType,
functionName
}
});
}

Expand All @@ -132,8 +164,8 @@ module.exports = {
url: getDocumentationUrl(__filename)
},
messages: {
[MESSAGE_ID_ARROW]: 'Move arrow function to the outer scope.',
[MESSAGE_ID_FUNCTION]: 'Move function to the outer scope.'
[MESSAGE_ID_NAMED]: 'Move {{functionType}} `{{functionName}}` to the outer scope.',
[MESSAGE_ID_ANONYMOUS]: 'Move {{functionType}} to the outer scope.'
}
}
};
3 changes: 3 additions & 0 deletions rules/prefer-exponentiation-operator.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
'use strict';
const getDocumentationUrl = require('./utils/get-documentation-url');

const create = () => ({});

module.exports = {
create,
meta: {
type: 'suggestion',
docs: {
Expand Down
29 changes: 27 additions & 2 deletions rules/prefer-spread.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,32 @@ const selector = [
].join('');

const create = context => {
const getSource = node => context.getSourceCode().getText(node);
const sourceCode = context.getSourceCode();
const getSource = node => sourceCode.getText(node);

const needsSemicolon = node => {
const tokenBefore = sourceCode.getTokenBefore(node);

if (tokenBefore) {
const {type, value} = tokenBefore;
if (type === 'Punctuator') {
if (value === ';') {
return false;
}

if (value === ']' || value === ')') {
return true;
}
}

const lastBlockNode = sourceCode.getNodeByRangeIndex(tokenBefore.range[0]);
if (lastBlockNode && lastBlockNode.type === 'ObjectExpression') {
return true;
}
}

return false;
};

return {
[selector](node) {
Expand All @@ -23,7 +48,7 @@ const create = context => {
message: 'Prefer the spread operator over `Array.from()`.',
fix: fixer => {
const [arrayLikeArgument, mapFn, thisArgument] = node.arguments.map(getSource);
let replacement = `[...${arrayLikeArgument}]`;
let replacement = `${needsSemicolon(node) ? ';' : ''}[...${arrayLikeArgument}]`;

if (mapFn) {
const mapArguments = [mapFn, thisArgument].filter(Boolean);
Expand Down
3 changes: 3 additions & 0 deletions rules/regex-shorthand.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
'use strict';
const getDocumentationUrl = require('./utils/get-documentation-url');

const create = () => ({});

module.exports = {
create,
meta: {
type: 'suggestion',
docs: {
Expand Down
Loading

0 comments on commit b19da20

Please sign in to comment.