112 lines
3.5 KiB
JavaScript
112 lines
3.5 KiB
JavaScript
|
/**
|
||
|
* @author Toru Nagashima <https://github.com/mysticatea>
|
||
|
* See LICENSE file in root directory for full license.
|
||
|
*/
|
||
|
"use strict"
|
||
|
|
||
|
const { isArrowToken } = require("eslint-utils")
|
||
|
|
||
|
module.exports = {
|
||
|
meta: {
|
||
|
docs: {
|
||
|
description: "disallow arrow function expressions.",
|
||
|
category: "ES2015",
|
||
|
recommended: false,
|
||
|
url:
|
||
|
"http://mysticatea.github.io/eslint-plugin-es/rules/no-arrow-functions.html",
|
||
|
},
|
||
|
fixable: "code",
|
||
|
schema: [],
|
||
|
messages: {
|
||
|
forbidden: "ES2015 arrow function expressions are forbidden.",
|
||
|
},
|
||
|
},
|
||
|
create(context) {
|
||
|
const sourceCode = context.getSourceCode()
|
||
|
|
||
|
/**
|
||
|
* ArrowFunctionExpression to FunctionExpression
|
||
|
* @param {Node} node ArrowFunctionExpression Node
|
||
|
* @returns {string} function expression text
|
||
|
*/
|
||
|
function toFunctionExpression(node) {
|
||
|
const params = node.params
|
||
|
const paramText = params.length
|
||
|
? sourceCode.text.slice(
|
||
|
params[0].range[0],
|
||
|
params[params.length - 1].range[1]
|
||
|
)
|
||
|
: ""
|
||
|
|
||
|
const arrowToken = sourceCode.getTokenBefore(
|
||
|
node.body,
|
||
|
isArrowToken
|
||
|
)
|
||
|
const preText = sourceCode.text.slice(
|
||
|
arrowToken.range[1],
|
||
|
node.body.range[0]
|
||
|
)
|
||
|
const bodyText = sourceCode.text.slice(
|
||
|
arrowToken.range[1],
|
||
|
node.range[1]
|
||
|
)
|
||
|
|
||
|
if (node.body.type === "BlockStatement") {
|
||
|
return `function(${paramText})${bodyText}`
|
||
|
}
|
||
|
if (preText.includes("\n")) {
|
||
|
return `function(${paramText}){return(${bodyText})}`
|
||
|
}
|
||
|
return `function(${paramText}){return ${bodyText}}`
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Report that ArrowFunctionExpression is being used
|
||
|
* @param {Node} node ArrowFunctionExpression Node
|
||
|
* @param {boolean} hasThis Whether `this` is referenced in` function` scope
|
||
|
* @param {boolean} hasSuper Whether `super` is referenced in` function` scope
|
||
|
* @returns {void}
|
||
|
*/
|
||
|
function report(node, hasThis, hasSuper) {
|
||
|
context.report({
|
||
|
node,
|
||
|
messageId: "forbidden",
|
||
|
fix(fixer) {
|
||
|
if (hasSuper) {
|
||
|
return undefined
|
||
|
}
|
||
|
const functionText = toFunctionExpression(node)
|
||
|
return fixer.replaceText(
|
||
|
node,
|
||
|
hasThis ? `${functionText}.bind(this)` : functionText
|
||
|
)
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
|
||
|
let stack = { upper: null, hasThis: false, hasSuper: false }
|
||
|
return {
|
||
|
":function"() {
|
||
|
stack = { upper: stack, hasThis: false, hasSuper: false }
|
||
|
},
|
||
|
":function:exit"(node) {
|
||
|
const { hasThis, hasSuper } = stack
|
||
|
stack = stack.upper
|
||
|
|
||
|
if (node.type === "ArrowFunctionExpression") {
|
||
|
report(node, hasThis, hasSuper)
|
||
|
|
||
|
stack.hasThis = stack.hasThis || hasThis
|
||
|
stack.hasSuper = stack.hasSuper || hasSuper
|
||
|
}
|
||
|
},
|
||
|
ThisExpression() {
|
||
|
stack.hasThis = true
|
||
|
},
|
||
|
Super() {
|
||
|
stack.hasSuper = true
|
||
|
},
|
||
|
}
|
||
|
},
|
||
|
}
|