Skip to content

Commit

Permalink
Add quick fix for S4621 ('no-duplicate-in-composite')
Browse files Browse the repository at this point in the history
  • Loading branch information
yassin-kammoun-sonarsource committed Mar 22, 2022
1 parent 8ee58e3 commit e2b4f73
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
1 change: 1 addition & 0 deletions eslint-bridge/src/quickfix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const quickFixRules = new Set([
'inverted-assertion-arguments',
'no-alphabetical-sort',
'no-commented-code',
'no-duplicate-in-composite',
'no-global-this',
'no-in-misuse',
'no-primitive-wrappers',
Expand Down
32 changes: 31 additions & 1 deletion eslint-bridge/src/rules/no-duplicate-in-composite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// https://jira.sonarsource.com/browse/RSPEC-4621
// https://sonarsource.github.io/rspec/#/rspec/S4621/javascript

import { Rule } from 'eslint';
import * as estree from 'estree';
Expand All @@ -26,6 +26,7 @@ import { toEncodedMessage } from '../utils';

export const rule: Rule.RuleModule = {
meta: {
hasSuggestions: true,
schema: [
{
// internal parameter for rules having secondary locations
Expand Down Expand Up @@ -54,6 +55,7 @@ export const rule: Rule.RuleModule = {

groupedTypes.forEach(duplicates => {
if (duplicates.length > 1) {
const suggest = getSuggestions(compositeType, duplicates.slice(1), context);
const primaryNode = duplicates.splice(1, 1)[0];
const secondaryMessages = Array(duplicates.length);
secondaryMessages[0] = `Original`;
Expand All @@ -66,10 +68,38 @@ export const rule: Rule.RuleModule = {
secondaryMessages,
),
loc: primaryNode.loc,
suggest,
});
}
});
},
};
},
};

function getSuggestions(
composite: TSESTree.TSUnionType | TSESTree.TSIntersectionType,
duplicates: TSESTree.Node[],
context: Rule.RuleContext,
): Rule.SuggestionReportDescriptor[] {
const uniqueTypes = composite.types.filter(tpe => !duplicates.includes(tpe));
const uniqueTexts = uniqueTypes.map(tpe =>
context.getSourceCode().getText(tpe as unknown as estree.Node),
);
const compositeNode = composite as unknown as estree.Node;
const firstToken = context.getSourceCode().getFirstToken(compositeNode);
const lastToken = context.getSourceCode().getLastToken(compositeNode);
let [prefix, suffix] = ['', ''];
if (firstToken?.value === '(' && lastToken?.value === ')') {
prefix = '(';
suffix = ')';
}
const typeSeparator = composite.type === 'TSUnionType' ? ' | ' : ' & ';
const newComposite = `${prefix}${uniqueTexts.join(typeSeparator)}${suffix}`;
return [
{
desc: 'Remove duplicate types',
fix: fixer => fixer.replaceText(compositeNode, newComposite),
},
];
}
85 changes: 85 additions & 0 deletions eslint-bridge/tests/rules/no-duplicate-in-composite.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,91 @@ ruleTester.run(
type nokIUnion = (number | string) & (number | string);`,
errors: 12,
},
{
code: `type T = number | number`,
errors: [
{
suggestions: [
{
desc: 'Remove duplicate types',
output: `type T = number`,
},
],
},
],
},
{
code: `type T = number & number`,
errors: [
{
suggestions: [
{
output: `type T = number`,
},
],
},
],
},
{
code: `type T = number | number | number`,
errors: [
{
suggestions: [
{
output: `type T = number`,
},
],
},
],
},
{
code: `type T = number | string | number`,
errors: [
{
suggestions: [
{
output: `type T = number | string`,
},
],
},
],
},
{
code: `type T = string | number | number`,
errors: [
{
suggestions: [
{
output: `type T = string | number`,
},
],
},
],
},
{
code: `type T = number | string | boolean | number`,
errors: [
{
suggestions: [
{
output: `type T = number | string | boolean`,
},
],
},
],
},
{
code: `type T = (number | string) & (number | string)`,
errors: [
{
suggestions: [
{
output: `type T = (number | string)`,
},
],
},
],
},
],
},
);

0 comments on commit e2b4f73

Please sign in to comment.