Skip to content

Commit 5ffccef

Browse files
committed
Add rule GCI1433 "No imported number format library"
...Handle numbro library only
1 parent e4ce6f1 commit 5ffccef

File tree

9 files changed

+235
-0
lines changed

9 files changed

+235
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- [#51](https://github.com/green-code-initiative/creedengo-javascript/pull/51) Add ESLint v9 and flat config support
13+
- [#84](https://github.com/green-code-initiative/creedengo-javascript/pull/84) Add rule GCI1433 "No imported number format library"
1314

1415
### Changed
1516

eslint-plugin/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ If your project uses a legacy ESLint version, it may use as well the now depreca
119119
| [limit-db-query-results](docs/rules/limit-db-query-results.md) | Should limit the number of returns for a SQL query ||
120120
| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md) | Disallow usage of image with empty source attribute ||
121121
| [no-import-all-from-library](docs/rules/no-import-all-from-library.md) | Should not import all from library ||
122+
| [no-imported-number-format-library](docs/rules/no-imported-number-format-library.md) | You should not format number with an external library ||
122123
| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md) | Disallow multiple access of same DOM element ||
123124
| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md) | Disallow multiple style changes at once ||
124125
| [no-torch](docs/rules/no-torch.md) | Should not programmatically enable torch mode ||
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# You should not format number with an external library (`@creedengo/no-imported-number-format-library`)
2+
3+
⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
## Why is this an issue?
8+
9+
Importing an external library for lightweight operations increases overall size of the program.
10+
Using native methods instead reduces the amount of memory and storage to run and store the application.
11+
This is especially critical in environments with limited resources, such as on mobile devices or in web applications
12+
where bandwidth and download times matter.
13+
14+
Smaller programs generally have better runtime performance.
15+
Reducing the number of unnecessary modules minimizes the amount of code that needs to be interpreted or compiled,
16+
leading to faster execution and improved overall performance.
17+
18+
## Examples
19+
20+
**Example with the [numbro](https://numbrojs.com/) library, when you use
21+
`format` method.**
22+
23+
```js
24+
// Example with numbro
25+
import numbro from "numbro";
26+
27+
numbro.setLanguage('en-GB');
28+
var string = numbro(1000).format({
29+
thousandSeparated: true,
30+
}); // '1,000'
31+
32+
// Example with Intl
33+
new Intl.NumberFormat("en-GB").format(1000); // '1,000'
34+
```
35+
36+
## Resources
37+
38+
### Documentation
39+
40+
- [Mozilla Web Technology for Developers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) -
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
3+
* Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
"use strict";
20+
21+
/** @type {import("eslint").Rule.RuleModule} */
22+
module.exports = {
23+
meta: {
24+
type: "suggestion",
25+
docs: {
26+
description: "You should not format number with an external library",
27+
category: "eco-design",
28+
recommended: "warn",
29+
},
30+
messages: {
31+
ShouldNotUseImportedNumberFormatLibrary:
32+
"You should not format number with an external library",
33+
},
34+
schema: [],
35+
},
36+
37+
create: function (context) {
38+
let variablesNumbro = [];
39+
40+
const errorReport = (node) => ({
41+
node,
42+
messageId: "ShouldNotUseImportedNumberFormatLibrary",
43+
});
44+
45+
return {
46+
VariableDeclarator(node) {
47+
if (node.init.callee?.name === "numbro") {
48+
variablesNumbro.push(node.id.name);
49+
}
50+
},
51+
CallExpression(node) {
52+
const formatIsCalledOnANumbroTypeVariable =
53+
node.callee.type === "MemberExpression" &&
54+
variablesNumbro.includes(node.callee.object.name) &&
55+
node.callee.property.name === "format";
56+
if (formatIsCalledOnANumbroTypeVariable) {
57+
context.report(errorReport(node.callee.property));
58+
}
59+
let formatIsCalledOnNumbroInstance =
60+
node.parent.type === "MemberExpression" &&
61+
node.callee.name === "numbro" &&
62+
node.parent.property.name === "format";
63+
if (formatIsCalledOnNumbroInstance) {
64+
context.report(errorReport(node.parent.property));
65+
}
66+
},
67+
};
68+
},
69+
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
3+
* Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
"use strict";
20+
21+
//------------------------------------------------------------------------------
22+
// Requirements
23+
//------------------------------------------------------------------------------
24+
25+
const rule = require("../../../lib/rules/no-imported-number-format-library");
26+
const RuleTester = require("eslint").RuleTester;
27+
28+
//------------------------------------------------------------------------------
29+
// Tests
30+
//------------------------------------------------------------------------------
31+
32+
const ruleTester = new RuleTester({
33+
parserOptions: {
34+
ecmaVersion: 6,
35+
sourceType: "module",
36+
},
37+
});
38+
const expectedError = {
39+
messageId: "ShouldNotUseImportedNumberFormatLibrary",
40+
type: "Identifier",
41+
};
42+
43+
ruleTester.run("no-imported-number-format-library", rule, {
44+
valid: [
45+
"new Intl.NumberFormat().format(1000);",
46+
"numbro(1000).add(5);",
47+
`
48+
const number = numbro(1000);
49+
const number2 = numbro(2000);
50+
number2.add(1000);
51+
`,
52+
],
53+
invalid: [
54+
{
55+
code: "numbro(1000).format({thousandSeparated: true});",
56+
errors: [expectedError],
57+
},
58+
{
59+
code: `
60+
const number = numbro(1000);
61+
number.format({thousandSeparated: true});
62+
`,
63+
errors: [expectedError],
64+
},
65+
{
66+
code: `
67+
const number = numbro(1000);
68+
const number2 = numbro(2000);
69+
number.format({thousandSeparated: true});
70+
`,
71+
errors: [expectedError],
72+
},
73+
],
74+
});

sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/CheckList.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public static List<Class<? extends JavaScriptCheck>> getAllChecks() {
4242
LimitDbQueryResult.class,
4343
NoEmptyImageSrcAttribute.class,
4444
NoImportAllFromLibrary.class,
45+
NoImportedNumberFormatLibrary.class,
4546
NoMultipleAccessDomElement.class,
4647
NoMultipleStyleChanges.class,
4748
NoTorch.class,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
3+
* Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package org.greencodeinitiative.creedengo.javascript.checks;
19+
20+
import org.greencodeinitiative.creedengo.javascript.DeprecatedEcoCodeRule;
21+
import org.sonar.check.Rule;
22+
import org.sonar.plugins.javascript.api.EslintBasedCheck;
23+
import org.sonar.plugins.javascript.api.JavaScriptRule;
24+
import org.sonar.plugins.javascript.api.TypeScriptRule;
25+
26+
@JavaScriptRule
27+
@TypeScriptRule
28+
@Rule(key = NoImportedNumberFormatLibrary.RULE_KEY)
29+
public class NoImportedNumberFormatLibrary implements EslintBasedCheck {
30+
31+
public static final String RULE_KEY = "GCI1433";
32+
33+
@Override
34+
public String eslintKey() {
35+
return "@creedengo/no-imported-number-format-library";
36+
}
37+
38+
}

sonar-plugin/src/main/resources/org/greencodeinitiative/creedengo/profiles/javascript_profile.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "Creedengo",
33
"ruleKeys": [
4+
"GCI1433",
45
"GCI9",
56
"GCI11",
67
"GCI12",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import numbro from "numbro";
2+
3+
numbro(1000).format({thousandSeparated: true}); // Non-compliant: usage of external library to format number
4+
5+
let variable = numbro(1000);
6+
variable.format({thousandSeparated: true}); // Non-compliant: usage of external library to format number
7+
8+
numbro(2000).add(1000); // Compliant
9+
10+
new Intl.NumberFormat().format(1000); // Compliant

0 commit comments

Comments
 (0)