eslint-plugin-prefer-arrow-functions
Advanced tools
Comparing version 3.3.2 to 3.4.0
"use strict"; | ||
var config_1 = require("./config"); | ||
var prefer_arrow_functions_1 = require("./prefer-arrow-functions"); | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
const config_1 = require("./config"); | ||
const prefer_arrow_functions_1 = __importDefault(require("./prefer-arrow-functions")); | ||
module.exports = { | ||
@@ -5,0 +8,0 @@ rules: { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var config_1 = require("./config"); | ||
const config_1 = require("./config"); | ||
exports.default = { | ||
@@ -30,45 +30,42 @@ meta: { | ||
}, | ||
create: function (context) { | ||
var options = context.options[0] || {}; | ||
var getOption = function (name) { | ||
return typeof options[name] !== 'undefined' | ||
? options[name] | ||
: config_1.DEFAULT_OPTIONS[name]; | ||
}; | ||
var allowNamedFunctions = getOption('allowNamedFunctions'); | ||
var singleReturnOnly = getOption('singleReturnOnly'); | ||
var classPropertiesAllowed = getOption('classPropertiesAllowed'); | ||
var disallowPrototype = getOption('disallowPrototype'); | ||
var returnStyle = getOption('returnStyle'); | ||
var sourceCode = context.getSourceCode(); | ||
var isBlockStatementWithSingleReturn = function (node) { | ||
create: (context) => { | ||
const options = context.options[0] || {}; | ||
const getOption = (name) => typeof options[name] !== 'undefined' | ||
? options[name] | ||
: config_1.DEFAULT_OPTIONS[name]; | ||
const allowNamedFunctions = getOption('allowNamedFunctions'); | ||
const singleReturnOnly = getOption('singleReturnOnly'); | ||
const classPropertiesAllowed = getOption('classPropertiesAllowed'); | ||
const disallowPrototype = getOption('disallowPrototype'); | ||
const returnStyle = getOption('returnStyle'); | ||
const { sourceCode } = context; | ||
const filename = context.getPhysicalFilename(); | ||
const isTSX = filename?.endsWith('.tsx'); | ||
const isBlockStatementWithSingleReturn = (node) => { | ||
return (node.body.body && | ||
node.body.body.length === 1 && | ||
node.body.body[0].type === 'ReturnStatement'); | ||
node.body.body[0].type === 'ReturnStatement' && | ||
node.body.body[0].argument !== null); | ||
}; | ||
var isImplicitReturn = function (node) { | ||
const isImplicitReturn = (node) => { | ||
return node.body && !node.body.body; | ||
}; | ||
var returnsImmediately = function (node) { | ||
const returnsImmediately = (node) => { | ||
return isBlockStatementWithSingleReturn(node) || isImplicitReturn(node); | ||
}; | ||
var getBodySource = function (node) { | ||
const getBodySource = (node) => { | ||
if (isBlockStatementWithSingleReturn(node) && | ||
returnStyle !== 'explicit') { | ||
var returnValue = node.body.body[0].argument; | ||
var source = sourceCode.getText(returnValue); | ||
return returnValue.type === 'ObjectExpression' ? "(" + source + ")" : source; | ||
const returnValue = node.body.body[0].argument; | ||
const source = sourceCode.getText(returnValue); | ||
return returnValue.type === 'ObjectExpression' ? `(${source})` : source; | ||
} | ||
if (isImplicitReturn(node) && returnStyle !== 'implicit') { | ||
return "{ return " + sourceCode.getText(node.body) + " }"; | ||
return `{ return ${sourceCode.getText(node.body)} }`; | ||
} | ||
return sourceCode.getText(node.body); | ||
}; | ||
var getParamsSource = function (params) { | ||
return params.map(function (param) { return sourceCode.getText(param); }); | ||
}; | ||
var getFunctionName = function (node) { | ||
return node && node.id && node.id.name ? node.id.name : ''; | ||
}; | ||
var getPreviousNode = function (node) { | ||
const getParamsSource = (params) => params.map((param) => sourceCode.getText(param)); | ||
const getFunctionName = (node) => node && node.id && node.id.name ? node.id.name : ''; | ||
const getPreviousNode = (node) => { | ||
if (isNamedExport(node)) { | ||
@@ -79,3 +76,3 @@ node = node.parent; | ||
return null; | ||
var nodeIndex = node.parent.body.indexOf(node); | ||
const nodeIndex = node.parent.body.indexOf(node); | ||
if (nodeIndex === 0) | ||
@@ -85,14 +82,19 @@ return null; | ||
}; | ||
var isGenericFunction = function (node) { return Boolean(node.typeParameters); }; | ||
var getGenericSource = function (node) { return sourceCode.getText(node.typeParameters); }; | ||
var isAsyncFunction = function (node) { return node.async === true; }; | ||
var isGeneratorFunction = function (node) { return node.generator === true; }; | ||
var isAssertionFunction = function (node) { | ||
return node.returnType && | ||
node.returnType.typeAnnotation && | ||
node.returnType.typeAnnotation.asserts; | ||
const isGenericFunction = (node) => Boolean(node.typeParameters); | ||
const getGenericSource = (node) => { | ||
const genericSource = sourceCode.getText(node.typeParameters); | ||
if (!isTSX) | ||
return genericSource; | ||
const genericParameterCount = node.typeParameters?.params?.length || 0; | ||
if (genericParameterCount === 1) | ||
return `<${node.typeParameters.params[0].name.name},>`; | ||
return genericSource; | ||
}; | ||
var isOverloadedFunction = function (node) { | ||
var _a; | ||
var previousNode = getPreviousNode(node); | ||
const isAsyncFunction = (node) => node.async === true; | ||
const isGeneratorFunction = (node) => node.generator === true; | ||
const isAssertionFunction = (node) => node.returnType && | ||
node.returnType.typeAnnotation && | ||
node.returnType.typeAnnotation.asserts; | ||
const isOverloadedFunction = (node) => { | ||
const previousNode = getPreviousNode(node); | ||
if (!previousNode) | ||
@@ -103,30 +105,27 @@ return false; | ||
if (previousNode.type === 'ExportNamedDeclaration' && | ||
((_a = previousNode.declaration) === null || _a === void 0 ? void 0 : _a.type) === 'TSDeclareFunction') | ||
previousNode.declaration?.type === 'TSDeclareFunction') | ||
return true; | ||
return false; | ||
}; | ||
var getReturnType = function (node) { | ||
var _a; | ||
return node.returnType && | ||
node.returnType.range && (_a = sourceCode.getText()).substring.apply(_a, node.returnType.range); | ||
}; | ||
var containsToken = function (type, value, node) { | ||
const getReturnType = (node) => node.returnType && | ||
node.returnType.range && | ||
sourceCode.getText().substring(...node.returnType.range); | ||
const containsToken = (type, value, node) => { | ||
return sourceCode | ||
.getTokens(node) | ||
.some(function (token) { return token.type === type && token.value === value; }); | ||
.some((token) => token.type === type && token.value === value); | ||
}; | ||
var containsSuper = function (node) { | ||
const containsSuper = (node) => { | ||
return containsToken('Keyword', 'super', node); | ||
}; | ||
var containsThis = function (node) { | ||
const containsThis = (node) => { | ||
return containsToken('Keyword', 'this', node); | ||
}; | ||
var containsArguments = function (node) { | ||
const containsArguments = (node) => { | ||
return containsToken('Identifier', 'arguments', node); | ||
}; | ||
var containsTokenSequence = function (sequence, node) { | ||
return sourceCode.getTokens(node).some(function (_, tokenIndex, tokens) { | ||
return sequence.every(function (_a, i) { | ||
var expectedType = _a[0], expectedValue = _a[1]; | ||
var actual = tokens[tokenIndex + i]; | ||
const containsTokenSequence = (sequence, node) => { | ||
return sourceCode.getTokens(node).some((_, tokenIndex, tokens) => { | ||
return sequence.every(([expectedType, expectedValue], i) => { | ||
const actual = tokens[tokenIndex + i]; | ||
return (actual && | ||
@@ -138,3 +137,3 @@ actual.type === expectedType && | ||
}; | ||
var containsNewDotTarget = function (node) { | ||
const containsNewDotTarget = (node) => { | ||
return containsTokenSequence([ | ||
@@ -146,16 +145,16 @@ ['Keyword', 'new'], | ||
}; | ||
var writeArrowFunction = function (node) { | ||
var fn = getFunctionDescriptor(node); | ||
var ASYNC = fn.isAsync ? 'async ' : ''; | ||
var GENERIC = fn.isGeneric ? fn.generic : ''; | ||
var BODY = fn.body; | ||
var RETURN_TYPE = fn.returnType ? fn.returnType : ''; | ||
var PARAMS = fn.params.join(', '); | ||
return "" + ASYNC + GENERIC + "(" + PARAMS + ")" + RETURN_TYPE + " => " + BODY; | ||
const writeArrowFunction = (node) => { | ||
const fn = getFunctionDescriptor(node); | ||
const ASYNC = fn.isAsync ? 'async ' : ''; | ||
const GENERIC = fn.isGeneric ? fn.generic : ''; | ||
const BODY = fn.body; | ||
const RETURN_TYPE = fn.returnType ? fn.returnType : ''; | ||
const PARAMS = fn.params.join(', '); | ||
return `${ASYNC}${GENERIC}(${PARAMS})${RETURN_TYPE} => ${BODY}`; | ||
}; | ||
var writeArrowConstant = function (node) { | ||
var fn = getFunctionDescriptor(node); | ||
return "const " + fn.name + " = " + writeArrowFunction(node); | ||
const writeArrowConstant = (node) => { | ||
const fn = getFunctionDescriptor(node); | ||
return `const ${fn.name} = ${writeArrowFunction(node)}`; | ||
}; | ||
var getFunctionDescriptor = function (node) { | ||
const getFunctionDescriptor = (node) => { | ||
return { | ||
@@ -172,12 +171,12 @@ body: getBodySource(node), | ||
}; | ||
var isPrototypeAssignment = function (node) { | ||
return context | ||
.getAncestors() | ||
const isPrototypeAssignment = (node) => { | ||
return sourceCode | ||
.getAncestors(node) | ||
.reverse() | ||
.some(function (ancestor) { | ||
var isPropertyOfReplacementPrototypeObject = ancestor.type === 'AssignmentExpression' && | ||
.some((ancestor) => { | ||
const isPropertyOfReplacementPrototypeObject = ancestor.type === 'AssignmentExpression' && | ||
ancestor.left && | ||
ancestor.left.property && | ||
ancestor.left.property.name === 'prototype'; | ||
var isMutationOfExistingPrototypeObject = ancestor.type === 'AssignmentExpression' && | ||
const isMutationOfExistingPrototypeObject = ancestor.type === 'AssignmentExpression' && | ||
ancestor.left && | ||
@@ -191,18 +190,14 @@ ancestor.left.object && | ||
}; | ||
var isWithinClassBody = function (node) { | ||
return context | ||
.getAncestors() | ||
const isWithinClassBody = (node) => { | ||
return sourceCode | ||
.getAncestors(node) | ||
.reverse() | ||
.some(function (ancestor) { | ||
.some((ancestor) => { | ||
return ancestor.type === 'ClassBody'; | ||
}); | ||
}; | ||
var isNamed = function (node) { return node.id && node.id.name; }; | ||
var isNamedDefaultExport = function (node) { | ||
return isNamed(node) && node.parent.type === 'ExportDefaultDeclaration'; | ||
}; | ||
var isNamedExport = function (node) { | ||
return node.parent.type === 'ExportNamedDeclaration'; | ||
}; | ||
var isSafeTransformation = function (node) { | ||
const isNamed = (node) => node.id && node.id.name; | ||
const isNamedDefaultExport = (node) => isNamed(node) && node.parent.type === 'ExportDefaultDeclaration'; | ||
const isNamedExport = (node) => node.parent.type === 'ExportNamedDeclaration'; | ||
const isSafeTransformation = (node) => { | ||
return (!isGeneratorFunction(node) && | ||
@@ -220,3 +215,3 @@ !isAssertionFunction(node) && | ||
}; | ||
var getMessage = function (node) { | ||
const getMessage = (node) => { | ||
return singleReturnOnly && returnsImmediately(node) | ||
@@ -227,25 +222,21 @@ ? config_1.USE_ARROW_WHEN_SINGLE_RETURN | ||
return { | ||
'ExportDefaultDeclaration > FunctionDeclaration': function (node) { | ||
'ExportDefaultDeclaration > FunctionDeclaration': (node) => { | ||
if (isSafeTransformation(node)) { | ||
context.report({ | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, writeArrowFunction(node) + ';'); | ||
}, | ||
fix: (fixer) => fixer.replaceText(node, writeArrowFunction(node) + ';'), | ||
message: getMessage(node), | ||
node: node, | ||
node, | ||
}); | ||
} | ||
}, | ||
':matches(ClassProperty, MethodDefinition, Property)[key.name][value.type="FunctionExpression"][kind!=/^(get|set)$/]': function (node) { | ||
var propName = node.key.name; | ||
var functionNode = node.value; | ||
var staticModifier = node.static ? 'static ' : ''; | ||
':matches(ClassProperty, MethodDefinition, Property)[key.name][value.type="FunctionExpression"][kind!=/^(get|set|constructor)$/]': (node) => { | ||
const propName = node.key.name; | ||
const functionNode = node.value; | ||
const staticModifier = node.static ? 'static ' : ''; | ||
if (isSafeTransformation(functionNode) && | ||
(!isWithinClassBody(functionNode) || classPropertiesAllowed)) { | ||
context.report({ | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, isWithinClassBody(node) | ||
? "" + staticModifier + propName + " = " + writeArrowFunction(functionNode) + ";" | ||
: "" + staticModifier + propName + ": " + writeArrowFunction(functionNode)); | ||
}, | ||
fix: (fixer) => fixer.replaceText(node, isWithinClassBody(node) | ||
? `${staticModifier}${propName} = ${writeArrowFunction(functionNode)};` | ||
: `${staticModifier}${propName}: ${writeArrowFunction(functionNode)}`), | ||
message: getMessage(functionNode), | ||
@@ -256,37 +247,35 @@ node: functionNode, | ||
}, | ||
'ArrowFunctionExpression[body.type!="BlockStatement"]': function (node) { | ||
'ArrowFunctionExpression[body.type!="BlockStatement"]': (node) => { | ||
if (returnStyle === 'explicit' && isSafeTransformation(node)) { | ||
context.report({ | ||
fix: function (fixer) { return fixer.replaceText(node, writeArrowFunction(node)); }, | ||
fix: (fixer) => fixer.replaceText(node, writeArrowFunction(node)), | ||
message: config_1.USE_EXPLICIT, | ||
node: node, | ||
node, | ||
}); | ||
} | ||
}, | ||
'ArrowFunctionExpression[body.body.length=1][body.body.0.type="ReturnStatement"]': function (node) { | ||
'ArrowFunctionExpression[body.body.length=1][body.body.0.type="ReturnStatement"]': (node) => { | ||
if (returnStyle === 'implicit' && isSafeTransformation(node)) { | ||
context.report({ | ||
fix: function (fixer) { return fixer.replaceText(node, writeArrowFunction(node)); }, | ||
fix: (fixer) => fixer.replaceText(node, writeArrowFunction(node)), | ||
message: config_1.USE_IMPLICIT, | ||
node: node, | ||
node, | ||
}); | ||
} | ||
}, | ||
'FunctionExpression[parent.type!=/^(ClassProperty|MethodDefinition|Property)$/]': function (node) { | ||
'FunctionExpression[parent.type!=/^(ClassProperty|MethodDefinition|Property)$/]': (node) => { | ||
if (isSafeTransformation(node)) { | ||
context.report({ | ||
fix: function (fixer) { return fixer.replaceText(node, writeArrowFunction(node)); }, | ||
fix: (fixer) => fixer.replaceText(node, writeArrowFunction(node)), | ||
message: getMessage(node), | ||
node: node, | ||
node, | ||
}); | ||
} | ||
}, | ||
'FunctionDeclaration[parent.type!="ExportDefaultDeclaration"]': function (node) { | ||
'FunctionDeclaration[parent.type!="ExportDefaultDeclaration"]': (node) => { | ||
if (isSafeTransformation(node)) { | ||
context.report({ | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, writeArrowConstant(node) + ';'); | ||
}, | ||
fix: (fixer) => fixer.replaceText(node, writeArrowConstant(node) + ';'), | ||
message: getMessage(node), | ||
node: node, | ||
node, | ||
}); | ||
@@ -293,0 +282,0 @@ } |
{ | ||
"name": "eslint-plugin-prefer-arrow-functions", | ||
"description": "Convert functions to arrow functions", | ||
"version": "3.3.2", | ||
"version": "3.4.0", | ||
"author": "Jamie Mason (https://github.com/JamieMason)", | ||
"bugs": "https://github.com/JamieMason/eslint-plugin-prefer-arrow-functions/issues", | ||
"contributors": [ | ||
"Anders Kaseorg (https://github.com/andersk)", | ||
"Gabriel Montes (https://github.com/gabmontes)", | ||
"Harel Moshe (https://github.com/harelmo)", | ||
"Keith Lea (https://github.com/keithkml)", | ||
"Lou Cyx (https://github.com/loucyx)", | ||
"Marek Dědič (https://github.com/marekdedic)", | ||
"Michael Gallagher (https://github.com/mikeapr4)", | ||
@@ -18,16 +21,22 @@ "Mitchell Merry (https://github.com/mitchell-merry)", | ||
"devDependencies": { | ||
"@eslint/eslintrc": "3.1.0", | ||
"@eslint/js": "9.9.0", | ||
"@release-it/conventional-changelog": "8.0.1", | ||
"@types/jest": "27.0.2", | ||
"@types/node": "16.11.7", | ||
"@typescript-eslint/eslint-plugin": "5.3.1", | ||
"@typescript-eslint/parser": "5.3.1", | ||
"@types/eslint": "9.6.0", | ||
"@types/node": "22.2.0", | ||
"@typescript-eslint/eslint-plugin": "8.0.1", | ||
"@typescript-eslint/parser": "8.0.1", | ||
"@vitest/coverage-v8": "2.0.5", | ||
"auto-changelog": "2.4.0", | ||
"eslint": "8.57.0", | ||
"jest": "27.3.1", | ||
"prettier": "2.4.1", | ||
"release-it": "17.0.1", | ||
"rimraf": "3.0.2", | ||
"ts-jest": "27.0.7", | ||
"typescript": "4.4.4" | ||
"eslint": "9.9.0", | ||
"globals": "15.9.0", | ||
"prettier": "3.3.3", | ||
"release-it": "17.6.0", | ||
"rimraf": "6.0.1", | ||
"typescript": "5.5.4", | ||
"vitest": "2.0.5" | ||
}, | ||
"engines": { | ||
"node": ">=18.0.0" | ||
}, | ||
"files": [ | ||
@@ -45,3 +54,3 @@ "dist" | ||
"peerDependencies": { | ||
"eslint": ">=5.0.0" | ||
"eslint": ">=9.0.0" | ||
}, | ||
@@ -52,3 +61,3 @@ "repository": "JamieMason/eslint-plugin-prefer-arrow-functions", | ||
"format": "prettier --write './src/**/*.ts'", | ||
"lint": "eslint --ext .ts .", | ||
"lint": "eslint .", | ||
"prebuild": "rimraf ./dist", | ||
@@ -58,4 +67,5 @@ "prelint": "npm run format", | ||
"release": "release-it", | ||
"test": "jest" | ||
"test": "vitest run src", | ||
"test:watch": "vitest run --watch" | ||
} | ||
} |
23738
16
303