diff --git a/README.md b/README.md index 48013251..5e18af75 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Code Smells, or maintainability issues, are raised for places of code which migh * "if ... else if" constructs should end with "else" clauses ([`elseif-without-else`]) (*disabled*) * "switch" statements should not have too many "case" clauses ([`max-switch-cases`]) * Collapsible "if" statements should be merged ([`no-collapsible-if`]) -* Collection sizes and array length comparisons should make sense ([`no-collection-size-mischeck`]) (*uses-types*) +* Collection sizes and array length comparisons should make sense ([`no-collection-size-mischeck`]) (:wrench: *fixable*, *uses-types*) * String literals should not be duplicated ([`no-duplicate-string`]) * Two branches in a conditional structure should not have exactly the same implementation ([`no-duplicated-branches`]) * Boolean expressions should not be gratuitous ([`no-gratuitous-expressions`]) diff --git a/docs/rules/no-collection-size-mischeck.md b/docs/rules/no-collection-size-mischeck.md index 621418d8..20040e2a 100644 --- a/docs/rules/no-collection-size-mischeck.md +++ b/docs/rules/no-collection-size-mischeck.md @@ -1,5 +1,7 @@ # no-collection-size-mischeck +:wrench: *fixable* + The size of a collection and the length of an array are always greater than or equal to zero. So testing that a size or length is greater than or equal to zero doesn't make sense, since the result is always `true`. Similarly testing that it is less than zero will always return `false`. Perhaps the intent was to check the non-emptiness of the collection or array instead. ## Noncompliant Code Example diff --git a/src/rules/no-collection-size-mischeck.ts b/src/rules/no-collection-size-mischeck.ts index c44f27f8..56ed746e 100644 --- a/src/rules/no-collection-size-mischeck.ts +++ b/src/rules/no-collection-size-mischeck.ts @@ -31,9 +31,11 @@ const rule: TSESLint.RuleModule = { messages: { fixCollectionSizeCheck: 'Fix this expression; {{propertyName}} of "{{objectName}}" is always greater or equal to zero.', + suggestFixedSizeCheck: 'Use "{{operator}}" for {{operation}} check', }, schema: [], type: 'problem', + hasSuggestions: true, docs: { description: 'Collection sizes and array length comparisons should make sense', recommended: 'error', @@ -63,6 +65,7 @@ const rule: TSESLint.RuleModule = { objectName: context.getSourceCode().getText(object), }, node, + suggest: getSuggestion(expr, property.name, context), }); } } @@ -82,4 +85,26 @@ function isCollection(node: TSESTree.Node, services: RequiredParserServices) { return !!tp.symbol && CollectionLike.includes(tp.symbol.name); } +function getSuggestion( + expr: TSESTree.BinaryExpression, + operation: string, + context: TSESLint.RuleContext, +): TSESLint.ReportSuggestionArray { + const { left, operator } = expr; + const operatorToken = context + .getSourceCode() + .getTokenAfter(left, token => token.value === operator)!; + const fixedOperator = operator === '<' ? '==' : '>'; + return [ + { + messageId: 'suggestFixedSizeCheck', + data: { + operation, + operator: fixedOperator, + }, + fix: fixer => fixer.replaceText(operatorToken, fixedOperator), + }, + ]; +} + export = rule; diff --git a/tests/rules/no-collection-size-mischeck.test.ts b/tests/rules/no-collection-size-mischeck.test.ts index d919a60e..4e0b168e 100644 --- a/tests/rules/no-collection-size-mischeck.test.ts +++ b/tests/rules/no-collection-size-mischeck.test.ts @@ -54,6 +54,16 @@ ruleTester.run('Collection sizes and array length comparisons should make sense' endLine: 1, column: 5, endColumn: 24, + suggestions: [ + { + messageId: 'suggestFixedSizeCheck', + data: { + operation: 'size', + operator: '==', + }, + output: `if (collection.size == 0) {}`, + }, + ], }, ], }, @@ -86,6 +96,16 @@ ruleTester.run('Collection sizes and array length comparisons should make sense' endLine: 1, column: 5, endColumn: 27, + suggestions: [ + { + messageId: 'suggestFixedSizeCheck', + data: { + operation: 'length', + operator: '>', + }, + output: `if (collection.length > 0) {}`, + }, + ], }, ], },