Repository: eslint/eslint
File: lib/rules/prefer-arrow-callback.js (JavaScript)

Code before:
					!scopeInfo.super &&
					!scopeInfo.meta
				) {
					context.report({
						node,
						messageId: "preferArrowCallback",
						*fix(fixer) {
							if (
								(!callbackInfo.isLexicalThis &&
									scopeInfo.this) ||
								hasDuplicateParams(node.params)
							) {
								/*
								 * If the callback function does not have .bind(this) and contains a reference to `this`, there
								 * is no way to determine what `this` should be, so don't perform any fixes.
								 * If the callback function has duplicates in its list of parameters (possible in sloppy mode),
								 * don't replace it with an arrow function, because this is a SyntaxError with arrow functions.
								 */
								return;
							}

							if (
								node.params.some(param => param.name === "this")
							) {
								return;
							}

							// Remove `.bind(this)` if exists.
							if (callbackInfo.isLexicalThis) {
								const memberNode = node.parent;

								/*
								 * If `.bind(this)` exists but the parent is not `.bind(this)`, don't remove it automatically.
								 * E.g. `(foo || function(){}).bind(this)`
								 */
								if (memberNode.type !== "MemberExpression") {
									return;
								}

								const callNode = memberNode.parent;
								const firstTokenToRemove =
									sourceCode.getTokenAfter(
										memberNode.object,
										astUtils.isNotClosingParenToken
									);
								const lastTokenToRemove =
									sourceCode.getLastToken(callNode);

								/*
								 * If the member expression is parenthesized, don't remove the right paren.
								 * E.g. `(function(){}.bind)(this)`

Review comment (refactor):
[Refactor] TypeScript only allows the first param to be named `this`. JavaScript doesn't allow any params to be named `this`. This can just check the first param, if it exists.

Code after:
					!scopeInfo.super &&
					!scopeInfo.meta
				) {
					context.report({
						node,
						messageId: "preferArrowCallback",
						*fix(fixer) {
							if (
								(!callbackInfo.isLexicalThis &&
									scopeInfo.this) ||
								hasDuplicateParams(node.params)
							) {
								/*
								 * If the callback function does not have .bind(this) and contains a reference to `this`, there
								 * is no way to determine what `this` should be, so don't perform any fixes.
								 * If the callback function has duplicates in its list of parameters (possible in sloppy mode),
								 * don't replace it with an arrow function, because this is a SyntaxError with arrow functions.
								 */
								return;
							}

							if (
								node.params.length &&
								node.params[0].name === "this"
							) {
								return;
							}

							// Remove `.bind(this)` if exists.
							if (callbackInfo.isLexicalThis) {
								const memberNode = node.parent;

								/*
								 * If `.bind(this)` exists but the parent is not `.bind(this)`, don't remove it automatically.
								 * E.g. `(foo || function(){}).bind(this)`
								 */
								if (memberNode.type !== "MemberExpression") {
									return;
								}

								const callNode = memberNode.parent;
								const firstTokenToRemove =
									sourceCode.getTokenAfter(
										memberNode.object,
										astUtils.isNotClosingParenToken,
									);
								const lastTokenToRemove =
									sourceCode.getLastToken(callNode);

								/*
								 * If the member expression is parenthesized, don't remove the right paren.