Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create rule S6861 (eslint-plugin-import/no-mutable-exports): Mutable variables should not be exported #4441

Merged
merged 1 commit into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions its/ruling/src/test/expected/jsts/Ghost/javascript-S6861.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"Ghost:core/client/app/app.js": [
12
],
"Ghost:core/client/app/router.js": [
11
],
"Ghost:core/client/app/utils/editor-shortcuts.js": [
6
],
"Ghost:core/client/tests/helpers/resolver.js": [
4
]
}
34 changes: 34 additions & 0 deletions its/ruling/src/test/expected/jsts/TypeScript/typescript-S6861.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"TypeScript:src/compiler/commandLineParser.ts": [
635
],
"TypeScript:src/compiler/core.ts": [
1217,
2224,
2242
],
"TypeScript:src/compiler/sys.ts": [
99
],
"TypeScript:src/compiler/utilities.ts": [
640,
641,
642,
4400
],
"TypeScript:src/harness/harness.ts": [
68,
499,
565,
589,
608,
688,
705,
780,
781,
874
],
"TypeScript:src/services/services.ts": [
938
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"ag-grid:src/ts/utils.ts": [
1080
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"ant-design:components/_util/warning.ts": [
9
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"console:src/views/FunctionsView/FunctionLogs/Codemirror.js": [
13
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"console:src/utils/metrics.ts": [
3
]
}
5 changes: 5 additions & 0 deletions its/ruling/src/test/expected/jsts/eigen/typescript-S6861.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"eigen:src/app/Scenes/MyProfile/MyProfilePayment.tsx": [
38
]
}
14 changes: 14 additions & 0 deletions its/ruling/src/test/expected/jsts/http/javascript-S6861.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"http:src/IConnection.js": [
3
],
"http:src/IInterceptResolution.js": [
5
],
"http:src/IRequest.js": [
3
],
"http:src/IResponse.js": [
3
]
}
20 changes: 20 additions & 0 deletions its/ruling/src/test/expected/jsts/jquery/javascript-S6861.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"jquery:src/core.js": [
19
],
"jquery:src/core/access.js": [
6
],
"jquery:src/core/init.js": [
9
],
"jquery:src/core/isAttached.js": [
6
],
"jquery:src/manipulation/wrapMap.js": [
2
],
"jquery:src/selector/rbuggyQSA.js": [
5
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"reddit-mobile:src/server/oauth.es6.js": [
18
],
"reddit-mobile:src/server/routes.es6.js": [
6
]
}
5 changes: 5 additions & 0 deletions its/ruling/src/test/expected/jsts/redux/javascript-S6861.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"redux:src/createStore.js": [
9
]
}
16 changes: 16 additions & 0 deletions its/ruling/src/test/expected/jsts/router/javascript-S6861.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"router:src/activation.js": [
5
],
"router:src/navigationPlan.js": [
1,
2,
3
],
"router:src/pipeline.js": [
10,
11,
12,
13
]
}
81 changes: 81 additions & 0 deletions its/ruling/src/test/expected/jsts/rxjs/typescript-S6861.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"rxjs:src/Rx.ts": [
193,
213
],
"rxjs:src/add/observable/bindCallback.ts": [
8
],
"rxjs:src/add/observable/bindNodeCallback.ts": [
8
],
"rxjs:src/add/observable/combineLatest.ts": [
8
],
"rxjs:src/add/observable/concat.ts": [
8
],
"rxjs:src/add/observable/defer.ts": [
8
],
"rxjs:src/add/observable/dom/ajax.ts": [
9
],
"rxjs:src/add/observable/dom/webSocket.ts": [
8
],
"rxjs:src/add/observable/empty.ts": [
8
],
"rxjs:src/add/observable/forkJoin.ts": [
8
],
"rxjs:src/add/observable/from.ts": [
8
],
"rxjs:src/add/observable/fromEvent.ts": [
8
],
"rxjs:src/add/observable/fromEventPattern.ts": [
8
],
"rxjs:src/add/observable/fromPromise.ts": [
8
],
"rxjs:src/add/observable/generate.ts": [
8
],
"rxjs:src/add/observable/interval.ts": [
8
],
"rxjs:src/add/observable/merge.ts": [
8
],
"rxjs:src/add/observable/never.ts": [
8
],
"rxjs:src/add/observable/of.ts": [
8
],
"rxjs:src/add/observable/onErrorResumeNext.ts": [
8
],
"rxjs:src/add/observable/pairs.ts": [
8
],
"rxjs:src/add/observable/race.ts": [
8
],
"rxjs:src/add/observable/range.ts": [
8
],
"rxjs:src/add/observable/timer.ts": [
8
],
"rxjs:src/add/observable/using.ts": [
8
],
"rxjs:src/add/observable/zip.ts": [
8
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"snoode:src/api.es6.js": [
16
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"sonar-web:src/main/js/apps/update-center/plugins.js": [
6
]
}
15 changes: 15 additions & 0 deletions its/ruling/src/test/expected/jsts/templating/javascript-S6861.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"templating:src/lib/types.js": [
3,
10,
17,
21,
25,
29,
35,
43,
57,
64,
73
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ public static List<Class<? extends JavaScriptCheck>> getAllChecks() {
NoMisusedPromisesCheck.class,
NoMixedContentCheck.class,
NoMixedEnumsCheck.class,
NoMutableExportsCheck.class,
NoNestedSwitchCheck.class,
NoNestedTemplateLiteralsCheck.class,
NoNewNativeNonconstructorCheck.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* 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.
*/
package org.sonar.javascript.checks;

import org.sonar.check.Rule;
import org.sonar.plugins.javascript.api.EslintBasedCheck;
import org.sonar.plugins.javascript.api.JavaScriptRule;
import org.sonar.plugins.javascript.api.TypeScriptRule;

@TypeScriptRule
@JavaScriptRule
@Rule(key = "S6861")
public class NoMutableExportsCheck implements EslintBasedCheck {

@Override
public String eslintKey() {
return "no-mutable-exports";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<h2>Why is this an issue?</h2>
<p>In JavaScript, a mutable variable is one whose value can be changed after it has been initially set. This is in contrast to immutable variables,
whose values cannot be changed once they are set.</p>
<p>Exporting mutable variables can lead to unpredictable behavior and bugs in your code. This is because any module that imports the variable can
change its value. If multiple modules import and change the value of the same variable, it can become difficult to track what the current value of the
variable is and which module changed it last.</p>
<h2>How to fix it</h2>
<p>If the value of the variable does not need to change, you can declare it as a constant using the <code>const</code> keyword. Alternatively, if you
have a group of related variables that need to be mutable, consider using a class to encapsulate them. You can then export an instance of the class,
or a factory function that creates instances of the class.</p>
<h3>Code examples</h3>
<h4>Noncompliant code example</h4>
<pre>
let mutableVar = "initial value";

export { mutableVar }; // Noncompliant
</pre>
<h4>Compliant solution</h4>
<pre>
const immutableVar = "constant value";
export { immutableVar };
</pre>
<p>or</p>
<pre>
class MyClass {
constructor() {
this.mutableVar = "initial value";
}
}

export function createMyClass() {
return new MyClass();
}
</pre>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
<li> MDN web docs - <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let">let</a> </li>
<li> MDN web docs - <a href="https://developer.mozilla.org/en-US/docs/Glossary/Mutable">Mutable</a> </li>
<li> MDN web docs - <a href="https://developer.mozilla.org/en-US/docs/Glossary/Immutable">Immutable</a> </li>
</ul>

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"title": "Mutable variables should not be exported",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [],
"defaultSeverity": "Major",
"ruleSpecification": "RSPEC-6861",
"sqKey": "S6861",
"scope": "All",
"quickfix": "infeasible",
"code": {
"impacts": {
"MAINTAINABILITY": "HIGH",
"RELIABILITY": "MEDIUM"
},
"attribute": "CONVENTIONAL"
},
"compatibleLanguages": [
"JAVASCRIPT",
"TYPESCRIPT"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@
"S6853",
"S6854",
"S6855",
"S6859"
"S6859",
"S6861"
]
}