-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
/
jsx-no-leaked-zero.js
99 lines (87 loc) · 3.02 KB
/
jsx-no-leaked-zero.js
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
/**
* @fileoverview Prevent zero from being rendered on numerical condition
* @author Mario Beltrán
*/
'use strict';
const docsUrl = require('../util/docsUrl');
const report = require('../util/report');
const isParenthesized = require('../util/ast').isParenthesized;
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const messages = {
noPotentialNumericEvaluation: 'Potential numeric evaluation resulting in an unintentionally rendered `0`',
};
const VALID_LEFT_SIDE_EXPRESSIONS = ['UnaryExpression', 'BinaryExpression', 'ConditionalExpression', 'CallExpression'];
const CAST_FIX_STRATEGY = 'cast';
const TERNARY_FIX_STRATEGY = 'ternary';
const DEFAULT_FIX_STRATEGY = TERNARY_FIX_STRATEGY;
/**
* @type {import('eslint').Rule.RuleModule}
*/
module.exports = {
meta: {
docs: {
description: 'Prevent zero from being rendered on numerical condition',
category: 'Possible Errors',
recommended: false,
url: docsUrl('jsx-no-leaked-zero'),
},
messages,
fixable: 'code',
schema: [
{
type: 'object',
properties: {
fixStrategy: {
type: 'string',
enum: [
CAST_FIX_STRATEGY,
TERNARY_FIX_STRATEGY,
],
default: DEFAULT_FIX_STRATEGY,
},
},
additionalProperties: false,
},
],
},
create(context) {
const config = context.options[0] || {};
const fixStrategy = config.fixStrategy || DEFAULT_FIX_STRATEGY;
function ruleFixer(fixer, logicalExpressionNode) {
if (fixStrategy === CAST_FIX_STRATEGY) {
let leftSideRange = logicalExpressionNode.left.range;
if (isParenthesized(context, logicalExpressionNode.left)) {
const [leftSideStart, leftSideEnd] = leftSideRange;
leftSideRange = [leftSideStart - 1, leftSideEnd + 1];
}
return fixer.insertTextBeforeRange(leftSideRange, '!!');
}
if (fixStrategy === TERNARY_FIX_STRATEGY) {
const sourceCode = context.getSourceCode();
const rightSideText = sourceCode.getText(logicalExpressionNode.right);
let leftSideText = sourceCode.getText(logicalExpressionNode.left);
if (isParenthesized(context, logicalExpressionNode.left)) {
leftSideText = `(${leftSideText})`;
}
return fixer.replaceText(logicalExpressionNode, `${leftSideText} ? ${rightSideText} : null`);
}
throw new Error('Invalid value for "fixStrategy" option');
}
return {
'JSXExpressionContainer > LogicalExpression[operator="&&"]'(node) {
const leftSide = node.left;
if (VALID_LEFT_SIDE_EXPRESSIONS.includes(leftSide.type)) {
return;
}
report(context, messages.noPotentialNumericEvaluation, 'noPotentialNumericEvaluation', {
node: leftSide,
fix(fixer) {
return ruleFixer(fixer, node);
},
});
},
};
},
};