UNPKG

3.94 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to validate spacing before function paren.
3 * @author Mathias Schreck <https://github.com/lo1tuma>
4 * @copyright 2015 Mathias Schreck
5 * See LICENSE in root directory for full license.
6 */
7"use strict";
8
9//------------------------------------------------------------------------------
10// Rule Definition
11//------------------------------------------------------------------------------
12
13module.exports = function(context) {
14
15 var configuration = context.options[0],
16 sourceCode = context.getSourceCode(),
17 requireAnonymousFunctionSpacing = true,
18 requireNamedFunctionSpacing = true;
19
20 if (typeof configuration === "object") {
21 requireAnonymousFunctionSpacing = configuration.anonymous !== "never";
22 requireNamedFunctionSpacing = configuration.named !== "never";
23 } else if (configuration === "never") {
24 requireAnonymousFunctionSpacing = false;
25 requireNamedFunctionSpacing = false;
26 }
27
28 /**
29 * Determines whether a function has a name.
30 * @param {ASTNode} node The function node.
31 * @returns {boolean} Whether the function has a name.
32 */
33 function isNamedFunction(node) {
34 var parent;
35
36 if (node.id) {
37 return true;
38 }
39
40 parent = node.parent;
41 return parent.type === "MethodDefinition" ||
42 (parent.type === "Property" &&
43 (
44 parent.kind === "get" ||
45 parent.kind === "set" ||
46 parent.method
47 )
48 );
49 }
50
51 /**
52 * Validates the spacing before function parentheses.
53 * @param {ASTNode} node The node to be validated.
54 * @returns {void}
55 */
56 function validateSpacingBeforeParentheses(node) {
57 var isNamed = isNamedFunction(node),
58 leftToken,
59 rightToken,
60 location;
61
62 if (node.generator && !isNamed) {
63 return;
64 }
65
66 rightToken = sourceCode.getFirstToken(node);
67 while (rightToken.value !== "(") {
68 rightToken = sourceCode.getTokenAfter(rightToken);
69 }
70 leftToken = context.getTokenBefore(rightToken);
71 location = leftToken.loc.end;
72
73 if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) {
74 if ((isNamed && !requireNamedFunctionSpacing) || (!isNamed && !requireAnonymousFunctionSpacing)) {
75 context.report({
76 node: node,
77 loc: location,
78 message: "Unexpected space before function parentheses.",
79 fix: function(fixer) {
80 return fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
81 }
82 });
83 }
84 } else {
85 if ((isNamed && requireNamedFunctionSpacing) || (!isNamed && requireAnonymousFunctionSpacing)) {
86 context.report({
87 node: node,
88 loc: location,
89 message: "Missing space before function parentheses.",
90 fix: function(fixer) {
91 return fixer.insertTextAfter(leftToken, " ");
92 }
93 });
94 }
95 }
96 }
97
98 return {
99 "FunctionDeclaration": validateSpacingBeforeParentheses,
100 "FunctionExpression": validateSpacingBeforeParentheses
101 };
102};
103
104module.exports.schema = [
105 {
106 "oneOf": [
107 {
108 "enum": ["always", "never"]
109 },
110 {
111 "type": "object",
112 "properties": {
113 "anonymous": {
114 "enum": ["always", "never"]
115 },
116 "named": {
117 "enum": ["always", "never"]
118 }
119 },
120 "additionalProperties": false
121 }
122 ]
123 }
124];