Skip to content

Commit fcfdec0

Browse files
committed
Breaking: Support ESM rules
1 parent 30bb8e2 commit fcfdec0

13 files changed

+345
-8
lines changed

lib/rules/prefer-object-rule.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ module.exports = {
4646
// note - we intentionally don't worry about formatting here, as otherwise we have
4747
// to indent the function correctly
4848

49-
if (ruleInfo.create.type === 'FunctionExpression') {
49+
if (ruleInfo.create.type === 'FunctionExpression' || ruleInfo.create.type === 'FunctionDeclaration') {
5050
const openParenToken = sourceCode.getFirstToken(
5151
ruleInfo.create,
5252
token => token.type === 'Punctuator' && token.value === '('

lib/utils.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,28 @@ module.exports = {
9898
let exportsVarOverridden = false;
9999
let exportsIsFunction = false;
100100

101-
const exportNodes = ast.body
101+
// ESM
102+
const exportNodesESM = ast.body
103+
.filter(statement => statement.type === 'ExportDefaultDeclaration')
104+
.map(statement => statement.declaration)
105+
.reduce((currentExports, node) => {
106+
if (node.type === 'ObjectExpression') {
107+
return node.properties.reduce((parsedProps, prop) => {
108+
const keyValue = module.exports.getKeyName(prop);
109+
if (INTERESTING_KEYS.has(keyValue)) {
110+
parsedProps[keyValue] = prop.value;
111+
}
112+
return parsedProps;
113+
}, {});
114+
} else if (isNormalFunctionExpression(node)) {
115+
exportsIsFunction = true;
116+
return { create: node, meta: null };
117+
}
118+
return currentExports;
119+
}, null);
120+
121+
// CJS
122+
const exportNodesCJS = ast.body
102123
.filter(statement => statement.type === 'ExpressionStatement')
103124
.map(statement => statement.expression)
104125
.filter(expression => expression.type === 'AssignmentExpression')
@@ -150,6 +171,8 @@ module.exports = {
150171
return currentExports;
151172
}, {});
152173

174+
const exportNodes = exportNodesESM || exportNodesCJS;
175+
153176
const createExists = Object.prototype.hasOwnProperty.call(exportNodes, 'create');
154177
if (!createExists) {
155178
return null;

tests/lib/rules/meta-property-ordering.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ ruleTester.run('test-case-property-ordering', rule, {
2424
create() {},
2525
};`,
2626

27+
{
28+
// ESM
29+
code: `
30+
export default {
31+
meta: {type, docs, fixable, schema, messages},
32+
create() {},
33+
};`,
34+
parserOptions: { sourceType: 'module' },
35+
},
36+
2737
`
2838
module.exports = {
2939
meta: {docs, schema, messages},
@@ -85,6 +95,30 @@ ruleTester.run('test-case-property-ordering', rule, {
8595
};`,
8696
errors: [{ messageId: 'inconsistentOrder', data: { order: ['type', 'docs', 'fixable'].join(', ') } }],
8797
},
98+
{
99+
// ESM
100+
code: `
101+
export default {
102+
meta: {
103+
docs,
104+
fixable,
105+
type: 'problem',
106+
},
107+
create() {},
108+
};`,
109+
110+
output: `
111+
export default {
112+
meta: {
113+
type: 'problem',
114+
docs,
115+
fixable,
116+
},
117+
create() {},
118+
};`,
119+
parserOptions: { sourceType: 'module' },
120+
errors: [{ messageId: 'inconsistentOrder', data: { order: ['type', 'docs', 'fixable'].join(', ') } }],
121+
},
88122
{
89123
code: `
90124
module.exports = {

tests/lib/rules/prefer-message-ids.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ ruleTester.run('prefer-message-ids', rule, {
2929
}
3030
};
3131
`,
32+
{
33+
// ESM
34+
code: `
35+
export default {
36+
create(context) {
37+
context.report({ node, messageId: 'foo' });
38+
}
39+
};
40+
`,
41+
parserOptions: { sourceType: 'module' },
42+
},
3243
`
3344
module.exports = {
3445
create(context) {
@@ -91,6 +102,18 @@ ruleTester.run('prefer-message-ids', rule, {
91102
`,
92103
errors: [{ messageId: 'foundMessage', type: 'Property' }],
93104
},
105+
{
106+
// ESM
107+
code: `
108+
export default {
109+
create(context) {
110+
context.report({ node, message: 'foo' });
111+
}
112+
};
113+
`,
114+
parserOptions: { sourceType: 'module' },
115+
errors: [{ messageId: 'foundMessage', type: 'Property' }],
116+
},
94117
{
95118
// With message in variable.
96119
code: `

tests/lib/rules/prefer-object-rule.js

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
const rule = require('../../../lib/rules/prefer-object-rule');
1212
const RuleTester = require('eslint').RuleTester;
1313

14-
const ERROR = { messageId: 'preferObject', line: 2, column: 26 };
15-
1614
// ------------------------------------------------------------------------------
1715
// Tests
1816
// ------------------------------------------------------------------------------
@@ -63,6 +61,18 @@ ruleTester.run('prefer-object-rule', rule, {
6361
};
6462
module.exports = rule;
6563
`,
64+
65+
{
66+
// ESM
67+
code: `
68+
export default {
69+
create(context) {
70+
return { Program() { context.report() } };
71+
},
72+
};
73+
`,
74+
parserOptions: { sourceType: 'module' },
75+
},
6676
],
6777

6878
invalid: [
@@ -77,7 +87,7 @@ ruleTester.run('prefer-object-rule', rule, {
7787
return { Program() { context.report() } };
7888
}};
7989
`,
80-
errors: [ERROR],
90+
errors: [{ messageId: 'preferObject', line: 2, column: 26 }],
8191
},
8292
{
8393
code: `
@@ -90,7 +100,7 @@ ruleTester.run('prefer-object-rule', rule, {
90100
return { Program() { context.report() } };
91101
}};
92102
`,
93-
errors: [ERROR],
103+
errors: [{ messageId: 'preferObject', line: 2, column: 26 }],
94104
},
95105
{
96106
code: `
@@ -103,7 +113,35 @@ ruleTester.run('prefer-object-rule', rule, {
103113
return { Program() { context.report() } };
104114
}};
105115
`,
106-
errors: [ERROR],
116+
errors: [{ messageId: 'preferObject', line: 2, column: 26 }],
117+
},
118+
119+
// ESM
120+
{
121+
code: `
122+
export default function (context) {
123+
return { Program() { context.report() } };
124+
};
125+
`,
126+
output: `
127+
export default {create(context) {
128+
return { Program() { context.report() } };
129+
}};
130+
`,
131+
parserOptions: { sourceType: 'module' },
132+
errors: [{ messageId: 'preferObject', line: 2, column: 24 }],
133+
},
134+
{
135+
code: 'export default function create() {};',
136+
output: 'export default {create() {}};',
137+
parserOptions: { sourceType: 'module' },
138+
errors: [{ messageId: 'preferObject', line: 1, column: 16 }],
139+
},
140+
{
141+
code: 'export default () => {};',
142+
output: 'export default {create: () => {}};',
143+
parserOptions: { sourceType: 'module' },
144+
errors: [{ messageId: 'preferObject', line: 1, column: 16 }],
107145
},
108146
],
109147
});

tests/lib/rules/report-message-format.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ ruleTester.run('report-message-format', rule, {
3333
`,
3434
options: ['foo'],
3535
},
36+
{
37+
// ESM
38+
code: `
39+
export default {
40+
create(context) {
41+
context.report(node, 'foo');
42+
}
43+
};
44+
`,
45+
options: ['foo'],
46+
parserOptions: { sourceType: 'module' },
47+
},
3648
{
3749
// With message as variable.
3850
code: `
@@ -164,6 +176,18 @@ ruleTester.run('report-message-format', rule, {
164176
`,
165177
options: ['foo'],
166178
},
179+
{
180+
// ESM
181+
code: `
182+
export default {
183+
create(context) {
184+
context.report(node, 'bar');
185+
}
186+
};
187+
`,
188+
options: ['foo'],
189+
parserOptions: { sourceType: 'module' },
190+
},
167191
{
168192
// With message as variable.
169193
code: `

tests/lib/rules/require-meta-docs-description.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ ruleTester.run('require-meta-docs-description', rule, {
2121
create(context) {}
2222
};
2323
`,
24+
{
25+
// ESM
26+
code: `
27+
export default {
28+
meta: { docs: { description: 'disallow unused variables' } },
29+
create(context) {}
30+
};
31+
`,
32+
parserOptions: { sourceType: 'module' },
33+
},
2434
`
2535
module.exports = {
2636
meta: { docs: { description: 'enforce a maximum line length' } },
@@ -104,6 +114,18 @@ ruleTester.run('require-meta-docs-description', rule, {
104114
output: null,
105115
errors: [{ messageId: 'missing', type: 'ObjectExpression' }],
106116
},
117+
{
118+
// ESM
119+
code: `
120+
export default {
121+
meta: {},
122+
create(context) {}
123+
};
124+
`,
125+
output: null,
126+
parserOptions: { sourceType: 'module' },
127+
errors: [{ messageId: 'missing', type: 'ObjectExpression' }],
128+
},
107129
{
108130
code: `
109131
module.exports = {

tests/lib/rules/require-meta-docs-url.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@ tester.run('require-meta-docs-url', rule, {
6666
pattern: 'path/to/{{name}}.md',
6767
}],
6868
},
69+
{
70+
// ESM
71+
filename: 'test-rule',
72+
code: `
73+
export default {
74+
meta: {docs: {url: "path/to/test-rule.md"}},
75+
create() {}
76+
}
77+
`,
78+
options: [{
79+
pattern: 'path/to/{{name}}.md',
80+
}],
81+
parserOptions: { sourceType: 'module' },
82+
},
6983
{
7084
// `url` in variable.
7185
filename: 'test-rule',
@@ -537,6 +551,31 @@ url: "plugin-name/test.md"
537551
}],
538552
errors: [{ messageId: 'missing', type: 'ObjectExpression' }],
539553
},
554+
{
555+
// ESM
556+
filename: 'test.js',
557+
code: `
558+
export default {
559+
meta: {},
560+
create() {}
561+
}
562+
`,
563+
output: `
564+
export default {
565+
meta: {
566+
docs: {
567+
url: "plugin-name/test.md"
568+
}
569+
},
570+
create() {}
571+
}
572+
`,
573+
options: [{
574+
pattern: 'plugin-name/{{ name }}.md',
575+
}],
576+
parserOptions: { sourceType: 'module' },
577+
errors: [{ messageId: 'missing', type: 'ObjectExpression' }],
578+
},
540579
{
541580
filename: 'test.js',
542581
code: `

tests/lib/rules/require-meta-fixable.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ ruleTester.run('require-meta-fixable', rule, {
3434
}
3535
};
3636
`,
37+
{
38+
// ESM
39+
code: `
40+
export default {
41+
meta: { fixable: 'code' },
42+
create(context) {
43+
context.report({node, message, fix: foo});
44+
}
45+
};
46+
`,
47+
parserOptions: { sourceType: 'module' },
48+
},
3749
// Value in variable.
3850
`
3951
const fixable = 'code';
@@ -183,6 +195,17 @@ ruleTester.run('require-meta-fixable', rule, {
183195
`,
184196
errors: [{ messageId: 'missing', type: 'ObjectExpression' }],
185197
},
198+
{
199+
// ESM
200+
code: `
201+
export default {
202+
meta: {},
203+
create(context) { context.report({node, message, fix: foo}); }
204+
};
205+
`,
206+
parserOptions: { sourceType: 'module' },
207+
errors: [{ messageId: 'missing', type: 'ObjectExpression' }],
208+
},
186209
{
187210
code: `
188211
module.exports = {

0 commit comments

Comments
 (0)