Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ed2bd60

Browse files
authored
fix(eslint-plugin): [prefer-string-starts-ends-with] check for negative start index in slice (typescript-eslint#1920)
1 parent a85c3e1 commit ed2bd60

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,27 @@ export default createRule({
166166
);
167167
}
168168

169+
/**
170+
* Check if a given node is a negative index expression
171+
*
172+
* E.g. `s.slice(- <expr>)`, `s.substring(s.length - <expr>)`
173+
*
174+
* @param node The node to check.
175+
* @param expectedIndexedNode The node which is expected as the receiver of index expression.
176+
*/
177+
function isNegativeIndexExpression(
178+
node: TSESTree.Node,
179+
expectedIndexedNode: TSESTree.Node,
180+
): boolean {
181+
return (
182+
(node.type === AST_NODE_TYPES.UnaryExpression &&
183+
node.operator === '-') ||
184+
(node.type === AST_NODE_TYPES.BinaryExpression &&
185+
node.operator === '-' &&
186+
isLengthExpression(node.left, expectedIndexedNode))
187+
);
188+
}
189+
169190
/**
170191
* Check if a given node is the expression of the last index.
171192
*
@@ -538,9 +559,10 @@ export default createRule({
538559
}
539560

540561
const isEndsWith =
541-
callNode.arguments.length === 1 ||
542-
(callNode.arguments.length === 2 &&
543-
isLengthExpression(callNode.arguments[1], node.object));
562+
(callNode.arguments.length === 1 ||
563+
(callNode.arguments.length === 2 &&
564+
isLengthExpression(callNode.arguments[1], node.object))) &&
565+
isNegativeIndexExpression(callNode.arguments[0], node.object);
544566
const isStartsWith =
545567
!isEndsWith &&
546568
callNode.arguments.length === 2 &&
@@ -564,6 +586,9 @@ export default createRule({
564586
) {
565587
return null;
566588
}
589+
// code being checked is likely mistake:
590+
// unequal length of strings being checked for equality
591+
// or reliant on behavior of substring (negative indices interpreted as 0)
567592
if (isStartsWith) {
568593
if (!isLengthExpression(callNode.arguments[1], eqNode.right)) {
569594
return null;

packages/eslint-plugin/tests/rules/prefer-string-starts-ends-with.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ ruleTester.run('prefer-string-starts-ends-with', rule, {
209209
s.slice(-4, -1) === "bar"
210210
}
211211
`,
212+
// https://github.com/typescript-eslint/typescript-eslint/issues/1690
213+
`
214+
function f(s: string) {
215+
s.slice(1) === "bar"
216+
}
217+
`,
212218
`
213219
function f(s: string) {
214220
pattern.test(s)
@@ -872,7 +878,7 @@ ruleTester.run('prefer-string-starts-ends-with', rule, {
872878
{
873879
code: `
874880
function f(s: string) {
875-
s.slice(startIndex) === needle // 'startIndex' can be different
881+
s.slice(-length) === needle // 'length' can be different
876882
}
877883
`,
878884
output: null,

0 commit comments

Comments
 (0)