Blame view

node_modules/eslint/lib/rules/padded-blocks.js 4.07 KB
c39994410   Ryan Glover   wip converting to...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  /**
   * @fileoverview A rule to ensure blank lines within blocks.
   * @author Mathias Schreck <https://github.com/lo1tuma>
   * @copyright 2014 Mathias Schreck. All rights reserved.
   */
  
  "use strict";
  
  //------------------------------------------------------------------------------
  // Rule Definition
  //------------------------------------------------------------------------------
  
  module.exports = function(context) {
      var requirePadding = context.options[0] !== "never";
  
      var ALWAYS_MESSAGE = "Block must be padded by blank lines.",
          NEVER_MESSAGE = "Block must not be padded by blank lines.";
  
      /**
       * Retrieves an array of all comments defined inside the given node.
       * @param {ASTNode} node The AST node.
       * @returns {ASTNode[]} An array of comment nodes.
       */
      function getCommentsInNode(node) {
          var allComments = context.getAllComments();
  
          return allComments.filter(function(comment) {
              return node.range[0] < comment.range[0] &&
                  node.range[1] > comment.range[1];
          });
      }
  
      /**
       * Checks if the location of a node or token is before the location of another node or token
       * @param {ASTNode|Token} a The node or token to check if its location is before b.
       * @param {ASTNode|Token} b The node or token which will be compared with a.
       * @returns {boolean} True if a is located before b.
       */
      function isLocatedBefore(a, b) {
          return a.range[1] < b.range[0];
      }
  
      /**
       * Checks if the given non empty block node has a blank line before its first child node.
       * @param {ASTNode} node The AST node of a BlockStatement.
       * @returns {boolean} Whether or not the block starts with a blank line.
       */
      function isBlockTopPadded(node) {
          var blockStart = node.loc.start.line,
              first = node.body[0],
              firstLine = first.loc.start.line,
              expectedFirstLine = blockStart + 2,
              comments = getCommentsInNode(node),
              firstComment = comments[0];
  
          if (firstComment && isLocatedBefore(firstComment, first)) {
              firstLine = firstComment.loc.start.line;
          }
  
          return expectedFirstLine <= firstLine;
      }
  
      /**
       * Checks if the given non empty block node has a blank line after its last child node.
       * @param {ASTNode} node The AST node of a BlockStatement.
       * @returns {boolean} Whether or not the block ends with a blank line.
       */
      function isBlockBottomPadded(node) {
          var blockEnd = node.loc.end.line,
              last = node.body[node.body.length - 1],
              lastToken = context.getLastToken(last),
              lastLine = lastToken.loc.end.line,
              expectedLastLine = blockEnd - 2,
              comments = getCommentsInNode(node),
              lastComment = comments[comments.length - 1];
  
          if (lastComment && isLocatedBefore(lastToken, lastComment)) {
              lastLine = lastComment.loc.end.line;
          }
  
          return lastLine <= expectedLastLine;
      }
  
      /**
       * Checks the given BlockStatement node to be padded if the block is not empty.
       * @param {ASTNode} node The AST node of a BlockStatement.
       * @returns {void} undefined.
       */
      function checkPadding(node) {
          if (node.body.length > 0) {
  
              var blockHasTopPadding = isBlockTopPadded(node),
                  blockHasBottomPadding = isBlockBottomPadded(node);
  
              if (requirePadding) {
                  if (!blockHasTopPadding) {
                      context.report(node, ALWAYS_MESSAGE);
                  }
  
                  if (!blockHasBottomPadding) {
                      context.report(node, node.loc.end, ALWAYS_MESSAGE);
                  }
              } else {
                  if (blockHasTopPadding) {
                      context.report(node, NEVER_MESSAGE);
                  }
  
                  if (blockHasBottomPadding) {
                      context.report(node, node.loc.end, NEVER_MESSAGE);
                  }
              }
          }
      }
  
      return {
          "BlockStatement": checkPadding
      };
  
  };
  
  module.exports.schema = [
      {
          "enum": ["always", "never"]
      }
  ];