Skip to content

Commit

Permalink
fix: Ensure deprecated context.parserServices warns (#17593)
Browse files Browse the repository at this point in the history
* fix: Ensure deprecated context.parserServices warns

Updated RuleTester to emit a deprecation warning whenever
`context.parserServices` is used.

* Update lib/rule-tester/rule-tester.js

Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>

* Update lib/rule-tester/rule-tester.js

Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>

---------

Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
  • Loading branch information
nzakas and mdjermanovic committed Sep 22, 2023
1 parent 1ea4cfb commit cc4d26b
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 51 deletions.
63 changes: 45 additions & 18 deletions lib/rule-tester/rule-tester.js
Expand Up @@ -396,6 +396,22 @@ function emitCodePathCurrentSegmentsWarning(ruleName) {
}
}

/**
* Emit a deprecation warning if `context.parserServices` is used.
* @param {string} ruleName Name of the rule.
* @returns {void}
*/
function emitParserServicesWarning(ruleName) {
if (!emitParserServicesWarning[`warned-${ruleName}`]) {
emitParserServicesWarning[`warned-${ruleName}`] = true;
process.emitWarning(
`"${ruleName}" rule is using \`context.parserServices\`, which is deprecated and will be removed in ESLint v9. Please use \`sourceCode.parserServices\` instead.`,
"DeprecationWarning"
);
}
}


//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -627,26 +643,37 @@ class RuleTester {
freezeDeeply(context.settings);
freezeDeeply(context.parserOptions);

const newContext = Object.freeze(
Object.create(
context,
Object.fromEntries(Object.keys(DEPRECATED_SOURCECODE_PASSTHROUGHS).map(methodName => [
methodName,
{
value(...args) {

// emit deprecation warning
emitDeprecatedContextMethodWarning(ruleName, methodName);

// call the original method
return context[methodName].call(this, ...args);
},
enumerable: true
}
]))
)
// wrap all deprecated methods
const newContext = Object.create(
context,
Object.fromEntries(Object.keys(DEPRECATED_SOURCECODE_PASSTHROUGHS).map(methodName => [
methodName,
{
value(...args) {

// emit deprecation warning
emitDeprecatedContextMethodWarning(ruleName, methodName);

// call the original method
return context[methodName].call(this, ...args);
},
enumerable: true
}
]))
);

// emit warning about context.parserServices
const parserServices = context.parserServices;

Object.defineProperty(newContext, "parserServices", {
get() {
emitParserServicesWarning(ruleName);
return parserServices;
}
});

Object.freeze(newContext);

return (typeof rule === "function" ? rule : rule.create)(newContext);
}
}));
Expand Down
76 changes: 43 additions & 33 deletions tests/lib/rule-tester/rule-tester.js
Expand Up @@ -1243,39 +1243,6 @@ describe("RuleTester", () => {
});
});

it("should pass-through services from parseForESLint to the rule", () => {
const enhancedParserPath = require.resolve("../../fixtures/parsers/enhanced-parser");
const disallowHiRule = {
create: context => ({
Literal(node) {
assert.strictEqual(context.parserServices, context.sourceCode.parserServices);

const disallowed = context.sourceCode.parserServices.test.getMessage(); // returns "Hi!"

if (node.value === disallowed) {
context.report({ node, message: `Don't use '${disallowed}'` });
}
}
})
};

ruleTester.run("no-hi", disallowHiRule, {
valid: [
{
code: "'Hello!'",
parser: enhancedParserPath
}
],
invalid: [
{
code: "'Hi!'",
parser: enhancedParserPath,
errors: [{ message: "Don't use 'Hi!'" }]
}
]
});
});

it("should prevent invalid options schemas", () => {
assert.throws(() => {
ruleTester.run("no-invalid-schema", require("../../fixtures/testers/rule-tester/no-invalid-schema"), {
Expand Down Expand Up @@ -2515,6 +2482,48 @@ describe("RuleTester", () => {
);
});

it("should pass-through services from parseForESLint to the rule and log deprecation notice", () => {
const enhancedParserPath = require.resolve("../../fixtures/parsers/enhanced-parser");
const disallowHiRule = {
create: context => ({
Literal(node) {
assert.strictEqual(context.parserServices, context.sourceCode.parserServices);

const disallowed = context.sourceCode.parserServices.test.getMessage(); // returns "Hi!"

if (node.value === disallowed) {
context.report({ node, message: `Don't use '${disallowed}'` });
}
}
})
};

ruleTester.run("no-hi", disallowHiRule, {
valid: [
{
code: "'Hello!'",
parser: enhancedParserPath
}
],
invalid: [
{
code: "'Hi!'",
parser: enhancedParserPath,
errors: [{ message: "Don't use 'Hi!'" }]
}
]
});

assert.strictEqual(processStub.callCount, 1, "calls `process.emitWarning()` once");
assert.deepStrictEqual(
processStub.getCall(0).args,
[
"\"no-hi\" rule is using `context.parserServices`, which is deprecated and will be removed in ESLint v9. Please use `sourceCode.parserServices` instead.",
"DeprecationWarning"
]
);

});
Object.entries({
getSource: "getText",
getSourceLines: "getLines",
Expand Down Expand Up @@ -2583,6 +2592,7 @@ describe("RuleTester", () => {

});


});

/**
Expand Down

0 comments on commit cc4d26b

Please sign in to comment.