summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib/rules/generator-star-spacing.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/generator-star-spacing.js')
-rw-r--r--tools/node_modules/eslint/lib/rules/generator-star-spacing.js199
1 files changed, 199 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/generator-star-spacing.js b/tools/node_modules/eslint/lib/rules/generator-star-spacing.js
new file mode 100644
index 0000000000..a718b59afc
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/generator-star-spacing.js
@@ -0,0 +1,199 @@
+/**
+ * @fileoverview Rule to check the spacing around the * in generator functions.
+ * @author Jamund Ferguson
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+const OVERRIDE_SCHEMA = {
+ oneOf: [
+ {
+ enum: ["before", "after", "both", "neither"]
+ },
+ {
+ type: "object",
+ properties: {
+ before: { type: "boolean" },
+ after: { type: "boolean" }
+ },
+ additionalProperties: false
+ }
+ ]
+};
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce consistent spacing around `*` operators in generator functions",
+ category: "ECMAScript 6",
+ recommended: false
+ },
+
+ fixable: "whitespace",
+
+ schema: [
+ {
+ oneOf: [
+ {
+ enum: ["before", "after", "both", "neither"]
+ },
+ {
+ type: "object",
+ properties: {
+ before: { type: "boolean" },
+ after: { type: "boolean" },
+ named: OVERRIDE_SCHEMA,
+ anonymous: OVERRIDE_SCHEMA,
+ method: OVERRIDE_SCHEMA
+ },
+ additionalProperties: false
+ }
+ ]
+ }
+ ]
+ },
+
+ create(context) {
+
+ const optionDefinitions = {
+ before: { before: true, after: false },
+ after: { before: false, after: true },
+ both: { before: true, after: true },
+ neither: { before: false, after: false }
+ };
+
+ /**
+ * Returns resolved option definitions based on an option and defaults
+ *
+ * @param {any} option - The option object or string value
+ * @param {Object} defaults - The defaults to use if options are not present
+ * @returns {Object} the resolved object definition
+ */
+ function optionToDefinition(option, defaults) {
+ if (!option) {
+ return defaults;
+ }
+
+ return typeof option === "string"
+ ? optionDefinitions[option]
+ : Object.assign({}, defaults, option);
+ }
+
+ const modes = (function(option) {
+ option = option || {};
+ const defaults = optionToDefinition(option, optionDefinitions.before);
+
+ return {
+ named: optionToDefinition(option.named, defaults),
+ anonymous: optionToDefinition(option.anonymous, defaults),
+ method: optionToDefinition(option.method, defaults)
+ };
+ }(context.options[0]));
+
+ const sourceCode = context.getSourceCode();
+
+ /**
+ * Checks if the given token is a star token or not.
+ *
+ * @param {Token} token - The token to check.
+ * @returns {boolean} `true` if the token is a star token.
+ */
+ function isStarToken(token) {
+ return token.value === "*" && token.type === "Punctuator";
+ }
+
+ /**
+ * Gets the generator star token of the given function node.
+ *
+ * @param {ASTNode} node - The function node to get.
+ * @returns {Token} Found star token.
+ */
+ function getStarToken(node) {
+ return sourceCode.getFirstToken(
+ (node.parent.method || node.parent.type === "MethodDefinition") ? node.parent : node,
+ isStarToken
+ );
+ }
+
+ /**
+ * Checks the spacing between two tokens before or after the star token.
+ *
+ * @param {string} kind Either "named", "anonymous", or "method"
+ * @param {string} side Either "before" or "after".
+ * @param {Token} leftToken `function` keyword token if side is "before", or
+ * star token if side is "after".
+ * @param {Token} rightToken Star token if side is "before", or identifier
+ * token if side is "after".
+ * @returns {void}
+ */
+ function checkSpacing(kind, side, leftToken, rightToken) {
+ if (!!(rightToken.range[0] - leftToken.range[1]) !== modes[kind][side]) {
+ const after = leftToken.value === "*";
+ const spaceRequired = modes[kind][side];
+ const node = after ? leftToken : rightToken;
+ const type = spaceRequired ? "Missing" : "Unexpected";
+ const message = "{{type}} space {{side}} *.";
+ const data = {
+ type,
+ side
+ };
+
+ context.report({
+ node,
+ message,
+ data,
+ fix(fixer) {
+ if (spaceRequired) {
+ if (after) {
+ return fixer.insertTextAfter(node, " ");
+ }
+ return fixer.insertTextBefore(node, " ");
+ }
+ return fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
+ }
+ });
+ }
+ }
+
+ /**
+ * Enforces the spacing around the star if node is a generator function.
+ *
+ * @param {ASTNode} node A function expression or declaration node.
+ * @returns {void}
+ */
+ function checkFunction(node) {
+ if (!node.generator) {
+ return;
+ }
+
+ const starToken = getStarToken(node);
+ const prevToken = sourceCode.getTokenBefore(starToken);
+ const nextToken = sourceCode.getTokenAfter(starToken);
+
+ let kind = "named";
+
+ if (node.parent.type === "MethodDefinition" || (node.parent.type === "Property" && node.parent.method)) {
+ kind = "method";
+ } else if (!node.id) {
+ kind = "anonymous";
+ }
+
+ // Only check before when preceded by `function`|`static` keyword
+ if (!(kind === "method" && starToken === sourceCode.getFirstToken(node.parent))) {
+ checkSpacing(kind, "before", prevToken, starToken);
+ }
+
+ checkSpacing(kind, "after", starToken, nextToken);
+ }
+
+ return {
+ FunctionDeclaration: checkFunction,
+ FunctionExpression: checkFunction
+ };
+
+ }
+};