• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Align arguments in multiline function calls
3 * @author Rich Trott
4 */
5'use strict';
6
7//------------------------------------------------------------------------------
8// Rule Definition
9//------------------------------------------------------------------------------
10
11function checkArgumentAlignment(context, node) {
12
13  function isNodeFirstInLine(node, byEndLocation) {
14    const firstToken = byEndLocation === true ? context.getLastToken(node, 1) :
15      context.getTokenBefore(node);
16    const startLine = byEndLocation === true ? node.loc.end.line :
17      node.loc.start.line;
18    const endLine = firstToken ? firstToken.loc.end.line : -1;
19
20    return startLine !== endLine;
21  }
22
23  if (node.arguments.length === 0)
24    return;
25
26  var msg = '';
27  const first = node.arguments[0];
28  var currentLine = first.loc.start.line;
29  const firstColumn = first.loc.start.column;
30
31  const ignoreTypes = [
32    'ArrowFunctionExpression',
33    'FunctionExpression',
34    'ObjectExpression',
35  ];
36
37  const args = node.arguments;
38
39  // For now, don't bother trying to validate potentially complicating things
40  // like closures. Different people will have very different ideas and it's
41  // probably best to implement configuration options.
42  if (args.some((node) => { return ignoreTypes.indexOf(node.type) !== -1; })) {
43    return;
44  }
45
46  if (!isNodeFirstInLine(node)) {
47    return;
48  }
49
50  var misaligned;
51
52  args.slice(1).forEach((argument) => {
53    if (!misaligned) {
54      if (argument.loc.start.line === currentLine + 1) {
55        if (argument.loc.start.column !== firstColumn) {
56          if (isNodeFirstInLine(argument)) {
57            msg = 'Function argument in column ' +
58                  `${argument.loc.start.column + 1}, ` +
59                  `expected in ${firstColumn + 1}`;
60            misaligned = argument;
61          }
62        }
63      }
64    }
65    currentLine = argument.loc.start.line;
66  });
67
68  if (msg)
69    context.report(misaligned, msg);
70}
71
72module.exports = function(context) {
73  return {
74    'CallExpression': (node) => checkArgumentAlignment(context, node)
75  };
76};
77