2 * @fileoverview This rule shoud require or disallow spaces before or after unary operations.
3 * @author Marcin Kumorek
4 * @copyright 2014 Marcin Kumorek. All rights reserved.
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 module.exports = function(context) {
13 var options = context.options && Array.isArray(context.options) && context.options[0] || { words: true, nonwords: false };
15 //--------------------------------------------------------------------------
17 //--------------------------------------------------------------------------
20 * Check if the parent unary operator is "!" in order to know if it's "!!" convert to Boolean or just "!" negation
21 * @param {ASTnode} node AST node
22 * @returns {boolean} Whether or not the parent is unary "!" operator
24 function isParentUnaryBangExpression(node) {
25 return node && node.parent && node.parent.type === "UnaryExpression" && node.parent.operator === "!";
29 * Checks if the type is a unary word expression
30 * @param {string} type value of AST token
31 * @returns {boolean} Whether the word is in the list of known words
33 function isWordExpression(type) {
34 return ["delete", "new", "typeof", "void"].indexOf(type) !== -1;
38 * Check if the node's child argument is an "ObjectExpression"
39 * @param {ASTnode} node AST node
40 * @returns {boolean} Whether or not the argument's type is "ObjectExpression"
42 function isArgumentObjectExpression(node) {
43 return node.argument && node.argument.type && node.argument.type === "ObjectExpression";
47 * Check Unary Word Operators for spaces after the word operator
48 * @param {ASTnode} node AST node
49 * @param {object} firstToken first token from the AST node
50 * @param {object} secondToken second token from the AST node
53 function checkUnaryWordOperatorForSpaces(node, firstToken, secondToken) {
55 if (secondToken.range[0] === firstToken.range[1]) {
56 context.report(node, "Unary word operator \"" + firstToken.value + "\" must be followed by whitespace.");
60 if (!options.words && isArgumentObjectExpression(node)) {
61 if (secondToken.range[0] > firstToken.range[1]) {
62 context.report(node, "Unexpected space after unary word operator \"" + firstToken.value + "\".");
68 * Checks UnaryExpression, UpdateExpression and NewExpression for spaces before and after the operator
69 * @param {ASTnode} node AST node
72 function checkForSpaces(node) {
73 var tokens = context.getFirstTokens(node, 2),
74 firstToken = tokens[0],
75 secondToken = tokens[1];
77 if (isWordExpression(firstToken.value)) {
78 checkUnaryWordOperatorForSpaces(node, firstToken, secondToken);
82 if (options.nonwords) {
84 if (isParentUnaryBangExpression(node)) {
87 if (firstToken.range[1] === secondToken.range[0]) {
88 context.report(node, "Unary operator \"" + firstToken.value + "\" must be followed by whitespace.");
91 if (firstToken.range[1] === secondToken.range[0]) {
92 context.report(node, "Space is required before unary expressions \"" + secondToken.value + "\".");
97 if (secondToken.range[0] > firstToken.range[1]) {
98 context.report(node, "Unexpected space after unary operator \"" + firstToken.value + "\".");
101 if (secondToken.range[0] > firstToken.range[1]) {
102 context.report(node, "Unexpected space before unary operator \"" + secondToken.value + "\".");
108 //--------------------------------------------------------------------------
110 //--------------------------------------------------------------------------
113 "UnaryExpression": checkForSpaces,
114 "UpdateExpression": checkForSpaces,
115 "NewExpression": checkForSpaces