1 | /**
|
2 | * @fileoverview Disallows or enforces spaces inside of brackets.
|
3 | * @author Ian Christian Myers
|
4 | */
|
5 | ;
|
6 |
|
7 | //------------------------------------------------------------------------------
|
8 | // Rule Definition
|
9 | //------------------------------------------------------------------------------
|
10 |
|
11 | module.exports = function(context) {
|
12 |
|
13 | var shouldSpace = context.options[0] || "never";
|
14 |
|
15 | //--------------------------------------------------------------------------
|
16 | // Helpers
|
17 | //--------------------------------------------------------------------------
|
18 |
|
19 | /**
|
20 | * Determines whether two adjacent tokens are have whitespace between them.
|
21 | * @param {Object} left The left token object.
|
22 | * @param {Object} right The right token object.
|
23 | * @returns {Boolean} Whether or not there is space between the tokens.
|
24 | */
|
25 | function isSpaced(left, right) {
|
26 | return left.range[1] < right.range[0];
|
27 | }
|
28 |
|
29 | /**
|
30 | * Determines whether two adjacent tokens are on the same line.
|
31 | * @param {Object} left The left token object.
|
32 | * @param {Object} right The right token object.
|
33 | * @returns {Boolean} Whether or not the tokens are on the same line.
|
34 | */
|
35 | function isSameLine(left, right) {
|
36 | return left.loc.start.line === right.loc.start.line;
|
37 | }
|
38 |
|
39 | /**
|
40 | * Checks whether the given set of tokens are spaced according to the user
|
41 | * given preferences. Reports the node, if the tokens are improperly spaced.
|
42 | * @param {ASTNode} node The node to report in the event of an error.
|
43 | * @param {Object[]} tokens The tokens to be checked for spacing.
|
44 | * @returns {void}
|
45 | */
|
46 | function verifySpacing(node, tokens) {
|
47 | if (shouldSpace === "always") {
|
48 | if (!isSpaced(tokens[0], tokens[1])) {
|
49 | context.report(node, tokens[0].loc.end,
|
50 | "A space is required after '" + tokens[0].value + "'");
|
51 | }
|
52 |
|
53 | if (!isSpaced(tokens[tokens.length - 2], tokens[tokens.length - 1])) {
|
54 | context.report(node, tokens[tokens.length - 1].loc.start,
|
55 | "A space is required before '" + tokens[tokens.length - 1].value + "'");
|
56 | }
|
57 | } else if (shouldSpace === "never") {
|
58 |
|
59 | // This is an exception for Array and Object literals that do not
|
60 | // have any values on the same lines as brackets.
|
61 | if ((node.type === "ArrayExpression" || node.type === "ObjectExpression") &&
|
62 | !isSameLine(tokens[0], tokens[1]) &&
|
63 | !isSameLine(tokens[tokens.length - 2], tokens[tokens.length - 1])) {
|
64 | return;
|
65 | }
|
66 |
|
67 | if (isSpaced(tokens[0], tokens[1])) {
|
68 | context.report(node, tokens[0].loc.end,
|
69 | "There should be no space after '" + tokens[0].value + "'");
|
70 | }
|
71 |
|
72 | if (isSpaced(tokens[tokens.length - 2], tokens[tokens.length - 1])) {
|
73 | context.report(node, tokens[tokens.length - 1].loc.start,
|
74 | "There should be no space before '" + tokens[tokens.length - 1].value + "'");
|
75 | }
|
76 | }
|
77 | }
|
78 |
|
79 | /**
|
80 | * Checks whether the brackets of an Object or Array literal are spaced
|
81 | * according to the given preferences.
|
82 | * @param {ASTNode} node The ArrayExpression or ObjectExpression node.
|
83 | * @returns {void}
|
84 | */
|
85 | function checkLiteral(node) {
|
86 | var tokens = context.getTokens(node);
|
87 | verifySpacing(node, tokens);
|
88 | }
|
89 |
|
90 | /**
|
91 | * Checks whether the brackets of an Object's member are spaced according to
|
92 | * the given preferences, if the member is being accessed with bracket
|
93 | * notation
|
94 | * @param {ASTNode} node The MemberExpression node.
|
95 | * @returns {void}
|
96 | */
|
97 | function checkMember(node) {
|
98 |
|
99 | // Ensure the property is not enclosed in brackets.
|
100 | if (node.computed) {
|
101 | var tokens = context.getTokens(node.property, 1, 1);
|
102 | verifySpacing(node, tokens);
|
103 | }
|
104 | }
|
105 |
|
106 |
|
107 | //--------------------------------------------------------------------------
|
108 | // Public
|
109 | //--------------------------------------------------------------------------
|
110 |
|
111 | return {
|
112 |
|
113 | "MemberExpression": checkMember,
|
114 | "ArrayExpression": checkLiteral,
|
115 | "ObjectExpression": checkLiteral
|
116 |
|
117 | };
|
118 |
|
119 | };
|