diff --git a/.eslintrc b/.eslintrc index 8e01cc4c94c0e4..e8496e8560f0a7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,7 +13,7 @@ rules: no-duplicate-case: 2 no-empty-character-class: 2 no-ex-assign: 2 - no-extra-boolean-cast : 2 + no-extra-boolean-cast: 2 no-extra-parens: [2, "functions"] no-extra-semi: 2 no-func-assign: 2 @@ -86,7 +86,7 @@ rules: # Custom rules in tools/eslint-rules new-with-error: [2, "Error", "RangeError", "TypeError", "SyntaxError", "ReferenceError"] - + align-multiline-assignment: 2 # Global scoped method and vars globals: diff --git a/tools/eslint-rules/align-multiline-assignment.js b/tools/eslint-rules/align-multiline-assignment.js new file mode 100644 index 00000000000000..69f1f33d4d184f --- /dev/null +++ b/tools/eslint-rules/align-multiline-assignment.js @@ -0,0 +1,68 @@ +/** + * @fileoverview Align multiline variable assignments + * @author Rich Trott + */ +'use strict'; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ +function getBinaryExpressionStarts(binaryExpression, starts = []) { + function getStartsFromOneSide(side, starts) { + starts.push(side.loc.start); + if (side.type === 'BinaryExpression') { + starts = getBinaryExpressionStarts(side, starts); + } + return starts; + } + + starts = getStartsFromOneSide(binaryExpression.left, starts); + starts = getStartsFromOneSide(binaryExpression.right, starts); + return starts; +} + +function checkExpressionAlignment(expression) { + if (!expression) + return; + + var msg = ''; + + switch (expression.type) { + case 'BinaryExpression': + var starts = getBinaryExpressionStarts(expression); + var startLine = starts[0].line; + const startColumn = starts[0].column; + starts.forEach((loc) => { + if (loc.line > startLine) { + startLine = loc.line; + if (loc.column !== startColumn) { + msg = 'Misaligned multiline assignment'; + } + } + }); + break; + } + return msg; +} + +function testAssignment(context, node) { + const msg = checkExpressionAlignment(node.right); + if (msg) + context.report(node, msg); +} + +function testDeclaration(context, node) { + node.declarations.forEach((declaration) => { + const msg = checkExpressionAlignment(declaration.init); + // const start = declaration.init.loc.start; + if (msg) + context.report(node, msg); + }); +} + +module.exports = function(context) { + return { + 'AssignmentExpression': (node) => testAssignment(context, node), + 'VariableDeclaration': (node) => testDeclaration(context, node) + }; +};