node/tools/eslint/lib/rules/space-before-blocks.js
Rich Trott f601d040b5 tools: update ESLint to version 2.1.0
Update ESLint to 2.1.0. ESLint has a number of potentially-useful new
features but this change attempts to be minimal in its changes.
However, some things could not be avoided reasonably.

ESLint 2.1.0 found a few lint issues that ESLing 1.x missed with
template strings that did not take advantage of any features of
template strings, and `let` declarations where `const` sufficed.

Additionally, ESLint 2.1.0 removes some granularity around enabling ES6
features. Some features (e.g., spread operator) that had been turned off
in our configuration for ESLint 1.x are now permitted.

PR-URL: https://github.com/nodejs/node/pull/5214
Reviewed-By: Michaël Zasso <mic.besace@gmail.com>
Reviewed-By: jbergstroem - Johan Bergström <bugs@bergstroem.nu>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
2016-02-21 22:12:40 +11:00

140 lines
4.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @fileoverview A rule to ensure whitespace before blocks.
* @author Mathias Schreck <https://github.com/lo1tuma>
* @copyright 2014 Mathias Schreck. All rights reserved.
*/
"use strict";
var astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
var config = context.options[0],
sourceCode = context.getSourceCode(),
checkFunctions = true,
checkKeywords = true,
checkClasses = true;
if (typeof config === "object") {
checkFunctions = config.functions !== "never";
checkKeywords = config.keywords !== "never";
checkClasses = config.classes !== "never";
} else if (config === "never") {
checkFunctions = false;
checkKeywords = false;
checkClasses = false;
}
/**
* Checks whether or not a given token is an arrow operator (=>) or a keyword
* in order to avoid to conflict with `arrow-spacing` and `keyword-spacing`.
*
* @param {Token} token - A token to check.
* @returns {boolean} `true` if the token is an arrow operator.
*/
function isConflicted(token) {
return (token.type === "Punctuator" && token.value === "=>") || token.type === "Keyword";
}
/**
* Checks the given BlockStatement node has a preceding space if it doesnt start on a new line.
* @param {ASTNode|Token} node The AST node of a BlockStatement.
* @returns {void} undefined.
*/
function checkPrecedingSpace(node) {
var precedingToken = context.getTokenBefore(node),
hasSpace,
parent,
requireSpace;
if (precedingToken && !isConflicted(precedingToken) && astUtils.isTokenOnSameLine(precedingToken, node)) {
hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node);
parent = context.getAncestors().pop();
if (parent.type === "FunctionExpression" || parent.type === "FunctionDeclaration") {
requireSpace = checkFunctions;
} else if (node.type === "ClassBody") {
requireSpace = checkClasses;
} else {
requireSpace = checkKeywords;
}
if (requireSpace) {
if (!hasSpace) {
context.report({
node: node,
message: "Missing space before opening brace.",
fix: function(fixer) {
return fixer.insertTextBefore(node, " ");
}
});
}
} else {
if (hasSpace) {
context.report({
node: node,
message: "Unexpected space before opening brace.",
fix: function(fixer) {
return fixer.removeRange([precedingToken.range[1], node.range[0]]);
}
});
}
}
}
}
/**
* Checks if the CaseBlock of an given SwitchStatement node has a preceding space.
* @param {ASTNode} node The node of a SwitchStatement.
* @returns {void} undefined.
*/
function checkSpaceBeforeCaseBlock(node) {
var cases = node.cases,
firstCase,
openingBrace;
if (cases.length > 0) {
firstCase = cases[0];
openingBrace = context.getTokenBefore(firstCase);
} else {
openingBrace = context.getLastToken(node, 1);
}
checkPrecedingSpace(openingBrace);
}
return {
"BlockStatement": checkPrecedingSpace,
"ClassBody": checkPrecedingSpace,
"SwitchStatement": checkSpaceBeforeCaseBlock
};
};
module.exports.schema = [
{
"oneOf": [
{
"enum": ["always", "never"]
},
{
"type": "object",
"properties": {
"keywords": {
"enum": ["always", "never"]
},
"functions": {
"enum": ["always", "never"]
},
"classes": {
"enum": ["always", "never"]
}
},
"additionalProperties": false
}
]
}
];