eslint-plugin-crisp 1.7.8 → 1.7.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -94,6 +94,47 @@ function isReference(node) {
|
|
|
94
94
|
);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
// Checks an empty object or array literal (eg. `{}` or `[]`)
|
|
98
|
+
function isEmptyLiteral(node) {
|
|
99
|
+
return (
|
|
100
|
+
(node.type === "ObjectExpression" && node.properties.length === 0) ||
|
|
101
|
+
(node.type === "ArrayExpression" && node.elements.length === 0)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Checks a fallback expression like `value || "none"` or `value ?? other`
|
|
106
|
+
function isFallback(node) {
|
|
107
|
+
node = unwrapTransparentExpression(node);
|
|
108
|
+
|
|
109
|
+
if (
|
|
110
|
+
!node ||
|
|
111
|
+
node.type !== "LogicalExpression" ||
|
|
112
|
+
(node.operator !== "||" && node.operator !== "??")
|
|
113
|
+
) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const isOperandValid = (operand) => {
|
|
118
|
+
operand = unwrapTransparentExpression(operand);
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
operand.type === "Literal" ||
|
|
122
|
+
isEmptyLiteral(operand) ||
|
|
123
|
+
isReference(operand) ||
|
|
124
|
+
isFallback(operand)
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
return isReference(node.left) || isFallback(node.left)
|
|
129
|
+
? isOperandValid(node.right)
|
|
130
|
+
: false;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Checks a logger argument value is a reference, a fallback or an object of those
|
|
134
|
+
function isAllowedValue(node) {
|
|
135
|
+
return isReference(node) || isFallback(node) || isReferenceObject(node);
|
|
136
|
+
}
|
|
137
|
+
|
|
97
138
|
// Checks an inline object only contains references (no computed values)
|
|
98
139
|
function isReferenceObject(node) {
|
|
99
140
|
node = unwrapTransparentExpression(node);
|
|
@@ -115,10 +156,65 @@ function isReferenceObject(node) {
|
|
|
115
156
|
return false;
|
|
116
157
|
}
|
|
117
158
|
|
|
118
|
-
return
|
|
159
|
+
return isAllowedValue(property.value);
|
|
119
160
|
});
|
|
120
161
|
}
|
|
121
162
|
|
|
163
|
+
// Checks a node is a `logger.levels.<level>` member expression
|
|
164
|
+
function isLevelsReference(node) {
|
|
165
|
+
node = unwrapTransparentExpression(node);
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
Boolean(node) &&
|
|
169
|
+
node.type === "MemberExpression" &&
|
|
170
|
+
node.object.type === "MemberExpression" &&
|
|
171
|
+
getPropertyName(node.object) === "levels" &&
|
|
172
|
+
node.object.object.type === "MemberExpression" &&
|
|
173
|
+
getPropertyName(node.object.object) === "logger"
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Checks a condition tests a logger level (eg. `logger.levels.error === true && x`)
|
|
178
|
+
function isLevelCheck(node) {
|
|
179
|
+
node = unwrapTransparentExpression(node);
|
|
180
|
+
|
|
181
|
+
if (!node) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (node.type === "LogicalExpression" && node.operator === "&&") {
|
|
186
|
+
return isLevelCheck(node.left) || isLevelCheck(node.right);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (
|
|
190
|
+
node.type === "BinaryExpression" &&
|
|
191
|
+
(node.operator === "===" || node.operator === "==")
|
|
192
|
+
) {
|
|
193
|
+
return isLevelsReference(node.left) || isLevelsReference(node.right);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return isLevelsReference(node);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Checks a node is inside the consequent of a logger level guard
|
|
200
|
+
function isGuarded(ancestors, node) {
|
|
201
|
+
const chain = [...ancestors, node];
|
|
202
|
+
|
|
203
|
+
for (let index = chain.length - 2; index >= 0; index--) {
|
|
204
|
+
const ancestor = chain[index];
|
|
205
|
+
|
|
206
|
+
if (
|
|
207
|
+
ancestor.type === "IfStatement" &&
|
|
208
|
+
chain[index + 1] === ancestor.consequent &&
|
|
209
|
+
isLevelCheck(ancestor.test)
|
|
210
|
+
) {
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
|
|
122
218
|
export default {
|
|
123
219
|
meta: {
|
|
124
220
|
type: "suggestion",
|
|
@@ -132,7 +228,7 @@ export default {
|
|
|
132
228
|
message:
|
|
133
229
|
"Logger messages must be single-line, double-quoted string literals.",
|
|
134
230
|
reference:
|
|
135
|
-
"Logger interpolation arguments must be references or inline objects of
|
|
231
|
+
"Logger interpolation arguments must be references, fallbacks (`||`, `??`) or inline objects of those, not computed expressions."
|
|
136
232
|
}
|
|
137
233
|
},
|
|
138
234
|
|
|
@@ -145,6 +241,11 @@ export default {
|
|
|
145
241
|
return;
|
|
146
242
|
}
|
|
147
243
|
|
|
244
|
+
// Guarded by a log level check: computed values are allowed
|
|
245
|
+
if (isGuarded(sourceCode.getAncestors(node), node)) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
148
249
|
const [message, ...values] = node.arguments;
|
|
149
250
|
|
|
150
251
|
if (
|
|
@@ -161,7 +262,7 @@ export default {
|
|
|
161
262
|
}
|
|
162
263
|
|
|
163
264
|
for (const value of values) {
|
|
164
|
-
if (!
|
|
265
|
+
if (!isAllowedValue(value)) {
|
|
165
266
|
context.report({
|
|
166
267
|
node: value,
|
|
167
268
|
messageId: "reference"
|
|
@@ -15,6 +15,16 @@ ruleTester.run("logger-arguments", rule, {
|
|
|
15
15
|
value
|
|
16
16
|
);`,
|
|
17
17
|
"App.logger.info(\"This intentionally long logger message may exceed the usual source line length when necessary.\");",
|
|
18
|
+
"App.logger.debug(\"Loaded value: %s\", value || \"default\");",
|
|
19
|
+
"App.logger.debug(\"Loaded value: %s\", this.value ?? \"none\");",
|
|
20
|
+
"App.logger.debug(\"Loaded value: %s\", first || second || \"none\");",
|
|
21
|
+
"App.logger.debug(\"Loaded value: %s\", { user: userId || \"none\" });",
|
|
22
|
+
"if (App.logger.levels.error === true) { App.logger.error(\"Purge failed: %s\", buckets.join(\", \"), error); }",
|
|
23
|
+
"if (App.logger.levels.warn === true) { App.logger.warn(fn_log_format()); }",
|
|
24
|
+
"if (App.logger.levels.error === true && other) { if (x) { App.logger.error(\"Slow: %s\", a + b); } }",
|
|
25
|
+
"if (this._app.logger.levels.debug) { this._app.logger.debug(\"Count: %s\", list.length + 1); }",
|
|
26
|
+
"App.logger.error(\"Failed\", { params: (request.params || {}) });",
|
|
27
|
+
"App.logger.error(\"Failed: %s\", list || []);",
|
|
18
28
|
"App.logger.warn(\"Shutting down\", { bufferedCount });",
|
|
19
29
|
"App.logger.warn(\"Shutting down\", { count: this.count, ...meta });",
|
|
20
30
|
"App.logger.warn(\"Shutting down\", { nested: { bufferedCount } }, logMeta);",
|
|
@@ -80,7 +90,15 @@ ruleTester.run("logger-arguments", rule, {
|
|
|
80
90
|
]
|
|
81
91
|
},
|
|
82
92
|
{
|
|
83
|
-
code: "App.logger.debug(\"Loaded value: %s\", value ||
|
|
93
|
+
code: "App.logger.debug(\"Loaded value: %s\", value || compute());",
|
|
94
|
+
errors: [
|
|
95
|
+
{
|
|
96
|
+
messageId: "reference"
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
code: "App.logger.debug(\"Loaded value: %s\", value && \"default\");",
|
|
84
102
|
errors: [
|
|
85
103
|
{
|
|
86
104
|
messageId: "reference"
|
|
@@ -111,6 +129,22 @@ ruleTester.run("logger-arguments", rule, {
|
|
|
111
129
|
}
|
|
112
130
|
]
|
|
113
131
|
},
|
|
132
|
+
{
|
|
133
|
+
code: "if (App.logger.levels.error === true) {} else { App.logger.error(\"Purge: %s\", buckets.join(\", \")); }",
|
|
134
|
+
errors: [
|
|
135
|
+
{
|
|
136
|
+
messageId: "reference"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
code: "if (enabled) { App.logger.error(\"Purge: %s\", buckets.join(\", \")); }",
|
|
142
|
+
errors: [
|
|
143
|
+
{
|
|
144
|
+
messageId: "reference"
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
},
|
|
114
148
|
{
|
|
115
149
|
code: "App.logger.debug(\"Retry count: %s\", 3);",
|
|
116
150
|
errors: [
|
|
@@ -120,7 +154,7 @@ ruleTester.run("logger-arguments", rule, {
|
|
|
120
154
|
]
|
|
121
155
|
},
|
|
122
156
|
{
|
|
123
|
-
code: "App.logger.debug(\"Values: %s / %s\", values.join(\", \"), fallback ||
|
|
157
|
+
code: "App.logger.debug(\"Values: %s / %s\", values.join(\", \"), fallback || compute());",
|
|
124
158
|
errors: [
|
|
125
159
|
{
|
|
126
160
|
messageId: "reference"
|