Skip to content

Commit dd7302b

Browse files
committed
New: meta-property-ordering (fixes #62)
1 parent 9bab974 commit dd7302b

File tree

5 files changed

+264
-0
lines changed

5 files changed

+264
-0
lines changed

.eslintrc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extends:
88
root: true
99
rules:
1010
require-jsdoc: error
11+
self/meta-property-ordering: off
1112
self/require-meta-docs-url: off
1213
self/report-message-format:
1314
- error

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Name | ✔️ | 🛠 | Description
5151
----- | ----- | ----- | -----
5252
[consistent-output](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/consistent-output.md) | | | Enforce consistent use of output assertions in rule tests
5353
[fixer-return](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/fixer-return.md) | ✔️ | | Expected fixer function to always return a value.
54+
[meta-property-ordering](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/meta-property-ordering.md) | | 🛠 | Enforces the order of meta properties
5455
[no-deprecated-context-methods](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-deprecated-context-methods.md) | | 🛠 | Disallows usage of deprecated methods on rule context objects
5556
[no-deprecated-report-api](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-deprecated-report-api.md) | ✔️ | 🛠 | disallow use of the deprecated context.report() API
5657
[no-identical-tests](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-identical-tests.md) | ✔️ | 🛠 | disallow identical tests

docs/rules/meta-property-ordering.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# enforce ordering of meta properties in rule source (meta-property-ordering)
2+
3+
(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule.
4+
5+
This rule enforces that the properties of rule meta are arranged in a consistent order.
6+
7+
## Rule Details
8+
9+
### Options
10+
11+
This rule has an array option:
12+
13+
* `['type', 'docs', 'fixable', 'schema', 'messages', 'deprecated', 'replacedBy']` (default): The properties of meta should be placed in a consistent order.
14+
15+
Examples of **incorrect** code for this rule:
16+
17+
```js
18+
19+
/* eslint eslint-plugin/meta-property-ordering: ["error",
20+
["type", "docs", "fixable", "schema", "messages"]
21+
] */
22+
23+
// invalid; wrong order
24+
{
25+
fixable: false,
26+
type: "problem",
27+
docs: "",
28+
}
29+
30+
```
31+
32+
Examples of **correct** code for this rule:
33+
34+
```js
35+
/* eslint eslint-plugin/test-case-property-ordering: ["error",
36+
["type", "docs", "fixable", "schema", "messages"]
37+
] */
38+
39+
// valid;
40+
{
41+
type: "bar",
42+
docs: "foo",
43+
fooooooooo: "foo",
44+
fixable: false,
45+
}
46+
47+
```
48+
49+
## When Not To Use It
50+
51+
If don't want to enforce ordering of properies in meta, you can turn off this rule.

lib/rules/meta-property-ordering.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* @fileoverview Enforces the order of meta properties
3+
*/
4+
5+
'use strict';
6+
7+
const { getKeyName, getRuleInfo } = require('../utils');
8+
9+
// ------------------------------------------------------------------------------
10+
// Rule Definition
11+
// ------------------------------------------------------------------------------
12+
13+
module.exports = {
14+
meta: {
15+
docs: {
16+
description: 'Enforces the order of meta properties',
17+
category: 'Rules',
18+
recommended: false,
19+
},
20+
type: 'suggestion',
21+
fixable: 'code',
22+
schema: [{
23+
type: 'array',
24+
elements: { type: 'string' },
25+
}],
26+
},
27+
28+
create (context) {
29+
const sourceCode = context.getSourceCode();
30+
const info = getRuleInfo(sourceCode.ast);
31+
32+
const message = 'The meta properties should be placed in a consistent order: [{{order}}].';
33+
const order = context.options[0] || ['type', 'docs', 'fixable', 'schema', 'messages'];
34+
35+
const orderMap = new Map(order.map((name, i) => [name, i]));
36+
37+
return {
38+
Program () {
39+
if (
40+
!info ||
41+
!info.meta ||
42+
info.meta.properties.length < 2
43+
) {
44+
return;
45+
}
46+
47+
const propsActual = info.meta.properties
48+
.filter(prop => orderMap.has(getKeyName(prop)));
49+
50+
for (let i = 1, j = propsActual.length; i < j; i += 1) {
51+
const last = propsActual[i - 1];
52+
const curr = propsActual[i];
53+
if (order.indexOf(getKeyName(last)) > order.indexOf(getKeyName(curr))) {
54+
const propsExpected = propsActual
55+
.slice()
56+
.sort((a, b) => orderMap.get(getKeyName(a)) - orderMap.get(getKeyName(b)));
57+
58+
context.report({
59+
node: curr,
60+
message,
61+
data: {
62+
order: propsExpected.map(getKeyName).join(', '),
63+
},
64+
fix (fixer) {
65+
return propsActual.map((prop, k) => {
66+
return fixer.replaceText(
67+
prop,
68+
sourceCode.getText(propsExpected[k])
69+
);
70+
});
71+
},
72+
});
73+
}
74+
}
75+
},
76+
};
77+
},
78+
};
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/**
2+
* @fileoverview Enforces the order of meta properties
3+
*/
4+
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
const rule = require('../../../lib/rules/meta-property-ordering');
12+
const RuleTester = require('eslint').RuleTester;
13+
14+
// ------------------------------------------------------------------------------
15+
// Tests
16+
// ------------------------------------------------------------------------------
17+
18+
/**
19+
* @param {string[]} order
20+
* @returns {string}
21+
*/
22+
function getMessage (order) {
23+
return `The meta properties should be placed in a consistent order: [${order.join(', ')}].`;
24+
}
25+
26+
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
27+
ruleTester.run('test-case-property-ordering', rule, {
28+
valid: [
29+
`
30+
module.exports = {
31+
meta: {type, docs, fixable, schema, messages},
32+
create() {},
33+
};`,
34+
35+
`
36+
module.exports = {
37+
meta: {docs, schema, messages},
38+
create() {},
39+
};`,
40+
41+
`
42+
module.exports = {
43+
meta: {docs, foo, bar, messages},
44+
create() {},
45+
};`,
46+
47+
`
48+
module.exports = {
49+
meta: {
50+
type: 'problem',
51+
docs: {},
52+
fixable: 'code',
53+
schema: [],
54+
messages: {}
55+
},
56+
create() {},
57+
};`,
58+
{
59+
code: `
60+
module.exports = {
61+
meta: {messages, schema, docs},
62+
create() {},
63+
};`,
64+
options: [['schema', 'docs']],
65+
},
66+
`
67+
module.exports = {
68+
meta: {},
69+
create() {},
70+
};`,
71+
],
72+
73+
invalid: [
74+
{
75+
code: `
76+
module.exports = {
77+
meta: {
78+
docs,
79+
fixable,
80+
type: 'problem',
81+
},
82+
create() {},
83+
};`,
84+
85+
output: `
86+
module.exports = {
87+
meta: {
88+
type: 'problem',
89+
docs,
90+
fixable,
91+
},
92+
create() {},
93+
};`,
94+
errors: [{ message: getMessage(['type', 'docs', 'fixable']) }],
95+
},
96+
{
97+
code: `
98+
module.exports = {
99+
meta: {schema, fixable, type, docs},
100+
create() {},
101+
};`,
102+
103+
output: `
104+
module.exports = {
105+
meta: {type, docs, fixable, schema},
106+
create() {},
107+
};`,
108+
errors: [
109+
{ message: getMessage(['type', 'docs', 'fixable', 'schema']) },
110+
{ message: getMessage(['type', 'docs', 'fixable', 'schema']) },
111+
],
112+
},
113+
114+
{
115+
code: `
116+
module.exports = {
117+
meta: {fixable, fooooooooo, doc, type},
118+
create() {},
119+
};`,
120+
121+
output: `
122+
module.exports = {
123+
meta: {type, fooooooooo, doc, fixable},
124+
create() {},
125+
};`,
126+
options: [['type', 'doc', 'fixable']],
127+
errors: [
128+
{ message: getMessage(['type', 'doc', 'fixable']) },
129+
{ message: getMessage(['type', 'doc', 'fixable']) },
130+
],
131+
},
132+
],
133+
});

0 commit comments

Comments
 (0)