UNPKG

2.9 kBJavaScriptView Raw
1/**
2 * @fileoverview Look for useless escapes in strings and regexes
3 * @author Onur Temizkan
4 */
5
6"use strict";
7
8//------------------------------------------------------------------------------
9// Rule Definition
10//------------------------------------------------------------------------------
11
12const VALID_STRING_ESCAPES = [
13 "\\",
14 "n",
15 "r",
16 "v",
17 "t",
18 "b",
19 "f",
20 "u",
21 "x",
22 "\n",
23 "\r"
24];
25
26const VALID_REGEX_ESCAPES = [
27 "\\",
28 ".",
29 "-",
30 "^",
31 "$",
32 "*",
33 "+",
34 "?",
35 "{",
36 "}",
37 "[",
38 "]",
39 "|",
40 "(",
41 ")",
42 "b",
43 "B",
44 "c",
45 "d",
46 "D",
47 "f",
48 "n",
49 "r",
50 "s",
51 "S",
52 "t",
53 "v",
54 "w",
55 "W",
56 "x",
57 "u"
58];
59
60module.exports = {
61 meta: {
62 docs: {
63 description: "disallow unnecessary escape characters",
64 category: "Best Practices",
65 recommended: false
66 },
67
68 schema: []
69 },
70
71 create(context) {
72
73 /**
74 * Checks if the escape character in given slice is unnecessary.
75 *
76 * @private
77 * @param {string[]} escapes - list of valid escapes
78 * @param {ASTNode} node - node to validate.
79 * @param {string} elm - string slice to validate.
80 * @returns {void}
81 */
82 function validate(escapes, node, elm) {
83 const escapeNotFound = escapes.indexOf(elm[0][1]) === -1;
84 const isQuoteEscape = elm[0][1] === node.raw[0];
85
86 if (escapeNotFound && !isQuoteEscape) {
87 context.report({
88 node,
89 loc: {
90 line: node.loc.start.line,
91 column: node.loc.start.column + elm.index
92 },
93 message: "Unnecessary escape character: {{character}}.",
94 data: {
95 character: elm[0]
96 }
97 });
98 }
99 }
100
101 /**
102 * Checks if a node has an escape.
103 *
104 * @param {ASTNode} node - node to check.
105 * @returns {void}
106 */
107 function check(node) {
108 let nodeEscapes, match;
109 const pattern = /\\[^\d]/g;
110
111 if (typeof node.value === "string") {
112
113 // JSXAttribute doesn't have any escape sequence: https://facebook.github.io/jsx/
114 if (node.parent.type === "JSXAttribute") {
115 return;
116 }
117
118 nodeEscapes = VALID_STRING_ESCAPES;
119 } else if (node.regex) {
120 nodeEscapes = VALID_REGEX_ESCAPES;
121 } else {
122 return;
123 }
124
125 while ((match = pattern.exec(node.raw))) {
126 validate(nodeEscapes, node, match);
127 }
128 }
129 return {
130 Literal: check
131 };
132 }
133};