summaryrefslogtreecommitdiff
path: root/tools/eslint/lib/rules/operator-linebreak.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/eslint/lib/rules/operator-linebreak.js')
-rw-r--r--tools/eslint/lib/rules/operator-linebreak.js100
1 files changed, 100 insertions, 0 deletions
diff --git a/tools/eslint/lib/rules/operator-linebreak.js b/tools/eslint/lib/rules/operator-linebreak.js
new file mode 100644
index 0000000000..020c61544c
--- /dev/null
+++ b/tools/eslint/lib/rules/operator-linebreak.js
@@ -0,0 +1,100 @@
+/**
+ * @fileoverview Operator linebreak - enforces operator linebreak style of two types: after and before
+ * @author Benoît Zugmeyer
+ * @copyright 2015 Benoît Zugmeyer. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ var style = context.options[0] || "after";
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Checks whether two tokens are on the same line.
+ * @param {ASTNode} left The leftmost token.
+ * @param {ASTNode} right The rightmost token.
+ * @returns {boolean} True if the tokens are on the same line, false if not.
+ * @private
+ */
+ function isSameLine(left, right) {
+ return left.loc.end.line === right.loc.start.line;
+ }
+
+ /**
+ * Checks the operator placement
+ * @param {ASTNode} node The binary operator node to check
+ * @private
+ * @returns {void}
+ */
+ function validateBinaryExpression(node) {
+ var leftToken = context.getLastToken(node.left || node.id);
+ var operatorToken = context.getTokenAfter(leftToken);
+
+ // When the left part of a binary expression is a single expression wrapped in
+ // parentheses (ex: `(a) + b`), leftToken will be the last token of the expression
+ // and operatorToken will be the closing parenthesis.
+ // The leftToken should be the last closing parenthesis, and the operatorToken
+ // should be the token right after that.
+ while (operatorToken.value === ")") {
+ leftToken = operatorToken;
+ operatorToken = context.getTokenAfter(operatorToken);
+ }
+
+ var rightToken = context.getTokenAfter(operatorToken);
+ var operator = operatorToken.value;
+
+ // if single line
+ if (isSameLine(leftToken, operatorToken) &&
+ isSameLine(operatorToken, rightToken)) {
+
+ return;
+
+ } else if (!isSameLine(leftToken, operatorToken) &&
+ !isSameLine(operatorToken, rightToken)) {
+
+ // lone operator
+ context.report(node, {
+ line: operatorToken.loc.end.line,
+ column: operatorToken.loc.end.column
+ }, "Bad line breaking before and after '" + operator + "'.");
+
+ } else if (style === "before" && isSameLine(leftToken, operatorToken)) {
+
+ context.report(node, {
+ line: operatorToken.loc.end.line,
+ column: operatorToken.loc.end.column
+ }, "'" + operator + "' should be placed at the beginning of the line.");
+
+ } else if (style === "after" && isSameLine(operatorToken, rightToken)) {
+
+ context.report(node, {
+ line: operatorToken.loc.end.line,
+ column: operatorToken.loc.end.column
+ }, "'" + operator + "' should be placed at the end of the line.");
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+ "BinaryExpression": validateBinaryExpression,
+ "LogicalExpression": validateBinaryExpression,
+ "AssignmentExpression": validateBinaryExpression,
+ "VariableDeclarator": function (node) {
+ if (node.init) {
+ validateBinaryExpression(node);
+ }
+ }
+ };
+};