UNPKG

6.52 kBJavaScriptView Raw
1"use strict";
2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5}) : (function(o, m, k, k2) {
6 if (k2 === undefined) k2 = k;
7 o[k2] = m[k];
8}));
9var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10 Object.defineProperty(o, "default", { enumerable: true, value: v });
11}) : function(o, v) {
12 o["default"] = v;
13});
14var __importStar = (this && this.__importStar) || function (mod) {
15 if (mod && mod.__esModule) return mod;
16 var result = {};
17 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18 __setModuleDefault(result, mod);
19 return result;
20};
21Object.defineProperty(exports, "__esModule", { value: true });
22const utils_1 = require("@typescript-eslint/utils");
23const util = __importStar(require("../util"));
24exports.default = util.createRule({
25 name: 'space-before-function-paren',
26 meta: {
27 type: 'layout',
28 docs: {
29 description: 'Enforces consistent spacing before function parenthesis',
30 recommended: false,
31 extendsBaseRule: true,
32 },
33 fixable: 'whitespace',
34 schema: [
35 {
36 oneOf: [
37 {
38 enum: ['always', 'never'],
39 },
40 {
41 type: 'object',
42 properties: {
43 anonymous: {
44 enum: ['always', 'never', 'ignore'],
45 },
46 named: {
47 enum: ['always', 'never', 'ignore'],
48 },
49 asyncArrow: {
50 enum: ['always', 'never', 'ignore'],
51 },
52 },
53 additionalProperties: false,
54 },
55 ],
56 },
57 ],
58 messages: {
59 unexpected: 'Unexpected space before function parentheses.',
60 missing: 'Missing space before function parentheses.',
61 },
62 },
63 defaultOptions: ['always'],
64 create(context, [firstOption]) {
65 const sourceCode = context.getSourceCode();
66 const baseConfig = typeof firstOption === 'string' ? firstOption : 'always';
67 const overrideConfig = typeof firstOption === 'object' ? firstOption : {};
68 /**
69 * Determines whether a function has a name.
70 * @param {ASTNode} node The function node.
71 * @returns {boolean} Whether the function has a name.
72 */
73 function isNamedFunction(node) {
74 if (node.id != null) {
75 return true;
76 }
77 const parent = node.parent;
78 return (parent.type === utils_1.AST_NODE_TYPES.MethodDefinition ||
79 parent.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition ||
80 (parent.type === utils_1.AST_NODE_TYPES.Property &&
81 (parent.kind === 'get' || parent.kind === 'set' || parent.method)));
82 }
83 /**
84 * Gets the config for a given function
85 * @param {ASTNode} node The function node
86 * @returns {string} "always", "never", or "ignore"
87 */
88 function getConfigForFunction(node) {
89 var _a, _b, _c;
90 if (node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
91 // Always ignore non-async functions and arrow functions without parens, e.g. async foo => bar
92 if (node.async &&
93 util.isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 }))) {
94 return (_a = overrideConfig.asyncArrow) !== null && _a !== void 0 ? _a : baseConfig;
95 }
96 }
97 else if (isNamedFunction(node)) {
98 return (_b = overrideConfig.named) !== null && _b !== void 0 ? _b : baseConfig;
99 // `generator-star-spacing` should warn anonymous generators. E.g. `function* () {}`
100 }
101 else if (!node.generator) {
102 return (_c = overrideConfig.anonymous) !== null && _c !== void 0 ? _c : baseConfig;
103 }
104 return 'ignore';
105 }
106 /**
107 * Checks the parens of a function node
108 * @param {ASTNode} node A function node
109 * @returns {void}
110 */
111 function checkFunction(node) {
112 const functionConfig = getConfigForFunction(node);
113 if (functionConfig === 'ignore') {
114 return;
115 }
116 let leftToken, rightToken;
117 if (node.typeParameters) {
118 leftToken = sourceCode.getLastToken(node.typeParameters);
119 rightToken = sourceCode.getTokenAfter(leftToken);
120 }
121 else {
122 rightToken = sourceCode.getFirstToken(node, util.isOpeningParenToken);
123 leftToken = sourceCode.getTokenBefore(rightToken);
124 }
125 const hasSpacing = sourceCode.isSpaceBetweenTokens(leftToken, rightToken);
126 if (hasSpacing && functionConfig === 'never') {
127 context.report({
128 node,
129 loc: {
130 start: leftToken.loc.end,
131 end: rightToken.loc.start,
132 },
133 messageId: 'unexpected',
134 fix: fixer => fixer.removeRange([leftToken.range[1], rightToken.range[0]]),
135 });
136 }
137 else if (!hasSpacing &&
138 functionConfig === 'always' &&
139 (!node.typeParameters || node.id)) {
140 context.report({
141 node,
142 loc: rightToken.loc,
143 messageId: 'missing',
144 fix: fixer => fixer.insertTextAfter(leftToken, ' '),
145 });
146 }
147 }
148 return {
149 ArrowFunctionExpression: checkFunction,
150 FunctionDeclaration: checkFunction,
151 FunctionExpression: checkFunction,
152 TSEmptyBodyFunctionExpression: checkFunction,
153 TSDeclareFunction: checkFunction,
154 };
155 },
156});
157//# sourceMappingURL=space-before-function-paren.js.map
\No newline at end of file