Blame view

node_modules/eslint/lib/rules/no-warning-comments.js 3.68 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
  /**
   * @fileoverview Rule that warns about used warning comments
   * @author Alexander Schmidt <https://github.com/lxanders>
   */
  
  "use strict";
  
  var astUtils = require("../ast-utils");
  
  //------------------------------------------------------------------------------
  // Rule Definition
  //------------------------------------------------------------------------------
  
  module.exports = function(context) {
  
      var configuration = context.options[0] || {},
          warningTerms = configuration.terms || ["todo", "fixme", "xxx"],
          location = configuration.location || "start",
          selfConfigRegEx = /\bno-warning-comments\b/,
          warningRegExps;
  
      /**
       * Convert a warning term into a RegExp which will match a comment containing that whole word in the specified
       * location ("start" or "anywhere"). If the term starts or ends with non word characters, then the match will not
       * require word boundaries on that side.
       *
       * @param {String} term A term to convert to a RegExp
       * @returns {RegExp} The term converted to a RegExp
       */
      function convertToRegExp(term) {
          var escaped = term.replace(/[-\/\\$\^*+?.()|\[\]{}]/g, "\\$&"),
              // If the term ends in a word character (a-z0-9_), ensure a word boundary at the end, so that substrings do
              // not get falsely matched. eg "todo" in a string such as "mastodon".
              // If the term ends in a non-word character, then \b won't match on the boundary to the next non-word
              // character, which would likely be a space. For example `/\bFIX!\b/.test('FIX! blah') === false`.
              // In these cases, use no bounding match. Same applies for the prefix, handled below.
              suffix = /\w$/.test(term) ? "\\b" : "",
              prefix;
  
          if (location === "start") {
              // When matching at the start, ignore leading whitespace, and there's no need to worry about word boundaries
              prefix = "^\\s*";
          } else if (/^\w/.test(term)) {
              prefix = "\\b";
          } else {
              prefix = "";
          }
  
          return new RegExp(prefix + escaped + suffix, "i");
      }
  
      /**
       * Checks the specified comment for matches of the configured warning terms and returns the matches.
       * @param {String} comment The comment which is checked.
       * @returns {Array} All matched warning terms for this comment.
       */
      function commentContainsWarningTerm(comment) {
          var matches = [];
  
          warningRegExps.forEach(function(regex, index) {
              if (regex.test(comment)) {
                  matches.push(warningTerms[index]);
              }
          });
  
          return matches;
      }
  
      /**
       * Checks the specified node for matching warning comments and reports them.
       * @param {ASTNode} node The AST node being checked.
       * @returns {void} undefined.
       */
      function checkComment(node) {
          if (astUtils.isDirectiveComment(node) && selfConfigRegEx.test(node.value)) {
              return;
          }
  
          var matches = commentContainsWarningTerm(node.value);
  
          matches.forEach(function(matchedTerm) {
              context.report(node, "Unexpected \"" + matchedTerm + "\" comment.");
          });
      }
  
      warningRegExps = warningTerms.map(convertToRegExp);
      return {
          "BlockComment": checkComment,
          "LineComment": checkComment
      };
  };
  
  module.exports.schema = [
      {
          "type": "object",
          "properties": {
              "terms": {
                  "type": "array",
                  "items": {
                      "type": "string"
                  }
              },
              "location": {
                  "enum": ["start", "anywhere"]
              }
          },
          "additionalProperties": false
      }
  ];