@putout/plugin-variables 1.1.0 β†’ 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,11 @@
3
3
  [NPMIMGURL]: https://img.shields.io/npm/v/@putout/plugin-variables.svg?style=flat&longCache=true
4
4
  [NPMURL]: https://npmjs.org/package/@putout/plugin-variables "npm"
5
5
 
6
- 🐊[**Putout**](https://github.com/coderaiser/putout) plugin adds ability to find and remove `useless variables`.
6
+ > A **variable** is a named reference to a **value**.
7
+ >
8
+ > (c) [MDN](https://developer.mozilla.org/en-US/docs/Glossary/Variable)
9
+
10
+ 🐊[**Putout**](https://github.com/coderaiser/putout) plugin adds ability to transform `variables`.
7
11
 
8
12
  ## Install
9
13
 
@@ -18,6 +22,7 @@ npm i @putout/plugin-variables -D
18
22
  - βœ… [remove-useless-duplicate](#remove-useless-duplicate);
19
23
  - βœ… [remove-useless-variables](#remove-useless-variables);
20
24
  - βœ… [remove-useless-rename](#remove-useless-rename);
25
+ - βœ… [split-declarations](#split-declarations);
21
26
 
22
27
  ## Config
23
28
 
@@ -30,7 +35,8 @@ npm i @putout/plugin-variables -D
30
35
  }],
31
36
  "variables/remove-useless-duplicate": "on",
32
37
  "variables/remove-useless-rename": "on",
33
- "variables/remove-useless-remove": "on"
38
+ "variables/remove-useless-remove": "on",
39
+ "variables/split-declarations": "on"
34
40
  }
35
41
  }
36
42
  ```
@@ -157,10 +163,6 @@ bc = b.c.replace('x', 'y');
157
163
 
158
164
  ## remove-unreferenced
159
165
 
160
- > A **variable** is a named reference to a **value**.
161
- >
162
- > (c) [MDN](https://developer.mozilla.org/en-US/docs/Glossary/Variable)
163
-
164
166
  ### ❌ Example of incorrect code
165
167
 
166
168
  ```js
@@ -183,6 +185,61 @@ a = 5;
183
185
  console.log(a);
184
186
  ```
185
187
 
188
+ ## split-declarations
189
+
190
+ > - The [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) statement declares a block-scoped local variable, optionally initializing it to a value.
191
+ > - [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) statements are also block-scoped. The value of a constant can't be changed through reassignment, and it can't be redeclared. However, if a constant is an **object** or **array** its properties or items can be updated or removed.
192
+ >
193
+ > (c) MDN
194
+
195
+ Add ability to find and split variable declarations because (re)moving a line is simpler and less error prone then changing coma (`,`) to colon (`;`).
196
+ For the same reason, **diff** of changed declarations are more comfortable to read.
197
+
198
+ ### ❌ Example of incorrect code
199
+
200
+ ```js
201
+ let a, b;
202
+ ```
203
+
204
+ ### βœ… Example of correct code
205
+
206
+ ```js
207
+ let a;
208
+ let b;
209
+ ```
210
+
211
+ ### Comparison
212
+
213
+ Linter | Rule | Fix
214
+ --------|-------|------------|
215
+ 🐊 **Putout** | [`remove-debugger`](https://github.com/coderaiser/putout/tree/master/packages/plugin-split-variable-declarations#readme) | βœ…
216
+ ⏣ **ESLint** | [`no-var`](https://eslint.org/docs/latest/rules/one-var) | βœ…
217
+
218
+ ## convert-const-to-let
219
+
220
+ > The `TypeError` object represents an error when attempting to modify a value that cannot be changed.
221
+ >
222
+ > (c) [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError)
223
+
224
+ Convert `const` to `let` to avoid `TypeError`.
225
+ Check out in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/61ffff64a356c47e66af4ea17a9a755d/e7f5fa455c208a7faa9319d94130996d39afcbf7).
226
+
227
+ ### ❌ Example of incorrect code
228
+
229
+ ```js
230
+ let a = 5;
231
+
232
+ a = 3;
233
+ ```
234
+
235
+ ### βœ… Example of correct code
236
+
237
+ ```js
238
+ let a = 5;
239
+
240
+ a = 3;
241
+ ```
242
+
186
243
  ## License
187
244
 
188
245
  MIT
@@ -0,0 +1,69 @@
1
+ import {types} from 'putout';
2
+
3
+ const {
4
+ isBlockStatement,
5
+ isProgram,
6
+ } = types;
7
+
8
+ const {values} = Object;
9
+
10
+ const isKeyword = (a) => [
11
+ 'export',
12
+ 'const',
13
+ 'let',
14
+ 'var',
15
+ ].includes(a);
16
+
17
+ const isInsideBlock = ({parentPath}) => isProgram(parentPath) || isBlockStatement(parentPath);
18
+
19
+ export const report = () => `Use 'let' when reassign`;
20
+
21
+ export const fix = (path) => {
22
+ path.node.kind = 'let';
23
+ };
24
+
25
+ export const traverse = ({push}) => ({
26
+ VariableDeclaration: (path) => {
27
+ if (path.parentPath.isTSModuleBlock())
28
+ return;
29
+
30
+ const {scope} = path;
31
+ const {declare} = path.node;
32
+
33
+ if (declare)
34
+ return;
35
+
36
+ for (const binding of values(scope.bindings)) {
37
+ const {parentPath, node} = binding.path;
38
+ const {init} = node;
39
+
40
+ if (init && binding.constant)
41
+ continue;
42
+
43
+ if (isLoop(parentPath) && binding.constant)
44
+ continue;
45
+
46
+ if (!binding.path.isVariableDeclarator())
47
+ continue;
48
+
49
+ if (isKeyword(binding.path.node.id.name))
50
+ continue;
51
+
52
+ if (!binding.path.node.init && isInsideBlock(binding.path.parentPath))
53
+ continue;
54
+
55
+ if (parentPath.node.kind === 'const')
56
+ push(binding.path.parentPath);
57
+ }
58
+ },
59
+ });
60
+
61
+ const isLoop = ({parentPath}) => {
62
+ if (!parentPath)
63
+ return false;
64
+
65
+ if (parentPath.isForOfStatement())
66
+ return true;
67
+
68
+ return parentPath.isForInStatement();
69
+ };
package/lib/index.js CHANGED
@@ -1,15 +1,19 @@
1
+ import * as convertConstToLet from './convert-const-to-let/index.js';
1
2
  import * as removeUseless from './remove-useless/index.js';
2
3
  import * as removeUselessAssignment from './remove-useless-assignment/index.js';
3
4
  import * as removeUselessDeclarations from './remove-useless-declarations/index.js';
4
5
  import * as removeUselessDuplicates from './remove-useless-duplicates/index.js';
5
6
  import * as removeUselessRename from './remove-useless-rename/index.js';
6
7
  import * as removeUnreferenced from './remove-unreferenced/index.js';
8
+ import * as splitDeclarations from './split-declarations/index.js';
7
9
 
8
10
  export const rules = {
11
+ 'convert-const-to-let': convertConstToLet,
9
12
  'remove-useless': removeUseless,
10
13
  'remove-useless-assignment': removeUselessAssignment,
11
14
  'remove-useless-declarations': removeUselessDeclarations,
12
15
  'remove-useless-duplicates': removeUselessDuplicates,
13
16
  'remove-useless-rename': removeUselessRename,
14
17
  'remove-unreferenced': removeUnreferenced,
18
+ 'split-declarations': splitDeclarations,
15
19
  };
@@ -4,7 +4,9 @@ const {remove} = operator;
4
4
 
5
5
  export const report = () => 'Avoid unreferenced variables';
6
6
 
7
- export const fix = (path) => remove(path);
7
+ export const fix = (path) => {
8
+ remove(path);
9
+ };
8
10
 
9
11
  export const traverse = ({push}) => ({
10
12
  'return __a'(path) {
@@ -95,4 +97,9 @@ function getPropertyPath(path, name) {
95
97
  return propPath;
96
98
  }
97
99
 
98
- const isInsideForOf = (path) => path.__putout_for_of_reduce;
100
+ function isInsideForOf(path) {
101
+ if (path.isForOfStatement())
102
+ return true;
103
+
104
+ return path.__putout_for_of_reduce;
105
+ }
@@ -0,0 +1,67 @@
1
+ import {types, operator} from 'putout';
2
+
3
+ const {
4
+ isForStatement,
5
+ variableDeclaration,
6
+ } = types;
7
+
8
+ const {
9
+ replaceWithMultiple,
10
+ isKeyword,
11
+ } = operator;
12
+
13
+ export const report = () => 'Variables should be declared separately';
14
+
15
+ export const fix = (path) => {
16
+ const {node} = path;
17
+ const varNodes = getVarNodes(node);
18
+
19
+ replaceWithMultiple(path, varNodes);
20
+ };
21
+
22
+ export const traverse = ({push}) => ({
23
+ VariableDeclaration(path) {
24
+ const {
25
+ node,
26
+ parent,
27
+ parentPath,
28
+ } = path;
29
+
30
+ const {declarations} = node;
31
+
32
+ if (parentPath.isExportDeclaration())
33
+ return;
34
+
35
+ if (declarations.length === 1)
36
+ return;
37
+
38
+ for (const declaration of declarations) {
39
+ const {name} = declaration.id;
40
+
41
+ if (isKeyword(name))
42
+ return;
43
+ }
44
+
45
+ const init = node;
46
+
47
+ if (isForStatement(parent, {init}))
48
+ return;
49
+
50
+ push(path);
51
+ },
52
+ });
53
+
54
+ function getVarNodes({kind, declarations}) {
55
+ const result = [];
56
+
57
+ for (const declaration of declarations) {
58
+ const declarations = [declaration];
59
+
60
+ result.push(variableDeclaration(
61
+ kind,
62
+ declarations,
63
+ ));
64
+ }
65
+
66
+ return result;
67
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/plugin-variables",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "🐊Putout plugin adds ability to find and remove useless",
@@ -40,6 +40,7 @@
40
40
  "@putout/plugin-for-of": "*",
41
41
  "@putout/plugin-maybe": "*",
42
42
  "@putout/plugin-minify": "*",
43
+ "@putout/plugin-remove-unused-variables": "*",
43
44
  "@putout/plugin-remove-useless-array-from": "*",
44
45
  "@putout/plugin-reuse-duplicate-init": "*",
45
46
  "@putout/test": "^14.0.0",