summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib/rules/arrow-body-style.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/arrow-body-style.js')
-rw-r--r--tools/node_modules/eslint/lib/rules/arrow-body-style.js215
1 files changed, 215 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/arrow-body-style.js b/tools/node_modules/eslint/lib/rules/arrow-body-style.js
new file mode 100644
index 0000000000..78a391334d
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/arrow-body-style.js
@@ -0,0 +1,215 @@
+/**
+ * @fileoverview Rule to require braces in arrow function body.
+ * @author Alberto Rodríguez
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "require braces around arrow function bodies",
+ category: "ECMAScript 6",
+ recommended: false
+ },
+
+ schema: {
+ anyOf: [
+ {
+ type: "array",
+ items: [
+ {
+ enum: ["always", "never"]
+ }
+ ],
+ minItems: 0,
+ maxItems: 1
+ },
+ {
+ type: "array",
+ items: [
+ {
+ enum: ["as-needed"]
+ },
+ {
+ type: "object",
+ properties: {
+ requireReturnForObjectLiteral: { type: "boolean" }
+ },
+ additionalProperties: false
+ }
+ ],
+ minItems: 0,
+ maxItems: 2
+ }
+ ]
+ },
+
+ fixable: "code"
+ },
+
+ create(context) {
+ const options = context.options;
+ const always = options[0] === "always";
+ const asNeeded = !options[0] || options[0] === "as-needed";
+ const never = options[0] === "never";
+ const requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral;
+ const sourceCode = context.getSourceCode();
+
+ /**
+ * Checks whether the given node has ASI problem or not.
+ * @param {Token} token The token to check.
+ * @returns {boolean} `true` if it changes semantics if `;` or `}` followed by the token are removed.
+ */
+ function hasASIProblem(token) {
+ return token && token.type === "Punctuator" && /^[([/`+-]/.test(token.value);
+ }
+
+ /**
+ * Gets the closing parenthesis which is the pair of the given opening parenthesis.
+ * @param {Token} token The opening parenthesis token to get.
+ * @returns {Token} The found closing parenthesis token.
+ */
+ function findClosingParen(token) {
+ let node = sourceCode.getNodeByRangeIndex(token.range[1]);
+
+ while (!astUtils.isParenthesised(sourceCode, node)) {
+ node = node.parent;
+ }
+ return sourceCode.getTokenAfter(node);
+ }
+
+ /**
+ * Determines whether a arrow function body needs braces
+ * @param {ASTNode} node The arrow function node.
+ * @returns {void}
+ */
+ function validate(node) {
+ const arrowBody = node.body;
+
+ if (arrowBody.type === "BlockStatement") {
+ const blockBody = arrowBody.body;
+
+ if (blockBody.length !== 1 && !never) {
+ return;
+ }
+
+ if (asNeeded && requireReturnForObjectLiteral && blockBody[0].type === "ReturnStatement" &&
+ blockBody[0].argument && blockBody[0].argument.type === "ObjectExpression") {
+ return;
+ }
+
+ if (never || asNeeded && blockBody[0].type === "ReturnStatement") {
+ context.report({
+ node,
+ loc: arrowBody.loc.start,
+ message: "Unexpected block statement surrounding arrow body.",
+ fix(fixer) {
+ const fixes = [];
+
+ if (blockBody.length !== 1 ||
+ blockBody[0].type !== "ReturnStatement" ||
+ !blockBody[0].argument ||
+ hasASIProblem(sourceCode.getTokenAfter(arrowBody))
+ ) {
+ return fixes;
+ }
+
+ const openingBrace = sourceCode.getFirstToken(arrowBody);
+ const closingBrace = sourceCode.getLastToken(arrowBody);
+ const firstValueToken = sourceCode.getFirstToken(blockBody[0], 1);
+ const lastValueToken = sourceCode.getLastToken(blockBody[0]);
+ const commentsExist =
+ sourceCode.commentsExistBetween(openingBrace, firstValueToken) ||
+ sourceCode.commentsExistBetween(lastValueToken, closingBrace);
+
+ /*
+ * Remove tokens around the return value.
+ * If comments don't exist, remove extra spaces as well.
+ */
+ if (commentsExist) {
+ fixes.push(
+ fixer.remove(openingBrace),
+ fixer.remove(closingBrace),
+ fixer.remove(sourceCode.getTokenAfter(openingBrace)) // return keyword
+ );
+ } else {
+ fixes.push(
+ fixer.removeRange([openingBrace.range[0], firstValueToken.range[0]]),
+ fixer.removeRange([lastValueToken.range[1], closingBrace.range[1]])
+ );
+ }
+
+ /*
+ * If the first token of the reutrn value is `{`,
+ * enclose the return value by parentheses to avoid syntax error.
+ */
+ if (astUtils.isOpeningBraceToken(firstValueToken)) {
+ fixes.push(
+ fixer.insertTextBefore(firstValueToken, "("),
+ fixer.insertTextAfter(lastValueToken, ")")
+ );
+ }
+
+ /*
+ * If the last token of the return statement is semicolon, remove it.
+ * Non-block arrow body is an expression, not a statement.
+ */
+ if (astUtils.isSemicolonToken(lastValueToken)) {
+ fixes.push(fixer.remove(lastValueToken));
+ }
+
+ return fixes;
+ }
+ });
+ }
+ } else {
+ if (always || (asNeeded && requireReturnForObjectLiteral && arrowBody.type === "ObjectExpression")) {
+ context.report({
+ node,
+ loc: arrowBody.loc.start,
+ message: "Expected block statement surrounding arrow body.",
+ fix(fixer) {
+ const fixes = [];
+ const arrowToken = sourceCode.getTokenBefore(arrowBody, astUtils.isArrowToken);
+ const firstBodyToken = sourceCode.getTokenAfter(arrowToken);
+ const lastBodyToken = sourceCode.getLastToken(node);
+ const isParenthesisedObjectLiteral =
+ astUtils.isOpeningParenToken(firstBodyToken) &&
+ astUtils.isOpeningBraceToken(sourceCode.getTokenAfter(firstBodyToken));
+
+ // Wrap the value by a block and a return statement.
+ fixes.push(
+ fixer.insertTextBefore(firstBodyToken, "{return "),
+ fixer.insertTextAfter(lastBodyToken, "}")
+ );
+
+ // If the value is object literal, remove parentheses which were forced by syntax.
+ if (isParenthesisedObjectLiteral) {
+ fixes.push(
+ fixer.remove(firstBodyToken),
+ fixer.remove(findClosingParen(firstBodyToken))
+ );
+ }
+
+ return fixes;
+ }
+ });
+ }
+ }
+ }
+
+ return {
+ "ArrowFunctionExpression:exit": validate
+ };
+ }
+};