summaryrefslogtreecommitdiff
path: root/tools/eslint/lib/rules/no-useless-escape.js
blob: 036831fc394f4fa9854479021775be4b7605bc6c (plain)
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
126
127
128
129
130
/**
 * @fileoverview Look for useless escapes in strings and regexes
 * @author Onur Temizkan
 */

"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

var VALID_STRING_ESCAPES = [
    "\\",
    "n",
    "r",
    "v",
    "t",
    "b",
    "f",
    "u",
    "x",
    "\n",
    "\r"
];

var VALID_REGEX_ESCAPES = [
    "\\",
    ".",
    "-",
    "^",
    "$",
    "*",
    "+",
    "?",
    "{",
    "}",
    "[",
    "]",
    "|",
    "(",
    ")",
    "b",
    "B",
    "c",
    "d",
    "D",
    "f",
    "n",
    "r",
    "s",
    "S",
    "t",
    "v",
    "w",
    "W",
    "x",
    "u"
];

module.exports = {
    meta: {
        docs: {
            description: "disallow unnecessary escape characters",
            category: "Best Practices",
            recommended: false
        },

        schema: []
    },

    create: function(context) {

        /**
         * Checks if the escape character in given slice is unnecessary.
         *
         * @private
         * @param {string[]} escapes - list of valid escapes
         * @param {ASTNode} node - node to validate.
         * @param {string} elm - string slice to validate.
         * @returns {void}
         */
        function validate(escapes, node, elm) {
            var escapeNotFound = escapes.indexOf(elm[0][1]) === -1;
            var isQuoteEscape = elm[0][1] === node.raw[0];

            if (escapeNotFound && !isQuoteEscape) {
                context.report({
                    node: node,
                    loc: {
                        line: node.loc.start.line,
                        column: node.loc.start.column + elm.index
                    },
                    message: "Unnecessary escape character: " + elm[0]
                });
            }
        }

        /**
         * Checks if a node has an escape.
         *
         * @param {ASTNode} node - node to check.
         * @returns {void}
         */
        function check(node) {
            var nodeEscapes, match;
            var pattern = /\\[^\d]/g;

            if (typeof node.value === "string") {

                // JSXAttribute doesn't have any escape sequence: https://facebook.github.io/jsx/
                if (node.parent.type === "JSXAttribute") {
                    return;
                }

                nodeEscapes = VALID_STRING_ESCAPES;
            } else if (node.regex) {
                nodeEscapes = VALID_REGEX_ESCAPES;
            } else {
                return;
            }

            while ((match = pattern.exec(node.raw))) {
                validate(nodeEscapes, node, match);
            }
        }
        return {
            Literal: check
        };
    }
};