@putout/plugin-destructuring 1.2.0 → 1.4.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
@@ -17,9 +17,11 @@ npm i @putout/plugin-destructuring
17
17
 
18
18
  ## Rules
19
19
 
20
- - ✅ [apply-object](#apply-object);
21
20
  - ✅ [apply-array](#apply-array);
21
+ - ✅ [apply-object](#apply-object);
22
+ - ✅ [apply-declarations-order](#apply-declarations-order);
22
23
  - ✅ [convert-object-to-array](#convert-object-to-array);
24
+ - ✅ [extract-properties](#extract-properties);
23
25
  - ✅ [remove-useless-object](#remove-useless-object);
24
26
  - ✅ [remove-useless-arguments](#remove-useless-arguments);
25
27
  - ✅ [remove-useless-variables](#remove-useless-variables);
@@ -32,9 +34,11 @@ npm i @putout/plugin-destructuring
32
34
  ```json
33
35
  {
34
36
  "rules": {
35
- "destructuring/apply-object": "on",
36
37
  "destructuring/apply-array": "on",
38
+ "destructuring/apply-object": "on",
39
+ "destructuring/apply-declarations-order": "on",
37
40
  "destructuring/convert-object-to-array": "on",
41
+ "destructuring/extract-properties": "on",
38
42
  "destructuring/remove-useless-object": "on",
39
43
  "destructuring/remove-useless-arguments": "on",
40
44
  "destructuring/remove-useless-variables": "on",
@@ -53,7 +57,7 @@ npm i @putout/plugin-destructuring
53
57
  const first = array[0];
54
58
  ```
55
59
 
56
- ## ✅ Example of correct code
60
+ ### ✅ Example of correct code
57
61
 
58
62
  ```js
59
63
  const [first] = array;
@@ -77,6 +81,24 @@ const {name} = user;
77
81
  ({hello} = world);
78
82
  ```
79
83
 
84
+ ## apply-declarations-order
85
+
86
+ Helps to [extract-properties](#extract-properties'). Checkout in 🐊[**Putout Editor**](https://putout.vercel.app/#/gist/b70ff926b36e1e97ec7129aa0e0458a7/ece0a706de2fd24a66b4671284f7f75017f3c268).
87
+
88
+ ### ❌ Example of incorrect code
89
+
90
+ ```js
91
+ const {env} = require('node:process');
92
+ const process = require('node:process');
93
+ ```
94
+
95
+ ### ✅ Example of correct code
96
+
97
+ ```js
98
+ const process = require('node:process');
99
+ const {env} = process;
100
+ ```
101
+
80
102
  ## remove-useless-object
81
103
 
82
104
  Check out in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/c9ed04b421d75ae39e58038fa6e14630/4c097e3173990ec7e5ebabbe2cedf8e952092ebf).
@@ -118,8 +140,6 @@ const [a, b] = c;
118
140
  >
119
141
  > (c) [Destructuring in JavaScript: the not so good parts](https://goodguydaniel.com/blog/destructuring-not-so-good-parts)
120
142
 
121
- 🐊[**Putout**](https://github.com/coderaiser/putout) plugin adds ability to split nested destructuring.
122
-
123
143
  ### ❌ Example of incorrect code
124
144
 
125
145
  ```js
@@ -196,7 +216,7 @@ const {one, two} = require('numbers');
196
216
  } = data);
197
217
  ```
198
218
 
199
- ### remove-useless-arguments
219
+ ## remove-useless-arguments
200
220
 
201
221
  ### ❌ Example of incorrect code
202
222
 
@@ -237,6 +257,42 @@ function hi(c) {
237
257
  function hi({a, b}) {}
238
258
  ```
239
259
 
260
+ ## extract-properties
261
+
262
+ ### Equal Deep
263
+
264
+ #### ❌ Example of incorrect code
265
+
266
+ ```js
267
+ const {replaceWith} = a.operate;
268
+ const {isIdentifier} = a.types;
269
+ ```
270
+
271
+ #### ✅ Example of correct code
272
+
273
+ ```js
274
+ const {operator, types} = a;
275
+
276
+ const {replaceWith} = operator;
277
+ const {isIdentifier} = types;
278
+ ```
279
+
280
+ ### Not Equal Deep
281
+
282
+ #### ❌ Example of incorrect code
283
+
284
+ ```js
285
+ const {replaceWith} = a;
286
+ const {isIdentifier} = a.types;
287
+ ```
288
+
289
+ #### ✅ Example of correct code
290
+
291
+ ```js
292
+ const {replaceWith, types} = a;
293
+ const {isIdentifier} = types;
294
+ ```
295
+
240
296
  ## License
241
297
 
242
298
  MIT
@@ -0,0 +1,40 @@
1
+ import {types, operator} from 'putout';
2
+
3
+ const {
4
+ insertAfter,
5
+ remove,
6
+ compare,
7
+ getTemplateValues,
8
+ } = operator;
9
+
10
+ const {
11
+ isVariableDeclaration,
12
+ isIdentifier,
13
+ } = types;
14
+
15
+ export const report = () => `Apply declarations order`;
16
+
17
+ export const fix = ({path, current}) => {
18
+ const {node} = current;
19
+ remove(current);
20
+ insertAfter(path, node);
21
+ };
22
+
23
+ export const traverse = ({push}) => ({
24
+ 'const __a = __b': (path) => {
25
+ const {__a, __b} = getTemplateValues(path, 'const __a = __b');
26
+
27
+ if (!isIdentifier(__a))
28
+ return;
29
+
30
+ const prev = path.getAllPrevSiblings();
31
+
32
+ for (const current of prev.filter(isVariableDeclaration)) {
33
+ if (compare(__b, current.node.declarations[0].init))
34
+ push({
35
+ current,
36
+ path,
37
+ });
38
+ }
39
+ },
40
+ });
@@ -0,0 +1,78 @@
1
+ import {
2
+ template,
3
+ generate,
4
+ types,
5
+ operator,
6
+ } from 'putout';
7
+
8
+ const {
9
+ findBinding,
10
+ replaceWith,
11
+ getTemplateValues,
12
+ } = operator;
13
+
14
+ const {
15
+ isIdentifier,
16
+ isCallExpression,
17
+ } = types;
18
+
19
+ export const report = () => `Extract object properties into variables`;
20
+
21
+ const buildAst = template(`
22
+ const {PROPERTY} = OBJECT;
23
+ `);
24
+
25
+ export const fix = ({items}) => {
26
+ const names = [];
27
+
28
+ for (const item of items) {
29
+ const {object, property} = item.node;
30
+
31
+ if (isIdentifier(property) && !names.includes(property.name)) {
32
+ names.push(property.name);
33
+
34
+ const {body = item.scope.block.body} = item.scope.block.body;
35
+
36
+ body.unshift(buildAst({
37
+ PROPERTY: property,
38
+ OBJECT: object,
39
+ }));
40
+ }
41
+
42
+ replaceWith(item, item.node.property);
43
+ }
44
+ };
45
+
46
+ export const traverse = ({uplist, push}) => ({
47
+ 'const __object = __a.__b': (fullPath) => {
48
+ const {__a, __b} = getTemplateValues(fullPath, 'const __object = __a.__b');
49
+ const initPath = fullPath.get('declarations.0.init');
50
+ const {uid} = initPath.scope;
51
+
52
+ if (findBinding(fullPath, __b.name))
53
+ return;
54
+
55
+ if (isIdentifier(__a) || isCallExpression(__a)) {
56
+ const {code} = generate(__a);
57
+ const id = `${uid}-${code}`;
58
+
59
+ return uplist(id, initPath);
60
+ }
61
+ },
62
+ 'Program': {
63
+ exit: () => {
64
+ for (const items of uplist()) {
65
+ if (items.length < 2)
66
+ continue;
67
+
68
+ const index = items.length - 1;
69
+ const path = items[index];
70
+
71
+ push({
72
+ path,
73
+ items,
74
+ });
75
+ }
76
+ },
77
+ },
78
+ });
@@ -0,0 +1,72 @@
1
+ import {operator, types} from 'putout';
2
+
3
+ const {objectProperty} = types;
4
+
5
+ const {replaceWith, compare} = operator;
6
+
7
+ const SHORTHAND = true;
8
+ const COMPUTED = false;
9
+
10
+ export const report = () => `Extract object properties into variables`;
11
+
12
+ export const fix = ({path, expandPath, property}) => {
13
+ const newProperty = objectProperty(property, property, COMPUTED, SHORTHAND);
14
+
15
+ expandPath.node.properties.push(newProperty);
16
+ replaceWith(path, property);
17
+ };
18
+
19
+ export const traverse = ({listStore, push}) => ({
20
+ 'const __object = __a.__b': save({
21
+ listStore,
22
+ }),
23
+ 'const __object = __a(__args)': save({
24
+ listStore,
25
+ }),
26
+ 'Program': {
27
+ exit: exit({
28
+ push,
29
+ listStore,
30
+ }),
31
+ },
32
+ });
33
+
34
+ const save = ({listStore}) => (path) => {
35
+ const idPath = path.get('declarations.0.id');
36
+ const initPath = path.get('declarations.0.init');
37
+
38
+ listStore([initPath, idPath]);
39
+ };
40
+
41
+ const exit = ({push, listStore}) => () => {
42
+ const items = listStore();
43
+
44
+ for (const [initPath] of items) {
45
+ for (const [currentPath, expandPath] of items) {
46
+ const objectPath = initPath.get('object');
47
+
48
+ if (!objectPath.isMemberExpression() && !objectPath.isCallExpression())
49
+ continue;
50
+
51
+ const propertyPath = initPath.get('property');
52
+ const property = propertyPath.node;
53
+
54
+ const current = currentPath.node;
55
+ const {object} = initPath.node;
56
+ const {name} = property;
57
+
58
+ if (expandPath.scope.bindings[name])
59
+ continue;
60
+
61
+ if (expandPath.scope.uid !== initPath.scope.uid)
62
+ continue;
63
+
64
+ if (compare(object, current))
65
+ push({
66
+ expandPath,
67
+ path: initPath,
68
+ property,
69
+ });
70
+ }
71
+ }
72
+ };
package/lib/index.js CHANGED
@@ -1,6 +1,9 @@
1
- import * as convertObjectToArray from './convert-object-to-array/index.js';
1
+ import * as applyDeclarationsOrder from './apply-declarations-order/index.js';
2
2
  import * as applyObject from './apply-object/index.js';
3
3
  import * as applyArray from './apply-array/index.js';
4
+ import * as extractPropertiesEqualDeep from './extract-properties-equal-deep/index.js';
5
+ import * as extractPropertiesNotEqualDeep from './extract-properties-not-equal-deep/index.js';
6
+ import * as convertObjectToArray from './convert-object-to-array/index.js';
4
7
  import * as removeUselessObject from './remove-useless-object/index.js';
5
8
  import * as removeUselessArguments from './remove-useless-arguments/index.js';
6
9
  import * as removeUselessVariables from './remove-useless-variables/index.js';
@@ -9,12 +12,15 @@ import * as splitCall from './split-call/index.js';
9
12
  import * as mergeProperties from './merge-properties/index.js';
10
13
 
11
14
  export const rules = {
12
- 'apply-object': applyObject,
13
15
  'apply-array': applyArray,
16
+ 'apply-object': applyObject,
17
+ 'apply-declarations-order': applyDeclarationsOrder,
18
+ 'convert-object-to-array': convertObjectToArray,
19
+ 'extract-properties-equal-deep': extractPropertiesEqualDeep,
20
+ 'extract-properties-not-equal-deep': extractPropertiesNotEqualDeep,
14
21
  'remove-useless-object': removeUselessObject,
15
22
  'remove-useless-arguments': removeUselessArguments,
16
23
  'remove-useless-variables': removeUselessVariables,
17
- 'convert-object-to-array': convertObjectToArray,
18
24
  'split-nested': splitNested,
19
25
  'split-call': splitCall,
20
26
  'merge-properties': mergeProperties,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/plugin-destructuring",
3
- "version": "1.2.0",
3
+ "version": "1.4.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 transform destructuring",
@@ -23,7 +23,9 @@
23
23
  "coverage": "madrun coverage",
24
24
  "report": "madrun report"
25
25
  },
26
- "dependencies": {},
26
+ "dependencies": {
27
+ "redput": "^3.6.0"
28
+ },
27
29
  "keywords": [
28
30
  "putout",
29
31
  "putout-plugin",
@@ -39,9 +41,10 @@
39
41
  "@putout/plugin-printer": "*",
40
42
  "@putout/plugin-putout": "*",
41
43
  "@putout/plugin-tape": "*",
44
+ "@putout/plugin-variables": "*",
42
45
  "@putout/test": "^14.0.0",
43
46
  "c8": "^10.0.0",
44
- "eslint": "v10.0.0-alpha.0",
47
+ "eslint": "^10.0.0-alpha.0",
45
48
  "eslint-plugin-n": "^17.0.0",
46
49
  "eslint-plugin-putout": "^29.0.0",
47
50
  "madrun": "^11.0.0",