Skip to content

Commit

Permalink
Fix FP S6749 (jsx-no-useless-fragment): Ignore empty React fragments
Browse files Browse the repository at this point in the history
  • Loading branch information
yassin-kammoun-sonarsource committed Sep 21, 2023
1 parent cb6d786 commit e261284
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 59 deletions.
6 changes: 0 additions & 6 deletions its/ruling/src/test/expected/js/fireact/javascript-S6749.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
{
"fireact:src/components/Loader/index.js": [
24
],
"fireact:src/components/Logo/index.js": [
6
],
Expand All @@ -14,9 +11,6 @@
"fireact:src/pages/auth/accounts/DeleteAccount/index.js": [
57
],
"fireact:src/pages/auth/accounts/PaymentList/index.js": [
72
],
"fireact:src/pages/auth/accounts/PaymentMethod/index.js": [
131
]
Expand Down
16 changes: 0 additions & 16 deletions its/ruling/src/test/expected/ts/courselit/typescript-S6749.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,7 @@
"courselit:apps/web/components/public/base-layout/scaffold/drawer-content.tsx": [
57
],
"courselit:apps/web/components/public/base-layout/template/section.tsx": [
40
],
"courselit:apps/web/components/public/checkout/index.tsx": [
32,
33
],
"courselit:apps/web/components/public/code-injector.tsx": [
45
],
"courselit:apps/web/components/public/items.tsx": [
90
],
"courselit:apps/web/components/public/purchase-status.tsx": [
105
],
"courselit:packages/common-widgets/src/tagged-content/widget.tsx": [
77
]
}
37 changes: 0 additions & 37 deletions its/ruling/src/test/expected/ts/eigen/typescript-S6749.json
Original file line number Diff line number Diff line change
@@ -1,63 +1,26 @@
{
"eigen:src/app/Components/AuctionResultsList.tsx": [
90
],
"eigen:src/app/Components/States/ZeroState.tsx": [
17,
27
],
"eigen:src/app/Components/StickyTabPage/StickyTabPage.tsx": [
51
],
"eigen:src/app/Scenes/Artist/SearchCriteria.tests.tsx": [
18,
33,
52,
57,
66
],
"eigen:src/app/Scenes/Artwork/Components/CommercialButtons/InquiryModal.tsx": [
77
],
"eigen:src/app/Scenes/Artwork/Components/CommercialEditionSetInformation.tsx": [
57
],
"eigen:src/app/Scenes/City/Components/SavedEventSection/index.tsx": [
46
],
"eigen:src/app/Scenes/Home/Components/AuctionResultsRail.tsx": [
51
],
"eigen:src/app/Scenes/Home/Components/FairsRail.tsx": [
57
],
"eigen:src/app/Scenes/Home/Home.tsx": [
206
],
"eigen:src/app/Scenes/MyBids/MyBids.tsx": [
114
],
"eigen:src/app/Scenes/MyCollection/Screens/Artwork/Components/ArtworkInsights/MyCollectionArtworkArtistAuctionResults.tsx": [
50
],
"eigen:src/app/Scenes/MyCollection/Screens/Artwork/Components/MyCollectionArtworkHeader.tsx": [
112
],
"eigen:src/app/Scenes/SavedAddresses/SavedAddresses.tsx": [
165
],
"eigen:src/app/Scenes/SavedSearchAlertsList/Components/SavedSearchAlertsListPlaceholder.tsx": [
8
],
"eigen:src/app/Scenes/Search/components/placeholders/AlgoliaSearchPlaceholder.tsx": [
15
],
"eigen:src/app/Scenes/SellWithArtsy/SubmitArtwork/SubmitArtwork.tsx": [
217
],
"eigen:src/app/Scenes/Tag/Tag.tsx": [
65
],
"eigen:src/palette/elements/CollapsibleMenuItem/CollapsibleMenuItem.stories.tsx": [
154
],
Expand Down
46 changes: 46 additions & 0 deletions packages/jsts/src/rules/S6749/decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2011-2023 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// https://sonarsource.github.io/rspec/#/rspec/S6749/javascript

import { Rule } from 'eslint';
import { interceptReport } from '../helpers';

/**
* The core implementation of the rule reports on empty React fragments.
* Also, one of the two issue messages include a Unicode character.
*/
export function decorate(rule: Rule.RuleModule): Rule.RuleModule {
rule.meta!.hasSuggestions = true;
rule.meta!.messages = {
...rule.meta!.messages,
/* Map to a more friendly message */
NeedsMoreChildren: 'A fragment with only one child is redundant.',
};
return interceptReport(rule, (context, descriptor) => {
const { messageId, node, ...rest } = descriptor as any;

/* Ignore empty fragments */
if (node.type === 'JSXFragment' && node.children.length === 0) {
return;
}

context.report({ messageId, node, ...rest });
});
}
23 changes: 23 additions & 0 deletions packages/jsts/src/rules/S6749/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2011-2023 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { rules } from 'eslint-plugin-react';
import { decorate } from './decorator';

export const rule = decorate(rules['jsx-no-useless-fragment']);
43 changes: 43 additions & 0 deletions packages/jsts/src/rules/S6749/unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2011-2023 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { RuleTester } from 'eslint';
import { rule } from './';

const ruleTester = new RuleTester({
parserOptions: { ecmaVersion: 2018, ecmaFeatures: { jsx: true } },
});
ruleTester.run('Redundant React fragments should be removed', rule, {
valid: [
{
code: `function Empty() { return <></>; }`,
},
],
invalid: [
{
code: `function Child() { return <><img /></>; }`,
output: `function Child() { return <img />; }`,
errors: [
{
message: 'A fragment with only one child is redundant.',
},
],
},
],
});
2 changes: 2 additions & 0 deletions packages/jsts/src/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ import { rule as S5659 } from './S5659'; // insecure-jwt-token
import { rule as S3415 } from './S3415'; // inverted-assertion-arguments
import { rule as S6477 } from './S6477'; // jsx-key
import { rule as S6481 } from './S6481'; // jsx-no-constructed-context-values
import { rule as S6749 } from './S6749'; // jsx-no-useless-fragment
import { rule as S1439 } from './S1439'; // label-position
import { rule as S5148 } from './S5148'; // link-with-target-blank
import { rule as S4622 } from './S4622'; // max-union-size
Expand Down Expand Up @@ -381,6 +382,7 @@ rules['insecure-jwt-token'] = S5659;
rules['inverted-assertion-arguments'] = S3415;
rules['jsx-key'] = S6477;
rules['jsx-no-constructed-context-values'] = S6481;
rules['jsx-no-useless-fragment'] = S6749;
rules['label-position'] = S1439;
rules['link-with-target-blank'] = S5148;
rules['max-union-size'] = S4622;
Expand Down

0 comments on commit e261284

Please sign in to comment.