Repository: sindresorhus/eslint-plugin-unicorn (JavaScript)

Issue:
Unify `catch-error-name` variable renaming strategy with `prevent-abbreviations`
<!-- Issuehunt Badges -->
[<img alt="Issuehunt badges" src="https://img.shields.io/badge/IssueHunt-%2460%20Rewarded-%237E24E3.svg" />](https://issuehunt.io/r/sindresorhus/eslint-plugin-unicorn/issues/257)
<!-- /Issuehunt Badges -->


When generating a unique variable name `catch-error-name` uses number suffixes like `error2`, `error3` etc. It should instead add underscores like `error_`, `error__` etc. and use `avoidCapture` utility function to do it.

From this comment https://github.com/sindresorhus/eslint-plugin-unicorn/pull/237#issuecomment-464188799


<!-- Issuehunt content -->
<details>
<summary>
<b>IssueHunt Summary</b>
</summary>

#### [<img src='https://avatars1.githubusercontent.com/u/74260?v=4' alt='mrhen' width=24 height=24> mrhen](https://issuehunt.io/u/mrhen) has been rewarded.

### Sponsors (Total: $60.00)

- [<img src='https://avatars3.githubusercontent.com/u/44827199?v=4' alt='issuehunt' width=24 height=24> issuehunt](https://issuehunt.io/u/issuehunt) ($60.00)

### Tips

- Checkout the [Issuehunt explorer](https://issuehunt.io/r/sindresorhus/eslint-plugin-unicorn/) to discover more funded issues.
- Need some help from other developers? [Add your repositories](https://issuehunt.io/r/new) on IssueHunt to raise funds.
</details>
<!-- /Issuehunt content-->


Discussion:
👍 Good idea.
@issuehunt has funded $60.00 to this issue.

---
- Submit pull request via [IssueHunt](https://issuehunt.io/repos/55832243/issues/257) to receive this reward.
- Want to contribute? Chip in to this issue via [IssueHunt](https://issuehunt.io/repos/55832243/issues/257).
- Checkout the [IssueHunt Issue Explorer](https://issuehunt.io/issues) to see more funded issues.
- Need help from developers? [Add your repository](https://issuehunt.io/r/new) on IssueHunt to raise funds.
@sindresorhus has rewarded $54.00 to @mrhen. [See it on IssueHunt](https://issuehunt.io/repos/55832243/issues/257)

- :moneybag: Total deposit: $60.00
- :tada: Repository reward(0%): $0.00
- :wrench: Service fee(10%): $6.00



Patch:
diff --git a/docs/rules/catch-error-name.md b/docs/rules/catch-error-name.md
index eb531e939e..c415ac9391 100644
--- a/docs/rules/catch-error-name.md
+++ b/docs/rules/catch-error-name.md
@@ -59,10 +59,10 @@ try {
 
 ```js
 const handleError = error => {
-	const error2 = new Error('🦄');
+	const error_ = new Error('🦄');
 
-	obj.catch(error3 => {
-		// `error3` is allowed because of shadowed variables
+	obj.catch(error__ => {
+		// `error__` is allowed because of shadowed variables
 	});
 }
 ```
diff --git a/rules/catch-error-name.js b/rules/catch-error-name.js
index e4a346c444..ac39b65630 100644
--- a/rules/catch-error-name.js
+++ b/rules/catch-error-name.js
@@ -1,5 +1,6 @@
 'use strict';
 const astUtils = require('eslint-ast-utils');
+const avoidCapture = require('./utils/avoid-capture');
 const getDocsUrl = require('./utils/get-docs-url');
 
 // Matches `someObj.then([FunctionExpression | ArrowFunctionExpression])`
@@ -25,19 +26,11 @@ function isLintablePromiseCatch(node) {
 	return arg0.type === 'FunctionExpression' || arg0.type === 'ArrowFunctionExpression';
 }
 
-// TODO: Use `./utils/avoid-capture.js` instead
-function indexifyName(name, scope) {
-	const variables = scope.variableScope.set;
-
-	let index = 1;
-	while (variables.has(index === 1 ? name : name + index)) {
-		index++;
-	}
-
-	return name + (index === 1 ? '' : index);
-}
-
 const create = context => {
+	const {
+		ecmaVersion
+	} = context.parserOptions;
+
 	const options = {
 		name: 'error',
 		caughtErrorsIgnorePattern: '^_$',
@@ -96,7 +89,8 @@ const create = context => {
 					return;
 				}
 
-				const errorName = indexifyName(name, context.getScope());
+				const scope = context.getScope();
+				const errorName = avoidCapture(name, [scope.variableScope], ecmaVersion);
 				push(params.length === 0 || params[0].name === errorName || errorName);
 			}
 		},
@@ -118,7 +112,8 @@ const create = context => {
 				return;
 			}
 
-			const errName = indexifyName(name, context.getScope());
+			const scope = context.getScope();
+			const errName = avoidCapture(name, [scope.variableScope], ecmaVersion);
 			push(node.param.name === errName || errName);
 		},
 		'CatchClause:exit': node => {


Test patch:
diff --git a/test/catch-error-name.js b/test/catch-error-name.js
index 316442558f..458c3f1a0d 100644
--- a/test/catch-error-name.js
+++ b/test/catch-error-name.js
@@ -28,8 +28,8 @@ ruleTester.run('catch-error-name', rule, {
 			const handleError = error => {
 				try {
 					doSomething();
-				} catch (error2) {
-					console.log(error2);
+				} catch (error_) {
+					console.log(error_);
 				}
 			}
 		`),
@@ -37,53 +37,53 @@ ruleTester.run('catch-error-name', rule, {
 			const handleError = err => {
 				try {
 					doSomething();
-				} catch (err2) {
-					console.log(err2);
+				} catch (err_) {
+					console.log(err_);
 				}
 			}
 		`, 'err'),
 		testCase(`
 			const handleError = error => {
-				const error2 = new Error('🦄');
+				const error_ = new Error('🦄');
 
 				try {
 					doSomething();
-				} catch (error3) {
-					console.log(error3);
+				} catch (error__) {
+					console.log(error__);
 				}
 			}
 		`),
 		testCase('obj.catch(error => {})'),
 		testCase(`
 			const handleError = error => {
-				obj.catch(error2 => { });
+				obj.catch(error_ => { });
 			}
 		`),
 		testCase(`
 			const handleError = err => {
-				obj.catch(err2 => { });
+				obj.catch(err_ => { });
 			}
 		`, 'err'),
 		testCase(`
 			const handleError = error => {
-				const error2 = new Error('foo bar');
+				const error_ = new Error('foo bar');
 
-				obj.catch(error3 => { });
+				obj.catch(error__ => { });
 			}
 		`),
 		testCase(`
 			const handleError = error => {
-				const error2 = new Error('foo bar');
-				const error3 = new Error('foo bar');
-				const error4 = new Error('foo bar');
-				const error5 = new Error('foo bar');
-				const error6 = new Error('foo bar');
-				const error7 = new Error('foo bar');
-				const error8 = new Error('foo bar');
-				const error9 = new Error('foo bar');
-				const error10 = new Error('foo bar');
+				const error_ = new Error('foo bar');
+				const error__ = new Error('foo bar');
+				const error___ = new Error('foo bar');
+				const error____ = new Error('foo bar');
+				const error_____ = new Error('foo bar');
+				const error______ = new Error('foo bar');
+				const error_______ = new Error('foo bar');
+				const error________ = new Error('foo bar');
+				const error_________ = new Error('foo bar');
 
-				obj.catch(error11 => { });
+				obj.catch(error__________ => { });
 			}
 		`),
 		testCase('obj.catch(() => {})'),
@@ -166,6 +166,23 @@ ruleTester.run('catch-error-name', rule, {
 				}
 			`,
 			output: `
+				const handleError = error => {
+					try {
+						doSomething();
+					} catch (error_) {
+						console.log(error_);
+					}
+				}
+			`,
+			errors: [
+				{
+					ruleId: 'catch-error-name',
+					message: 'The catch parameter should be named `error_`.'
+				}
+			]
+		},
+		{
+			code: `
 				const handleError = error => {
 					try {
 						doSomething();
@@ -174,10 +191,19 @@ ruleTester.run('catch-error-name', rule, {
 					}
 				}
 			`,
+			output: `
+				const handleError = error => {
+					try {
+						doSomething();
+					} catch (error_) {
+						console.log(error_);
+					}
+				}
+			`,
 			errors: [
 				{
 					ruleId: 'catch-error-name',
-					message: 'The catch parameter should be named `error2`.'
+					message: 'The catch parameter should be named `error_`.'
 				}
 			]
 		},
@@ -199,59 +225,59 @@ ruleTester.run('catch-error-name', rule, {
 
 					try {
 						doSomething();
-					} catch (error2) {
-						console.log(error2);
+					} catch (error_) {
+						console.log(error_);
 					}
 				}
 			`,
 			errors: [
 				{
 					ruleId: 'catch-error-name',
-					message: 'The catch parameter should be named `error2`.'
+					message: 'The catch parameter should be named `error_`.'
 				}
 			]
 		},
 		{
 			code: `
 				const handleError = error => {
-					const error2 = new Error('foo bar');
+					const error_ = new Error('foo bar');
 
 					obj.catch(foo => { });
 				}
 			`,
 			output: `
 				const handleError = error => {
-					const error2 = new Error('foo bar');
+					const error_ = new Error('foo bar');
 
-					obj.catch(error3 => { });
+					obj.catch(error__ => { });
 				}
 			`,
 			errors: [
 				{
 					ruleId: 'catch-error-name',
-					message: 'The catch parameter should be named `error3`.'
+					message: 'The catch parameter should be named `error__`.'
 				}
 			]
 		},
 		{
 			code: `
 				const handleError = error => {
-					const error2 = new Error('foo bar');
+					const error_ = new Error('foo bar');
 
 					obj.catch(foo => { });
 				}
 			`,
 			output: `
 				const handleError = error => {
-					const error2 = new Error('foo bar');
+					const error_ = new Error('foo bar');
 
-					obj.catch(error3 => { });
+					obj.catch(error__ => { });
 				}
 			`,
 			errors: [
 				{
 					ruleId: 'catch-error-name',
-					message: 'The catch parameter should be named `error3`.'
+					message: 'The catch parameter should be named `error__`.'
 				}
 			],
 			options: [