@putout/plugin-destructuring 1.0.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/LICENSE +21 -0
- package/README.md +197 -0
- package/lib/array/index.js +22 -0
- package/lib/convert-object-to-array/index.js +41 -0
- package/lib/falsy/index.js +17 -0
- package/lib/index.js +17 -0
- package/lib/merge-properties/index.js +152 -0
- package/lib/object/index.js +15 -0
- package/lib/split-call/index.js +28 -0
- package/lib/split-nested/index.js +54 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) coderaiser
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# @putout/plugin-destructuring [![NPM version][NPMIMGURL]][NPMURL]
|
|
2
|
+
|
|
3
|
+
[NPMIMGURL]: https://img.shields.io/npm/v/@putout/plugin-destructuring.svg?style=flat&longCache=true
|
|
4
|
+
[NPMURL]: https://npmjs.org/package/@putout/plugin-destructuring"npm"
|
|
5
|
+
|
|
6
|
+
> The **destructuring** assignment syntax is a **JavaScript** expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
|
|
7
|
+
>
|
|
8
|
+
> (c) [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
|
|
9
|
+
|
|
10
|
+
π[**Putout**](https://github.com/coderaiser/putout) plugin adds ability to use **destructuring** on variable declarations.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
npm i @putout/plugin-destructuring
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Rules
|
|
19
|
+
|
|
20
|
+
- β
[apply-object](#apply-object);
|
|
21
|
+
- β
[apply-array](#apply-array);
|
|
22
|
+
- β
[remove-useless-object](#remove-useless-object);
|
|
23
|
+
- β
[convert-object-to-array](#convert-object-to-array);
|
|
24
|
+
- β
[split-nested](#split-nested);
|
|
25
|
+
- β
[split-call](#split-call);
|
|
26
|
+
|
|
27
|
+
## Config
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"rules": {
|
|
32
|
+
"destructuring/apply-object": "on",
|
|
33
|
+
"destructuring/apply-array": "on",
|
|
34
|
+
"destructuring/remove-useless-object": "on",
|
|
35
|
+
"destructuring/convert-object-to-array": "on"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## apply-array
|
|
41
|
+
|
|
42
|
+
### β Example of incorrect code
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
const first = array[0];
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## β
Example of correct code
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
const [first] = array;
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## apply-object
|
|
55
|
+
|
|
56
|
+
### β Example of incorrect code
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
const name = user.name;
|
|
60
|
+
|
|
61
|
+
hello = world.hello;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### β
Example of correct code
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
const {name} = user;
|
|
68
|
+
|
|
69
|
+
({hello} = world);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## remove-useless-object
|
|
73
|
+
|
|
74
|
+
Check out in π[**Putout Editor**](https://putout.cloudcmd.io/#/gist/c9ed04b421d75ae39e58038fa6e14630/4c097e3173990ec7e5ebabbe2cedf8e952092ebf).
|
|
75
|
+
|
|
76
|
+
### β Example of incorrect code
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
const {maxElementsInOneLine} = {
|
|
80
|
+
options,
|
|
81
|
+
};
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### β
Example of correct code
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
const {maxElementsInOneLine} = options;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## convert-object-to-array
|
|
91
|
+
|
|
92
|
+
Check out in π[**Putout Editor**](https://putout.cloudcmd.io/#/gist/a1d26daf8bb83ee3ea1c0b62a6ad3afd/cef9b4d27c9dbb0d413a935b0359a6fe9b50364f).
|
|
93
|
+
|
|
94
|
+
### β Example of incorrect code
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
const {0: a, 1: b} = c;
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### β
Example of correct code
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
const [a, b] = c;
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## split-nested
|
|
107
|
+
|
|
108
|
+
> - Don't use nested destructuring on data that comes from any external data sources (such as `REST API`s, `GraphQL` endpoints or files).
|
|
109
|
+
> - Don't use nested destructuring on function arguments that have long or complicated signatures.
|
|
110
|
+
>
|
|
111
|
+
> (c) [Destructuring in JavaScript: the not so good parts](https://goodguydaniel.com/blog/destructuring-not-so-good-parts)
|
|
112
|
+
|
|
113
|
+
π[**Putout**](https://github.com/coderaiser/putout) plugin adds ability to split nested destructuring.
|
|
114
|
+
|
|
115
|
+
### β Example of incorrect code
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
const {
|
|
119
|
+
a: {
|
|
120
|
+
b,
|
|
121
|
+
},
|
|
122
|
+
a: {
|
|
123
|
+
b: x,
|
|
124
|
+
},
|
|
125
|
+
} = c;
|
|
126
|
+
|
|
127
|
+
function f({a}) {
|
|
128
|
+
const {b} = a;
|
|
129
|
+
console.log(b);
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### β
Example of correct code
|
|
134
|
+
|
|
135
|
+
```js
|
|
136
|
+
const {a} = c;
|
|
137
|
+
const {b, b: x} = a;
|
|
138
|
+
|
|
139
|
+
function f({a}) {
|
|
140
|
+
const {b} = a;
|
|
141
|
+
console.log(b);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## split-call
|
|
146
|
+
|
|
147
|
+
### β Example of incorrect code
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
console.log('hello')({uid} = path.scope);
|
|
151
|
+
console.log('hello')[uid] = path.scope;
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### β
Example of correct code
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
console.log('hello');
|
|
158
|
+
({uid} = path.scope);
|
|
159
|
+
|
|
160
|
+
console.log('hello');
|
|
161
|
+
[uid] = path.scope;
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## merge-properties
|
|
165
|
+
|
|
166
|
+
> The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from `arrays`, or `properties` from `objects`, into distinct `variables`.
|
|
167
|
+
>
|
|
168
|
+
> (c) [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
|
|
169
|
+
|
|
170
|
+
Checkout in π[**Putout Editor**](https://putout.cloudcmd.io/#/gist/11c8cfa59f87e46238309b857448b9c5/688f10ad8fd7c0e4d9e9e0c74c399f1edb3ba29e).
|
|
171
|
+
|
|
172
|
+
### β Example of incorrect code
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
const {one} = require('numbers');
|
|
176
|
+
const {two} = require('numbers');
|
|
177
|
+
|
|
178
|
+
({from} = data);
|
|
179
|
+
({to} = data);
|
|
180
|
+
({names} = data);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### β
Example of correct code
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
const {one, two} = require('numbers');
|
|
187
|
+
|
|
188
|
+
({
|
|
189
|
+
from,
|
|
190
|
+
to,
|
|
191
|
+
names,
|
|
192
|
+
} = data);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const report = () => `Use array destructuring`;
|
|
2
|
+
|
|
3
|
+
export const exclude = () => [
|
|
4
|
+
'const __object = __[0]',
|
|
5
|
+
'const __array = __[0]',
|
|
6
|
+
'({__} = __[0])',
|
|
7
|
+
'[__] = __[0]',
|
|
8
|
+
'__a[0] = __b[0]',
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
export const replace = () => ({
|
|
12
|
+
'__a = __b[0]': '[__a] = __b',
|
|
13
|
+
'__a = __b[1]': '[, __a] = __b',
|
|
14
|
+
'const __a = __b[1]': 'const [, __a] = __b',
|
|
15
|
+
'const __a = __b[0]': convertTo('const [__a] = __b'),
|
|
16
|
+
'let __a = __b[0]': convertTo('let [__a] = __b'),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const convertTo = (template) => ({__a}) => {
|
|
20
|
+
delete __a.typeAnnotation;
|
|
21
|
+
return template;
|
|
22
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {types, operator} from 'putout';
|
|
2
|
+
|
|
3
|
+
const {replaceWith} = operator;
|
|
4
|
+
const {
|
|
5
|
+
isObjectProperty,
|
|
6
|
+
arrayPattern,
|
|
7
|
+
} = types;
|
|
8
|
+
|
|
9
|
+
export const report = () => `Use array destructuring instead of object destructuring`;
|
|
10
|
+
|
|
11
|
+
export const fix = (path) => {
|
|
12
|
+
const elements = [];
|
|
13
|
+
|
|
14
|
+
for (const {value} of path.node.properties) {
|
|
15
|
+
elements.push(value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const array = arrayPattern(elements);
|
|
19
|
+
replaceWith(path, array);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const traverse = ({push}) => ({
|
|
23
|
+
ObjectPattern(path) {
|
|
24
|
+
const properties = path.get('properties');
|
|
25
|
+
|
|
26
|
+
if (!properties.length)
|
|
27
|
+
return;
|
|
28
|
+
|
|
29
|
+
for (const [i, prop] of properties.entries()) {
|
|
30
|
+
if (!isObjectProperty(prop))
|
|
31
|
+
return;
|
|
32
|
+
|
|
33
|
+
const {key} = prop.node;
|
|
34
|
+
|
|
35
|
+
if (i !== key.value)
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
push(path);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const FIRST_PROPERTY = 'declarations.0.id.properties.0';
|
|
2
|
+
|
|
3
|
+
export const report = (path) => {
|
|
4
|
+
const {name} = path.get(`${FIRST_PROPERTY}.key`).node;
|
|
5
|
+
return `Use destructuring instead of setting '${name}' to 'undefined'`;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const match = () => ({
|
|
9
|
+
'const {__a} = {__b}': (vars, path) => {
|
|
10
|
+
const prop = path.get(FIRST_PROPERTY);
|
|
11
|
+
return !prop.node.computed;
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const replace = () => ({
|
|
16
|
+
'const {__a} = {__b}': 'const {__a} = __b',
|
|
17
|
+
});
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as convertObjectToArray from './convert-object-to-array/index.js';
|
|
2
|
+
import * as object from './object/index.js';
|
|
3
|
+
import * as array from './array/index.js';
|
|
4
|
+
import * as falsy from './falsy/index.js';
|
|
5
|
+
import * as splitNested from './split-nested/index.js';
|
|
6
|
+
import * as splitCall from './split-call/index.js';
|
|
7
|
+
import * as mergeProperties from './merge-properties/index.js';
|
|
8
|
+
|
|
9
|
+
export const rules = {
|
|
10
|
+
'apply-object': object,
|
|
11
|
+
'apply-array': array,
|
|
12
|
+
'remove-useless-object': falsy,
|
|
13
|
+
'convert-object-to-array': convertObjectToArray,
|
|
14
|
+
'split-nested': splitNested,
|
|
15
|
+
'split-call': splitCall,
|
|
16
|
+
'merge-properties': mergeProperties,
|
|
17
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import {types, operator} from 'putout';
|
|
2
|
+
|
|
3
|
+
const {remove, compare} = operator;
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
isObjectPattern,
|
|
7
|
+
isRestElement,
|
|
8
|
+
isAssignmentExpression,
|
|
9
|
+
isVariableDeclaration,
|
|
10
|
+
isExpressionStatement,
|
|
11
|
+
} = types;
|
|
12
|
+
|
|
13
|
+
const notEmptyPlaces = (a) => a.places.length;
|
|
14
|
+
|
|
15
|
+
const LEFT = {
|
|
16
|
+
VariableDeclarator: 'id',
|
|
17
|
+
AssignmentExpression: 'left',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const RIGHT = {
|
|
21
|
+
VariableDeclarator: 'init',
|
|
22
|
+
AssignmentExpression: 'right',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const report = () => 'Merge object properties when destructuring';
|
|
26
|
+
|
|
27
|
+
export const fix = ({path, places}) => {
|
|
28
|
+
merge(path, places);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const traverse = ({push, store}) => {
|
|
32
|
+
const add = addVariable({
|
|
33
|
+
store,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
'VariableDeclarator|AssignmentExpression'(path) {
|
|
38
|
+
const {left, right} = split(path);
|
|
39
|
+
|
|
40
|
+
if (!right)
|
|
41
|
+
return;
|
|
42
|
+
|
|
43
|
+
if (!isObjectPattern(left))
|
|
44
|
+
return;
|
|
45
|
+
|
|
46
|
+
for (const property of left.properties) {
|
|
47
|
+
if (isRestElement(property))
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
add(path, right);
|
|
52
|
+
},
|
|
53
|
+
Program: {
|
|
54
|
+
exit() {
|
|
55
|
+
store()
|
|
56
|
+
.filter(notEmptyPlaces)
|
|
57
|
+
.filter(checkPlaces)
|
|
58
|
+
.map(push);
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function checkPlaces({places}) {
|
|
65
|
+
return places.filter(hasParentNode).length;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const hasParentNode = ({parentPath}) => {
|
|
69
|
+
if (!parentPath.node)
|
|
70
|
+
return false;
|
|
71
|
+
|
|
72
|
+
return isVariableDeclaration(parentPath) || isExpressionStatement(parentPath);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const createUID = (path) => {
|
|
76
|
+
const {uid} = path.scope;
|
|
77
|
+
const {type} = path;
|
|
78
|
+
const name = RIGHT[type];
|
|
79
|
+
|
|
80
|
+
const str = `${uid}-${path.get(name).toString()}`;
|
|
81
|
+
|
|
82
|
+
return str.replace(/['"`]/g, '*');
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const addVariable = ({store}) => (path, node) => {
|
|
86
|
+
const str = createUID(path);
|
|
87
|
+
const currentVar = store(str);
|
|
88
|
+
|
|
89
|
+
if (!currentVar) {
|
|
90
|
+
store(str, {
|
|
91
|
+
path,
|
|
92
|
+
places: [],
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const currentPath = currentVar.path;
|
|
99
|
+
|
|
100
|
+
if (path === currentPath)
|
|
101
|
+
return;
|
|
102
|
+
|
|
103
|
+
const {parentPath, type} = currentPath;
|
|
104
|
+
|
|
105
|
+
if (currentPath.removed || !currentPath.node)
|
|
106
|
+
return;
|
|
107
|
+
|
|
108
|
+
if (parentPath.removed || !parentPath.node)
|
|
109
|
+
return;
|
|
110
|
+
|
|
111
|
+
const name = RIGHT[type];
|
|
112
|
+
|
|
113
|
+
if (isAssignmentExpression(currentPath) && compare(currentPath.node[name], node))
|
|
114
|
+
return currentVar.places.push(path);
|
|
115
|
+
|
|
116
|
+
if (sameKind(path, currentPath))
|
|
117
|
+
return currentVar.places.push(path);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
function sameKind(path1, path2) {
|
|
121
|
+
const kind1 = path1.parentPath.node.kind;
|
|
122
|
+
const kind2 = path2.parentPath.node.kind;
|
|
123
|
+
|
|
124
|
+
return kind1 === kind2;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function split(path) {
|
|
128
|
+
const {type} = path;
|
|
129
|
+
const leftName = LEFT[type];
|
|
130
|
+
const rightName = RIGHT[type];
|
|
131
|
+
const left = path.node[leftName];
|
|
132
|
+
const right = path.node[rightName];
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
left,
|
|
136
|
+
right,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function merge(path, places) {
|
|
141
|
+
const {node, type} = path;
|
|
142
|
+
const name = LEFT[type];
|
|
143
|
+
|
|
144
|
+
for (const place of places) {
|
|
145
|
+
node[name].properties = [
|
|
146
|
+
...node[name].properties,
|
|
147
|
+
...place.node[name].properties,
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
remove(place);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {types} from 'putout';
|
|
2
|
+
|
|
3
|
+
const {isExpressionStatement} = types;
|
|
4
|
+
|
|
5
|
+
export const report = () => 'Use object destructuring';
|
|
6
|
+
|
|
7
|
+
export const match = () => ({
|
|
8
|
+
'__a = __b.__a': (vars, {parentPath}) => isExpressionStatement(parentPath),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const replace = () => ({
|
|
12
|
+
'const __a = __b.__a': 'const {__a} = __b',
|
|
13
|
+
'let __a = __b.__a': 'let {__a} = __b',
|
|
14
|
+
'__a = __b.__a': '({__a} = __b)',
|
|
15
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {types} from 'putout';
|
|
2
|
+
|
|
3
|
+
const {isIdentifier} = types;
|
|
4
|
+
|
|
5
|
+
export const report = () => `Split call with destructuring`;
|
|
6
|
+
|
|
7
|
+
export const replace = () => ({
|
|
8
|
+
'__a(__args)({__c} = __d)': `{
|
|
9
|
+
__a(__args);
|
|
10
|
+
({__c} = __d);
|
|
11
|
+
}`,
|
|
12
|
+
'__a(__args)[__c] = __d': ({__c}) => {
|
|
13
|
+
if (isIdentifier(__c))
|
|
14
|
+
return `{
|
|
15
|
+
__a(__args);
|
|
16
|
+
[__c] = __d;
|
|
17
|
+
}`;
|
|
18
|
+
|
|
19
|
+
__c.elements = __c.expressions;
|
|
20
|
+
__c.type = 'ArrayPattern';
|
|
21
|
+
delete __c.expressions;
|
|
22
|
+
|
|
23
|
+
return `{
|
|
24
|
+
__a(__args);
|
|
25
|
+
__c = __d;
|
|
26
|
+
}`;
|
|
27
|
+
},
|
|
28
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {types, template} from 'putout';
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
objectProperty,
|
|
5
|
+
isObjectPattern,
|
|
6
|
+
objectPattern,
|
|
7
|
+
} = types;
|
|
8
|
+
|
|
9
|
+
const buildDeclaration = template(`
|
|
10
|
+
const %%__b%% = %%__a%%
|
|
11
|
+
`);
|
|
12
|
+
|
|
13
|
+
export const report = () => 'Avoid nested destructuring';
|
|
14
|
+
|
|
15
|
+
export const match = () => ({
|
|
16
|
+
'const {__a: {__b}} = __c': matchConst,
|
|
17
|
+
'const {__a: {__b: __c}} = __d': matchConst,
|
|
18
|
+
'const {__a: {__b = __c}} = __d': matchConst,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const replace = () => ({
|
|
22
|
+
'const {__a: {__b}} = __c': 'const {__a} = __c, {__b} = __a',
|
|
23
|
+
'const {__a: {__b: __c}} = __d': 'const {__a} = __d, {__b: __c} = __a',
|
|
24
|
+
'const {__a: {__b = __c}} = __d': 'const {__a} = __d, {__b = __c} = __a',
|
|
25
|
+
'function f({ __a: { __b } }) {}': replaceArg,
|
|
26
|
+
'function f({ __a: { __b: __c } }) {}': replaceArg,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
function matchConst({__a, __c}, path) {
|
|
30
|
+
const bindings = path.scope.getAllBindings();
|
|
31
|
+
|
|
32
|
+
if (bindings[__a.name])
|
|
33
|
+
return false;
|
|
34
|
+
|
|
35
|
+
return !isObjectPattern(__c);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function replaceArg({__a, __b, __c}, path) {
|
|
39
|
+
const {properties} = path.node.params[0];
|
|
40
|
+
const [first] = properties;
|
|
41
|
+
|
|
42
|
+
first.value = first.key;
|
|
43
|
+
|
|
44
|
+
const declaration = buildDeclaration({
|
|
45
|
+
__a,
|
|
46
|
+
__b: objectPattern([
|
|
47
|
+
objectProperty(__b, __c || __b),
|
|
48
|
+
]),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
path.node.body.body.unshift(declaration);
|
|
52
|
+
|
|
53
|
+
return path;
|
|
54
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@putout/plugin-destructuring",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
|
|
6
|
+
"description": "πPutout plugin adds ability to transform destructuring",
|
|
7
|
+
"homepage": "https://github.com/coderaiser/putout/tree/master/packages/plugin-destructuring#readme",
|
|
8
|
+
"main": "lib/index.js",
|
|
9
|
+
"release": false,
|
|
10
|
+
"tag": false,
|
|
11
|
+
"changelog": false,
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/coderaiser/putout.git"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "madrun test",
|
|
18
|
+
"watch:test": "madrun watch:test",
|
|
19
|
+
"lint": "madrun lint",
|
|
20
|
+
"fresh:lint": "madrun fresh:lint",
|
|
21
|
+
"lint:fresh": "madrun lint:fresh",
|
|
22
|
+
"fix:lint": "madrun fix:lint",
|
|
23
|
+
"coverage": "madrun coverage",
|
|
24
|
+
"report": "madrun report"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"putout",
|
|
29
|
+
"putout-plugin",
|
|
30
|
+
"plugin",
|
|
31
|
+
"destructuring"
|
|
32
|
+
],
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@putout/plugin-declare": "*",
|
|
35
|
+
"@putout/plugin-declare-before-reference": "*",
|
|
36
|
+
"@putout/plugin-esm": "*",
|
|
37
|
+
"@putout/plugin-minify": "*",
|
|
38
|
+
"@putout/plugin-nodejs": "*",
|
|
39
|
+
"@putout/plugin-printer": "*",
|
|
40
|
+
"@putout/plugin-putout": "*",
|
|
41
|
+
"@putout/plugin-tape": "*",
|
|
42
|
+
"@putout/test": "^14.0.0",
|
|
43
|
+
"c8": "^10.0.0",
|
|
44
|
+
"eslint": "v10.0.0-alpha.0",
|
|
45
|
+
"eslint-plugin-n": "^17.0.0",
|
|
46
|
+
"eslint-plugin-putout": "^29.0.0",
|
|
47
|
+
"madrun": "^11.0.0",
|
|
48
|
+
"nodemon": "^3.0.1"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"putout": ">=41"
|
|
52
|
+
},
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=20"
|
|
56
|
+
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
}
|
|
60
|
+
}
|