@putout/plugin-putout 23.5.0 → 23.7.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
@@ -29,6 +29,7 @@ npm i @putout/plugin-putout -D
29
29
  - ✅ [apply-insert-after](#apply-insert-after);
30
30
  - ✅ [apply-insert-before](#apply-insert-before);
31
31
  - ✅ [apply-vars](#apply-vars);
32
+ - ✅ [apply-lowercase-to-node-builders](#apply-lowercase-to-node-builders);
32
33
  - ✅ [apply-namespace-specifier](#apply-namespace-specifier);
33
34
  - ✅ [apply-processors-destructuring](#apply-processors-destructuring);
34
35
  - ✅ [apply-remove](#apply-remove);
@@ -36,6 +37,7 @@ npm i @putout/plugin-putout -D
36
37
  - ✅ [apply-parens](#apply-parens);
37
38
  - ✅ [apply-short-processors](#apply-short-processors);
38
39
  - ✅ [check-match](#check-match);
40
+ - ✅ [check-declare](#check-declare);
39
41
  - ✅ [check-replace-code](#check-replace-code);
40
42
  - ✅ [convert-add-argument-to-add-args](#convert-add-argument-to-add-test-args);
41
43
  - ✅ [convert-babel-types](#convert-babel-types);
@@ -99,10 +101,12 @@ npm i @putout/plugin-putout -D
99
101
  "putout/apply-insert-after": "on",
100
102
  "putout/apply-vars": "on",
101
103
  "putout/apply-short-processors": "on",
104
+ "putout/apply-lowercase-to-node-builders": "on",
102
105
  "putout/apply-namespace-specifier": "on",
103
106
  "putout/apply-for-of-to-track-file": "on",
104
107
  "putout/apply-fixture-name-to-message": "on",
105
108
  "putout/check-match": "on",
109
+ "putout/check-declare": "on",
106
110
  "putout/check-replace-code": ["on", {
107
111
  "once": true
108
112
  }],
@@ -144,6 +148,22 @@ npm i @putout/plugin-putout -D
144
148
  }
145
149
  ```
146
150
 
151
+ ## apply-lowercase-to-node-builders
152
+
153
+ Checkout in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/fe78f6e48998fb39fa7e53e4046f1fc0/e1e6f2387895ff2ab98b4a9bcd2e8d565f7c3f16).
154
+
155
+ ### ❌ Example of incorrect code
156
+
157
+ ```js
158
+ path.node = Identifier('x');
159
+ ```
160
+
161
+ ### ✅ Example of correct code
162
+
163
+ ```js
164
+ path.node = identifier('x');
165
+ ```
166
+
147
167
  ## apply-processors-destructuring
148
168
 
149
169
  ### ❌ Example of incorrect code
@@ -845,6 +865,23 @@ module.exports.match = () => ({
845
865
  });
846
866
  ```
847
867
 
868
+ ## check-declare
869
+
870
+ Checks that [Declarator](https://github.com/coderaiser/putout/tree/master/packages/engine-runner#declarator) transform is possible.
871
+ Checkout in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/9fccb187bb8933afff0dc0db57b3cea8/25cb812978fadb4efb5f0cb44058a61f70f8b78e):
872
+
873
+ ### ❌ Example of incorrect code
874
+
875
+ ```js
876
+ module.exports.declare = () => ({
877
+ isNumber: 'const isNumber = () => {}',
878
+ isString: 'const isNumber = () => {}',
879
+ });
880
+ ```
881
+
882
+ ☝️ *There is no `fix` for this rule, it used internally to be more confident about `test coverage`, because of declaration form, transforms cannon be checked by `nyc` and `c8`, and uncovered lines can find unfixable false positives when running on code.
883
+ This is additional tests, if you forget to test some case (from a big list of rules that is supported) it will be checked with this `rule` and make transforms more stable.*
884
+
848
885
  ## check-replace-code
849
886
 
850
887
  Checks that [Replacer](https://github.com/coderaiser/putout/tree/master/packages/engine-runner#replacer) transform is possible.
@@ -2,9 +2,9 @@
2
2
 
3
3
  const {types, operator} = require('putout');
4
4
  const {
5
- Identifier,
6
- ObjectPattern,
7
- ObjectProperty,
5
+ objectProperty,
6
+ objectPattern,
7
+ identifier,
8
8
  } = types;
9
9
 
10
10
  const {remove, compare} = operator;
@@ -40,11 +40,11 @@ function addAwait(vars, path) {
40
40
  const [first] = params;
41
41
 
42
42
  if (first.name === 't') {
43
- const id = Identifier('progress');
43
+ const id = identifier('progress');
44
44
 
45
45
  path.scope.block.params = [
46
- ObjectPattern([
47
- ObjectProperty(id, id, false, true),
46
+ objectPattern([
47
+ objectProperty(id, id, false, true),
48
48
  ]),
49
49
  ];
50
50
  }
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  const {types} = require('putout');
4
- const {Identifier} = types;
4
+ const {identifier} = types;
5
5
 
6
6
  module.exports.report = () => `Add 'path' argument to 'traverse' visitors`;
7
7
 
8
8
  const TRAVERSE = '(__args) => __object';
9
9
 
10
10
  module.exports.fix = (path) => {
11
- path.node.params.push(Identifier('path'));
11
+ path.node.params.push(identifier('path'));
12
12
  };
13
13
 
14
14
  module.exports.traverse = ({push}) => ({
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  const {types, operator} = require('putout');
4
- const {traverse} = operator;
5
-
6
4
  const {
7
- ObjectProperty,
8
- ObjectPattern,
9
- Identifier,
5
+ objectPattern,
6
+ objectProperty,
7
+ identifier,
10
8
  } = types;
11
9
 
10
+ const {traverse} = operator;
11
+
12
12
  const defaultNames = [
13
13
  'push',
14
14
  'store',
@@ -21,11 +21,11 @@ module.exports.report = ({name}) => `Add '${name}' argument to 'traverse'`;
21
21
  module.exports.fix = ({name, fn}) => {
22
22
  const computed = false;
23
23
  const shorthand = true;
24
- const id = Identifier(name);
25
- const property = ObjectProperty(id, id, computed, shorthand);
24
+ const id = identifier(name);
25
+ const property = objectProperty(id, id, computed, shorthand);
26
26
 
27
27
  if (!fn.params.length) {
28
- fn.params.push(ObjectPattern([property]));
28
+ fn.params.push(objectPattern([property]));
29
29
  return;
30
30
  }
31
31
 
@@ -1,16 +1,15 @@
1
1
  'use strict';
2
2
 
3
3
  const {operator, types} = require('putout');
4
+ const {
5
+ objectProperty,
6
+ objectPattern,
7
+ identifier,
8
+ } = types;
4
9
 
5
10
  const computed = true;
6
11
  const shorthand = true;
7
12
 
8
- const {
9
- Identifier,
10
- ObjectPattern,
11
- ObjectProperty,
12
- } = types;
13
-
14
13
  const {compare} = operator;
15
14
 
16
15
  module.exports.report = () => 'Use Async API to test Formatter';
@@ -25,13 +24,13 @@ const create = (name) => (vars, path) => {
25
24
  const {block} = path.scope;
26
25
  const {body} = block.body;
27
26
  const n = body.length - 1;
28
- const nameId = Identifier(name);
27
+ const nameId = identifier(name);
29
28
 
30
29
  block.async = true;
31
30
 
32
31
  block.params = [
33
- ObjectPattern([
34
- ObjectProperty(nameId, nameId, !computed, shorthand),
32
+ objectPattern([
33
+ objectProperty(nameId, nameId, !computed, shorthand),
35
34
  ]),
36
35
  ];
37
36
 
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ const {types} = require('putout');
4
+ const {isIdentifier} = types;
5
+
6
+ module.exports.report = () => `Use lowercased node builders`;
7
+
8
+ module.exports.fix = (path) => {
9
+ const [first] = path.node.name;
10
+ const other = path.node.name.slice(1);
11
+
12
+ path.node.name = first.toLowerCase() + other;
13
+ };
14
+
15
+ module.exports.traverse = ({push}) => ({
16
+ CallExpression(path) {
17
+ const calleePath = path.get('callee');
18
+
19
+ if (!isIdentifier(calleePath))
20
+ return;
21
+
22
+ const {name} = calleePath.node;
23
+ const [first, second] = name;
24
+
25
+ if (!/[A-Z]/.test(first))
26
+ return;
27
+
28
+ if (!/[a-z]/.test(second))
29
+ return;
30
+
31
+ if (!types[name])
32
+ return;
33
+
34
+ push(calleePath);
35
+ },
36
+ });
@@ -3,7 +3,7 @@
3
3
  const {types, operator} = require('putout');
4
4
 
5
5
  const {compute, rename} = operator;
6
- const {Identifier} = types;
6
+ const {identifier} = types;
7
7
 
8
8
  const isString = (a) => typeof a === 'string';
9
9
  const chooseType = (a) => a === '__ignore' ? '__array' : '__object';
@@ -22,7 +22,7 @@ module.exports.report = ({value}) => {
22
22
  module.exports.fix = ({path, value}) => {
23
23
  const name = getShortName(value);
24
24
 
25
- path.node.key = Identifier(name);
25
+ path.node.key = identifier(name);
26
26
  path.node.computed = true;
27
27
  rename(path.get('value'), '__a', chooseType(name));
28
28
  };
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ const tryCatch = require('try-catch');
4
+ const putout = require('putout');
5
+
6
+ const {types, operator} = putout;
7
+
8
+ const noop = () => {};
9
+ const {getTemplateValues} = operator;
10
+
11
+ const DECLARE_ESM = 'export const declare = () => __object';
12
+ const DECLARE_COMMONJS = 'module.exports.declare = () => __object';
13
+ const COMMONJS = 'module.exports = __object';
14
+
15
+ const {
16
+ isTemplateLiteral,
17
+ isStringLiteral,
18
+ } = types;
19
+
20
+ module.exports.report = ({message}) => message;
21
+
22
+ module.exports.fix = noop;
23
+ module.exports.traverse = ({push}) => ({
24
+ [DECLARE_ESM]: createCheck(push, DECLARE_ESM),
25
+ [DECLARE_COMMONJS]: createCheck(push, DECLARE_COMMONJS),
26
+ [COMMONJS]: createCheck(push, COMMONJS),
27
+ });
28
+
29
+ const createCheck = (push, template) => (path) => {
30
+ const {__object} = getTemplateValues(path, template);
31
+
32
+ const lines = [];
33
+
34
+ for (const {value} of __object.properties) {
35
+ let current = '';
36
+
37
+ if (isStringLiteral(value)) {
38
+ current = value.value;
39
+ } else if (isTemplateLiteral(value)) {
40
+ if (value.quasis.length > 1)
41
+ continue;
42
+
43
+ current = value.quasis[0].value.cooked;
44
+ }
45
+
46
+ if (/^(const|import)/.test(current))
47
+ lines.push(current);
48
+ }
49
+
50
+ const source = lines.join(';\n');
51
+ const [error] = tryCatch(putout.parse, source);
52
+
53
+ if (!error)
54
+ return;
55
+
56
+ const {message} = error;
57
+
58
+ push({
59
+ path,
60
+ message,
61
+ });
62
+ };
@@ -2,12 +2,12 @@
2
2
 
3
3
  const {operator, types} = require('putout');
4
4
  const {
5
- ObjectPattern,
6
- BlockStatement,
7
- Identifier,
8
- ArrayPattern,
9
- ArrayExpression,
10
- ObjectExpression,
5
+ objectPattern,
6
+ objectExpression,
7
+ blockStatement,
8
+ identifier,
9
+ arrayExpression,
10
+ arrayPattern,
11
11
  } = types;
12
12
 
13
13
  const {replaceWith} = operator;
@@ -48,16 +48,16 @@ module.exports.fix = (path, {options}) => {
48
48
 
49
49
  if (name === '__array') {
50
50
  if (path.parentPath.isCallExpression())
51
- return replaceWith(path, ArrayPattern([]));
51
+ return replaceWith(path, arrayPattern([]));
52
52
 
53
53
  if (path.parentPath.isFunction())
54
- return replaceWith(path, ArrayPattern([]));
54
+ return replaceWith(path, arrayPattern([]));
55
55
 
56
56
  if (path.parentPath.isAssignmentExpression())
57
- return replaceWith(path, ArrayExpression([]));
57
+ return replaceWith(path, arrayExpression([]));
58
58
 
59
59
  if (path.parentPath.isVariableDeclarator())
60
- return replaceWith(path, ArrayExpression([]));
60
+ return replaceWith(path, arrayExpression([]));
61
61
  }
62
62
 
63
63
  if (name === '__object')
@@ -65,14 +65,14 @@ module.exports.fix = (path, {options}) => {
65
65
 
66
66
  if (name === '__body') {
67
67
  if (path.parentPath.isClassProperty()) {
68
- const key = Identifier(getVar());
68
+ const key = identifier(getVar());
69
69
 
70
70
  replaceWith(path, key);
71
71
 
72
72
  return;
73
73
  }
74
74
 
75
- replaceWith(path, BlockStatement([]));
75
+ replaceWith(path, blockStatement([]));
76
76
  }
77
77
  };
78
78
 
@@ -82,14 +82,14 @@ function objectify(path) {
82
82
  const isVar = parentPath.isVariableDeclarator();
83
83
 
84
84
  if (path.parentPath.isExportDeclaration())
85
- return replaceWith(path, ObjectExpression([]));
85
+ return replaceWith(path, objectExpression([]));
86
86
 
87
87
  if (path.parentPath.isCallExpression())
88
- return replaceWith(path, ObjectExpression([]));
88
+ return replaceWith(path, objectExpression([]));
89
89
 
90
90
  if (isAssign && parentPath.get('right') === path)
91
- return replaceWith(path, ObjectExpression([]));
91
+ return replaceWith(path, objectExpression([]));
92
92
 
93
93
  if (isVar && parentPath.get('id') === path)
94
- return replaceWith(path, ObjectPattern([]));
94
+ return replaceWith(path, objectPattern([]));
95
95
  }
@@ -5,9 +5,9 @@ const {types, operator} = require('putout');
5
5
  const {replaceWith} = operator;
6
6
 
7
7
  const {
8
- ReturnStatement,
9
8
  isCallExpression,
10
9
  isIdentifier,
10
+ returnStatement,
11
11
  } = types;
12
12
 
13
13
  const {entries} = Object;
@@ -29,7 +29,7 @@ module.exports.fix = fixType({
29
29
  path.node.params = [path.node.params[1]];
30
30
  },
31
31
  isCallExpression: (path) => {
32
- replaceWith(path, ReturnStatement(path.node.arguments[1]));
32
+ replaceWith(path, returnStatement(path.node.arguments[1]));
33
33
  },
34
34
  });
35
35
 
@@ -1,12 +1,19 @@
1
1
  'use strict';
2
2
 
3
- const camel = require('just-camel-case');
4
3
  const {
5
4
  types,
6
5
  operator,
7
6
  template,
8
7
  } = require('putout');
9
8
 
9
+ const camel = require('just-camel-case');
10
+ const {
11
+ stringLiteral,
12
+ arrayExpression,
13
+ objectProperty,
14
+ identifier,
15
+ } = types;
16
+
10
17
  const {
11
18
  replaceWith,
12
19
  insertBefore,
@@ -14,13 +21,6 @@ const {
14
21
  getPathAfterRequires,
15
22
  } = operator;
16
23
 
17
- const {
18
- ObjectProperty,
19
- Identifier,
20
- StringLiteral,
21
- ArrayExpression,
22
- } = types;
23
-
24
24
  module.exports.report = () => `Use top-level 'require()' instead of '...getRule()'`;
25
25
 
26
26
  const REQUIRE = `const __a = require(__b)`;
@@ -36,8 +36,8 @@ module.exports.match = () => ({
36
36
  module.exports.replace = () => ({
37
37
  'getRule(__a)': ({__a}, path) => {
38
38
  const name = camel(__a.value);
39
- const id = Identifier(name);
40
- const node = ObjectProperty(__a, id);
39
+ const id = identifier(name);
40
+ const node = objectProperty(__a, id);
41
41
 
42
42
  replaceWith(path.parentPath, node);
43
43
 
@@ -51,8 +51,8 @@ module.exports.replace = () => ({
51
51
  },
52
52
  'getRule(__a, __b)': ({__a, __b}, path) => {
53
53
  const name = camel(__a.value);
54
- const id = Identifier(name);
55
- const node = ObjectProperty(__a, ArrayExpression([__b, id]));
54
+ const id = identifier(name);
55
+ const node = objectProperty(__a, arrayExpression([__b, id]));
56
56
 
57
57
  replaceWith(path.parentPath, node);
58
58
 
@@ -73,7 +73,7 @@ function addRequire({__a, id, path}) {
73
73
 
74
74
  const nodeRequire = createRequire({
75
75
  __a: id,
76
- __b: StringLiteral(`./${__a.value}`),
76
+ __b: stringLiteral(`./${__a.value}`),
77
77
  });
78
78
 
79
79
  if (compare(first, REQUIRE)) {
@@ -3,7 +3,7 @@
3
3
  const {types, operator} = require('putout');
4
4
 
5
5
  const {replaceWith} = operator;
6
- const {ObjectProperty} = types;
6
+ const {objectProperty} = types;
7
7
 
8
8
  module.exports.report = () => 'Object Property should be used instead of Method';
9
9
 
@@ -29,5 +29,5 @@ module.exports.fix = (path) => {
29
29
  path.node.type = 'ArrowFunctionExpression';
30
30
  path.node.id = null;
31
31
 
32
- replaceWith(path, ObjectProperty(keyPath.node, path.node));
32
+ replaceWith(path, objectProperty(keyPath.node, path.node));
33
33
  };
@@ -7,8 +7,8 @@ const {
7
7
  } = require('putout');
8
8
 
9
9
  const fullstore = require('fullstore');
10
+ const {objectProperty, identifier} = types;
10
11
 
11
- const {Identifier, ObjectProperty} = types;
12
12
  const {
13
13
  replaceWith,
14
14
  insertAfter,
@@ -47,10 +47,10 @@ module.exports.fix = ({path, calleePath, property, object, program, isInserted})
47
47
  return;
48
48
  }
49
49
 
50
- const id = Identifier('replaceWith');
50
+ const id = identifier('replaceWith');
51
51
  const varPath = getVarPath(bindings);
52
52
 
53
- varPath.node.id.properties.unshift(ObjectProperty(id, id, false, true));
53
+ varPath.node.id.properties.unshift(objectProperty(id, id, false, true));
54
54
  };
55
55
 
56
56
  function getVarPath(bindings) {
@@ -6,10 +6,9 @@ const {
6
6
  types,
7
7
  } = require('putout');
8
8
 
9
+ const {objectProperty, identifier} = types;
9
10
  const {replaceWith, insertBefore} = operator;
10
11
 
11
- const {Identifier, ObjectProperty} = types;
12
-
13
12
  module.exports.report = () => {
14
13
  return `"operate.replaceWithMultiple" should be called instead of "path.replaceWithMultiple"`;
15
14
  };
@@ -31,10 +30,10 @@ module.exports.fix = ({path, calleePath, property, object, program}) => {
31
30
  if (!bindings.replaceWith && !bindings.insertAfter)
32
31
  return insertBefore(first, replaceWithAST);
33
32
 
34
- const id = Identifier('replaceWithMultiple');
33
+ const id = identifier('replaceWithMultiple');
35
34
  const varPath = getVarPath(bindings);
36
35
 
37
- varPath.node.id.properties.push(ObjectProperty(id, id, false, true));
36
+ varPath.node.id.properties.push(objectProperty(id, id, false, true));
38
37
  };
39
38
 
40
39
  function getVarPath(bindings) {
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const {isIdentifier, Identifier} = require('putout').types;
3
+ const {types} = require('putout');
4
+ const {isIdentifier, identifier} = types;
4
5
 
5
6
  module.exports.report = () => {
6
7
  return `"noTransformCode" should be called instead of using same arguments twice in "transformCode"`;
@@ -34,6 +35,6 @@ module.exports.traverse = ({push}) => ({
34
35
  });
35
36
 
36
37
  module.exports.fix = ({path, calleePath}) => {
37
- calleePath.node.property = Identifier('noTransformCode');
38
+ calleePath.node.property = identifier('noTransformCode');
38
39
  path.node.arguments.pop();
39
40
  };
@@ -6,7 +6,7 @@ const {
6
6
  operator,
7
7
  } = require('putout');
8
8
 
9
- const {StringLiteral} = types;
9
+ const {stringLiteral} = types;
10
10
  const {compare, remove} = operator;
11
11
 
12
12
  const isPush = (path) => path.get('value').isIdentifier({
@@ -43,7 +43,7 @@ module.exports.replace = () => ({
43
43
  const name = getName(propertyPath);
44
44
 
45
45
  if (isPush(propertyPath) || isBlock(propertyPath)) {
46
- node.right.body.elements.push(StringLiteral(name));
46
+ node.right.body.elements.push(stringLiteral(name));
47
47
  remove(propertyPath);
48
48
  }
49
49
  }
@@ -11,11 +11,11 @@ const {
11
11
  } = operator;
12
12
 
13
13
  const {
14
- Identifier,
15
14
  isReturnStatement,
16
15
  isObjectMethod,
17
16
  isObjectProperty,
18
17
  isObjectExpression,
18
+ identifier,
19
19
  } = types;
20
20
 
21
21
  module.exports.report = () => `Use Scanner instead of Traverser`;
@@ -23,7 +23,7 @@ module.exports.report = () => `Use Scanner instead of Traverser`;
23
23
  module.exports.fix = ({path, pathProperty}) => {
24
24
  if (path.isObjectMethod()) {
25
25
  replaceWith(path.parentPath, path.get('body'));
26
- path.parentPath.parentPath.node.params.unshift(Identifier('path'));
26
+ path.parentPath.parentPath.node.params.unshift(identifier('path'));
27
27
 
28
28
  path.parentPath.parentPath.parentPath.node.left.property.name = 'scan';
29
29
  return;
@@ -31,7 +31,7 @@ module.exports.fix = ({path, pathProperty}) => {
31
31
 
32
32
  if (path.isObjectProperty()) {
33
33
  replaceWith(path.parentPath, path.get('value.body'));
34
- path.parentPath.parentPath.node.params.unshift(Identifier('path'));
34
+ path.parentPath.parentPath.node.params.unshift(identifier('path'));
35
35
 
36
36
  const assignmentPath = path.parentPath.parentPath.parentPath;
37
37
 
@@ -1,14 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const {operator, types} = require('putout');
4
-
5
4
  const {
6
- StringLiteral,
7
- ArrayExpression,
8
- Identifier,
9
- ObjectProperty,
10
- ObjectExpression,
5
+ arrayExpression,
6
+ objectExpression,
7
+ stringLiteral,
8
+ identifier,
11
9
  isIdentifier,
10
+ objectProperty,
12
11
  } = types;
13
12
 
14
13
  const {replaceWith, getProperty} = operator;
@@ -30,7 +29,7 @@ module.exports.fix = (path, {options}) => {
30
29
  if (getProperty(objectPath, name))
31
30
  continue;
32
31
 
33
- const property = ObjectProperty(Identifier(name), StringLiteral(value));
32
+ const property = objectProperty(identifier(name), stringLiteral(value));
34
33
  objectPath.node.properties.unshift(property);
35
34
  }
36
35
  };
@@ -51,7 +50,7 @@ module.exports.filter = (path, {options}) => {
51
50
 
52
51
  const maybeLiteral = (a) => {
53
52
  if (isIdentifier(a))
54
- return StringLiteral(a.name);
53
+ return stringLiteral(a.name);
55
54
 
56
55
  return a;
57
56
  };
@@ -59,9 +58,9 @@ const maybeLiteral = (a) => {
59
58
  function convert(objectPath) {
60
59
  const {key, value} = objectPath.node.properties[0];
61
60
 
62
- replaceWith(objectPath, ObjectExpression([
63
- ObjectProperty(Identifier('plugins'), ArrayExpression([
64
- ArrayExpression([
61
+ replaceWith(objectPath, objectExpression([
62
+ objectProperty(identifier('plugins'), arrayExpression([
63
+ arrayExpression([
65
64
  maybeLiteral(key),
66
65
  value,
67
66
  ]),