Skip to content

Commit 3a87bbb

Browse files
authored
fix: Support legacy schema properties (#128)
1 parent c24083b commit 3a87bbb

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed

packages/compat/src/fixup-rules.js

+15
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,21 @@ export function fixupRule(ruleDefinition) {
183183
create: ruleCreate,
184184
};
185185

186+
// copy `schema` property of function-style rule or top-level `schema` property of object-style rule into `meta` object
187+
// @ts-ignore -- top-level `schema` property was not offically supported for object-style rules so it doesn't exist in types
188+
const { schema } = ruleDefinition;
189+
if (schema) {
190+
if (!newRuleDefinition.meta) {
191+
newRuleDefinition.meta = { schema };
192+
} else {
193+
newRuleDefinition.meta = {
194+
...newRuleDefinition.meta,
195+
// top-level `schema` had precedence over `meta.schema` so it's okay to overwrite `meta.schema` if it exists
196+
schema,
197+
};
198+
}
199+
}
200+
186201
// cache the fixed up rule
187202
fixedUpRuleReplacements.set(ruleDefinition, newRuleDefinition);
188203
fixedUpRules.add(newRuleDefinition);

packages/compat/tests/fixup-rules.js

+178
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,184 @@ describe("@eslint/backcompat", () => {
7676
assert.strictEqual(fixedUpRule, fixedUpRule2);
7777
});
7878

79+
it("should return a new rule object with `meta.schema` when a rule with top-level `schema` and without `meta` is passed to fixupRule", () => {
80+
const schema = [{ type: "string" }];
81+
const rule = {
82+
schema,
83+
create(context) {
84+
return {
85+
Identifier(node) {
86+
context.report(node, context.options[0]);
87+
},
88+
};
89+
},
90+
};
91+
const fixedUpRule = fixupRule(rule);
92+
93+
assert.notStrictEqual(rule, fixedUpRule);
94+
assert.deepStrictEqual(Object.keys(fixedUpRule), [
95+
...Object.keys(rule),
96+
"meta",
97+
]);
98+
assert.strictEqual(typeof fixedUpRule.meta, "object");
99+
assert.deepStrictEqual(fixedUpRule.meta.schema, schema);
100+
101+
const config = {
102+
plugins: {
103+
test: {
104+
rules: {
105+
"test-rule": fixedUpRule,
106+
},
107+
},
108+
},
109+
rules: {
110+
"test/test-rule": ["error", "my-option"],
111+
},
112+
};
113+
114+
const linter = new Linter();
115+
const code = "var foo;";
116+
const messages = linter.verify(code, config, {
117+
filename: "test.js",
118+
});
119+
120+
assert.strictEqual(messages.length, 1);
121+
assert.strictEqual(messages[0].message, "my-option");
122+
});
123+
124+
it("should return a new rule object with `meta.schema` when a rule with top-level `schema` and with `meta` is passed to fixupRule", () => {
125+
const schema = [{ type: "string" }];
126+
const rule = {
127+
schema,
128+
meta: {
129+
docs: {},
130+
},
131+
create(context) {
132+
return {
133+
Identifier(node) {
134+
context.report(node, context.options[0]);
135+
},
136+
};
137+
},
138+
};
139+
const fixedUpRule = fixupRule(rule);
140+
141+
assert.notStrictEqual(rule, fixedUpRule);
142+
assert.deepStrictEqual(Object.keys(rule), Object.keys(fixedUpRule));
143+
assert.deepStrictEqual(Object.keys(fixedUpRule.meta), [
144+
...Object.keys(rule.meta),
145+
"schema",
146+
]);
147+
assert.deepStrictEqual(fixedUpRule.meta.schema, schema);
148+
149+
const config = {
150+
plugins: {
151+
test: {
152+
rules: {
153+
"test-rule": fixedUpRule,
154+
},
155+
},
156+
},
157+
rules: {
158+
"test/test-rule": ["error", "my-option"],
159+
},
160+
};
161+
162+
const linter = new Linter();
163+
const code = "var foo;";
164+
const messages = linter.verify(code, config, {
165+
filename: "test.js",
166+
});
167+
168+
assert.strictEqual(messages.length, 1);
169+
assert.strictEqual(messages[0].message, "my-option");
170+
});
171+
172+
it("should return a rule object when a function-style rule is passed to fixupRule", () => {
173+
function rule(context) {
174+
return {
175+
Identifier(node) {
176+
context.report(node, "My message.");
177+
},
178+
};
179+
}
180+
const fixedUpRule = fixupRule(rule);
181+
182+
assert.strictEqual(typeof fixedUpRule, "object");
183+
assert.deepStrictEqual(Object.keys(fixedUpRule), ["create"]);
184+
assert.strictEqual(typeof fixedUpRule.create, "function");
185+
assert.notStrictEqual(rule, fixedUpRule.create); // the original rule should be wrapped in `create`
186+
187+
const config = {
188+
plugins: {
189+
test: {
190+
rules: {
191+
"test-rule": fixedUpRule,
192+
},
193+
},
194+
},
195+
rules: {
196+
"test/test-rule": "error",
197+
},
198+
};
199+
200+
const linter = new Linter();
201+
const code = "var foo;";
202+
const messages = linter.verify(code, config, {
203+
filename: "test.js",
204+
});
205+
206+
assert.strictEqual(messages.length, 1);
207+
assert.strictEqual(messages[0].message, "My message.");
208+
});
209+
210+
it("should return a rule object with `meta.schema` when a function-style rule with schema is passed to fixupRule", () => {
211+
function rule(context) {
212+
return {
213+
Identifier(node) {
214+
context.report(node, context.options[0]);
215+
},
216+
};
217+
}
218+
219+
const schema = [{ type: "string" }];
220+
rule.schema = schema;
221+
222+
const fixedUpRule = fixupRule(rule);
223+
224+
assert.strictEqual(typeof fixedUpRule, "object");
225+
assert.deepStrictEqual(Object.keys(fixedUpRule), [
226+
"create",
227+
"meta",
228+
]);
229+
assert.strictEqual(typeof fixedUpRule.create, "function");
230+
assert.notStrictEqual(rule, fixedUpRule.create); // the original rule should be wrapped in `create`
231+
assert.strictEqual(typeof fixedUpRule.meta, "object");
232+
assert.deepStrictEqual(fixedUpRule.meta.schema, schema);
233+
234+
const config = {
235+
plugins: {
236+
test: {
237+
rules: {
238+
"test-rule": fixedUpRule,
239+
},
240+
},
241+
},
242+
rules: {
243+
"test/test-rule": ["error", "my-option"],
244+
},
245+
};
246+
247+
const linter = new Linter();
248+
const code = "var foo;";
249+
const messages = linter.verify(code, config, {
250+
filename: "test.js",
251+
});
252+
253+
assert.strictEqual(messages.length, 1);
254+
assert.strictEqual(messages[0].message, "my-option");
255+
});
256+
79257
it("should create a rule where getDeclaredVariables() returns the same value as sourceCode.getDeclaredVariables(node)", () => {
80258
const rule = {
81259
create(context) {

0 commit comments

Comments
 (0)