UNPKG

4.02 kBJavaScriptView Raw
1/**
2 * @fileoverview A rule to disallow or enforce spaces inside of single line blocks.
3 * @author Toru Nagashima
4 * @copyright 2015 Toru Nagashima. All rights reserved.
5 */
6
7"use strict";
8
9var util = require("../ast-utils");
10
11//------------------------------------------------------------------------------
12// Rule Definition
13//------------------------------------------------------------------------------
14
15module.exports = function(context) {
16 var always = (context.options[0] !== "never"),
17 message = always ? "Requires a space" : "Unexpected space(s)",
18 sourceCode = context.getSourceCode();
19
20 /**
21 * Gets the open brace token from a given node.
22 * @param {ASTNode} node - A BlockStatement/SwitchStatement node to get.
23 * @returns {Token} The token of the open brace.
24 */
25 function getOpenBrace(node) {
26 if (node.type === "SwitchStatement") {
27 if (node.cases.length > 0) {
28 return context.getTokenBefore(node.cases[0]);
29 }
30 return context.getLastToken(node, 1);
31 }
32 return context.getFirstToken(node);
33 }
34
35 /**
36 * Checks whether or not:
37 * - given tokens are on same line.
38 * - there is/isn't a space between given tokens.
39 * @param {Token} left - A token to check.
40 * @param {Token} right - The token which is next to `left`.
41 * @returns {boolean}
42 * When the option is `"always"`, `true` if there are one or more spaces between given tokens.
43 * When the option is `"never"`, `true` if there are not any spaces between given tokens.
44 * If given tokens are not on same line, it's always `true`.
45 */
46 function isValid(left, right) {
47 return (
48 !util.isTokenOnSameLine(left, right) ||
49 sourceCode.isSpaceBetweenTokens(left, right) === always
50 );
51 }
52
53 /**
54 * Reports invalid spacing style inside braces.
55 * @param {ASTNode} node - A BlockStatement/SwitchStatement node to get.
56 * @returns {void}
57 */
58 function checkSpacingInsideBraces(node) {
59 // Gets braces and the first/last token of content.
60 var openBrace = getOpenBrace(node);
61 var closeBrace = context.getLastToken(node);
62 var firstToken = sourceCode.getTokenOrCommentAfter(openBrace);
63 var lastToken = sourceCode.getTokenOrCommentBefore(closeBrace);
64
65 // Skip if the node is invalid or empty.
66 if (openBrace.type !== "Punctuator" ||
67 openBrace.value !== "{" ||
68 closeBrace.type !== "Punctuator" ||
69 closeBrace.value !== "}" ||
70 firstToken === closeBrace
71 ) {
72 return;
73 }
74
75 // Skip line comments for option never
76 if (!always && firstToken.type === "Line") {
77 return;
78 }
79
80 // Check.
81 if (!isValid(openBrace, firstToken)) {
82 context.report({
83 node: node,
84 loc: openBrace.loc.start,
85 message: message + " after '{'.",
86 fix: function(fixer) {
87 if (always) {
88 return fixer.insertTextBefore(firstToken, " ");
89 }
90
91 return fixer.removeRange([openBrace.range[1], firstToken.range[0]]);
92 }
93 });
94 }
95 if (!isValid(lastToken, closeBrace)) {
96 context.report({
97 node: node,
98 loc: closeBrace.loc.start,
99 message: message + " before '}'.",
100 fix: function(fixer) {
101 if (always) {
102 return fixer.insertTextAfter(lastToken, " ");
103 }
104
105 return fixer.removeRange([lastToken.range[1], closeBrace.range[0]]);
106 }
107 });
108 }
109 }
110
111 return {
112 BlockStatement: checkSpacingInsideBraces,
113 SwitchStatement: checkSpacingInsideBraces
114 };
115};
116
117module.exports.schema = [
118 {enum: ["always", "never"]}
119];