UNPKG

2.7 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to ensure newline per method call when chaining calls
3 * @author Rajendra Patil
4 * @author Burak Yigit Kaya
5 */
6
7"use strict";
8
9const astUtils = require("../ast-utils");
10
11//------------------------------------------------------------------------------
12// Rule Definition
13//------------------------------------------------------------------------------
14
15module.exports = {
16 meta: {
17 docs: {
18 description: "require a newline after each call in a method chain",
19 category: "Stylistic Issues",
20 recommended: false
21 },
22
23 schema: [{
24 type: "object",
25 properties: {
26 ignoreChainWithDepth: {
27 type: "integer",
28 minimum: 1,
29 maximum: 10
30 }
31 },
32 additionalProperties: false
33 }]
34 },
35
36 create(context) {
37
38 const options = context.options[0] || {},
39 ignoreChainWithDepth = options.ignoreChainWithDepth || 2;
40
41 const sourceCode = context.getSourceCode();
42
43 /**
44 * Gets the property text of a given MemberExpression node.
45 * If the text is multiline, this returns only the first line.
46 *
47 * @param {ASTNode} node - A MemberExpression node to get.
48 * @returns {string} The property text of the node.
49 */
50 function getPropertyText(node) {
51 const prefix = node.computed ? "[" : ".";
52 const lines = sourceCode.getText(node.property).split(astUtils.LINEBREAK_MATCHER);
53 const suffix = node.computed && lines.length === 1 ? "]" : "";
54
55 return prefix + lines[0] + suffix;
56 }
57
58 return {
59 "CallExpression:exit"(node) {
60 if (!node.callee || node.callee.type !== "MemberExpression") {
61 return;
62 }
63
64 const callee = node.callee;
65 let parent = callee.object;
66 let depth = 1;
67
68 while (parent && parent.callee) {
69 depth += 1;
70 parent = parent.callee.object;
71 }
72
73 if (depth > ignoreChainWithDepth && callee.property.loc.start.line === callee.object.loc.end.line) {
74 context.report({
75 node: callee.property,
76 loc: callee.property.loc.start,
77 message: "Expected line break before `{{callee}}`.",
78 data: {
79 callee: getPropertyText(callee)
80 }
81 });
82 }
83 }
84 };
85 }
86};