Skip to content

Commit

Permalink
feat: add physicalFilename property to the rule context (#17111)
Browse files Browse the repository at this point in the history
* feat: add `physicalFilename` property to the rule context

* docs: mark `context.getPhysicalFilename()` as deprecated

* tests: add asertions for context.getPhysicalFilename()

* docs: update context.physicalFilename description

* docs: remove duplicate changes

* tests: add more assertions for `getFilename()` and `getPhysicalFilename()`
  • Loading branch information
snitin315 committed Apr 29, 2023
1 parent 0df4d4f commit 1468f5b
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 10 deletions.
3 changes: 2 additions & 1 deletion docs/src/extend/custom-rules.md
Expand Up @@ -125,6 +125,7 @@ The `context` object has the following properties:

* `id`: (`string`) The rule ID.
* `filename`: (`string`) The filename associated with the source.
* `physicalFilename`: (`string`) When linting a file, it provides the full path of the file on disk without any code block information. When linting text, it provides the value passed to `—stdin-filename` or `<text>` if not specified.
* `cwd`: (`string`) The `cwd` option passed to the [Linter](../integrate/nodejs-api#linter). It is a path to a directory that should be considered the current working directory.
* `options`: (`array`) An array of the [configured options](../use/configure/rules) for this rule. This array does not include the rule severity (see the [dedicated section](#accessing-options-passed-to-a-rule)).
* `settings`: (`object`) The [shared settings](../use/configure/configuration-files#adding-shared-settings) from the configuration.
Expand All @@ -147,7 +148,7 @@ Additionally, the `context` object has the following methods:
* If the node is an `ImportSpecifier`, `ImportDefaultSpecifier`, or `ImportNamespaceSpecifier`, the declared variable is returned.
* Otherwise, if the node does not declare any variables, an empty array is returned.
* `getFilename()`: (**Deprecated:** Use `context.filename` instead.) Returns the filename associated with the source.
* `getPhysicalFilename()`: When linting a file, it returns the full path of the file on disk without any code block information. When linting text, it returns the value passed to `—stdin-filename` or `<text>` if not specified.
* `getPhysicalFilename()`: (**Deprecated:** Use `context.physicalFilename` instead.) When linting a file, it returns the full path of the file on disk without any code block information. When linting text, it returns the value passed to `—stdin-filename` or `<text>` if not specified.
* `getScope()`: (**Deprecated:** Use `SourceCode#getScope(node)` instead.) Returns the [scope](./scope-manager-interface#scope-interface) of the currently-traversed node. This information can be used to track references to variables.
* `getSourceCode()`: Returns a `SourceCode` object that you can use to work with the source that was passed to ESLint (see [Accessing the Source Code](#accessing-the-source-code)).
* `markVariableAsUsed(name)`: (**Deprecated:** Use `SourceCode#markVariableAsUsed(name, node)` instead.) Marks a variable with the given name in the current scope as used. This affects the [no-unused-vars](../rules/no-unused-vars) rule. Returns `true` if a variable with the given name was found and marked as used, otherwise `false`.
Expand Down
1 change: 1 addition & 0 deletions lib/linter/linter.js
Expand Up @@ -955,6 +955,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
getFilename: () => filename,
filename,
getPhysicalFilename: () => physicalFilename || filename,
physicalFilename: physicalFilename || filename,
getScope: () => sourceCode.getScope(currentNode),
getSourceCode: () => sourceCode,
markVariableAsUsed: name => sourceCode.markVariableAsUsed(name, currentNode),
Expand Down
66 changes: 57 additions & 9 deletions tests/lib/linter/linter.js
Expand Up @@ -1847,7 +1847,8 @@ describe("Linter", () => {
linter.defineRule(code, {
create: context => ({
Literal(node) {
context.report(node, context.getPhysicalFilename());
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);
context.report(node, context.physicalFilename);
}
})
});
Expand Down Expand Up @@ -4868,7 +4869,8 @@ var a = "test2";
describe("physicalFilenames", () => {
it("should be same as `filename` passed on options object, if no processors are used", () => {
const physicalFilenameChecker = sinon.spy(context => {
assert.strictEqual(context.getPhysicalFilename(), "foo.js");
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);
assert.strictEqual(context.physicalFilename, "foo.js");
return {};
});

Expand All @@ -4879,7 +4881,8 @@ var a = "test2";

it("should default physicalFilename to <input> when options object doesn't have filename", () => {
const physicalFilenameChecker = sinon.spy(context => {
assert.strictEqual(context.getPhysicalFilename(), "<input>");
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);
assert.strictEqual(context.physicalFilename, "<input>");
return {};
});

Expand All @@ -4890,7 +4893,8 @@ var a = "test2";

it("should default physicalFilename to <input> when only two arguments are passed", () => {
const physicalFilenameChecker = sinon.spy(context => {
assert.strictEqual(context.getPhysicalFilename(), "<input>");
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);
assert.strictEqual(context.physicalFilename, "<input>");
return {};
});

Expand Down Expand Up @@ -6756,8 +6760,11 @@ var a = "test2";
linter.defineRule("report-original-text", {
create: context => ({
Program(ast) {
assert.strictEqual(context.getFilename(), context.filename);
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);

receivedFilenames.push(context.filename);
receivedPhysicalFilenames.push(context.getPhysicalFilename());
receivedPhysicalFilenames.push(context.physicalFilename);
context.report({ node: ast, message: context.getSourceCode().text });
}
})
Expand Down Expand Up @@ -9211,6 +9218,41 @@ describe("Linter with FlatConfigArray", () => {

});

describe("context.physicalFilename", () => {

const ruleId = "filename-rule";

it("has access to the physicalFilename", () => {

const config = {
plugins: {
test: {
rules: {
[ruleId]: {
create: context => ({
Literal(node) {
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);
context.report(node, context.physicalFilename);
}
})
}
}
}
},
rules: {
[`test/${ruleId}`]: 1
}
};

const messages = linter.verify("0", config, filename);
const suppressedMessages = linter.getSuppressedMessages();

assert.strictEqual(messages[0].message, filename);
assert.strictEqual(suppressedMessages.length, 0);
});

});

describe("context.getSourceLines()", () => {

it("should get proper lines when using \\n as a line break", () => {
Expand Down Expand Up @@ -11310,7 +11352,8 @@ describe("Linter with FlatConfigArray", () => {
describe("physicalFilename", () => {
it("should be same as `filename` passed on options object, if no processors are used", () => {
const physicalFilenameChecker = sinon.spy(context => {
assert.strictEqual(context.getPhysicalFilename(), "foo.js");
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);
assert.strictEqual(context.physicalFilename, "foo.js");
return {};
});

Expand All @@ -11333,7 +11376,8 @@ describe("Linter with FlatConfigArray", () => {

it("should default physicalFilename to <input> when options object doesn't have filename", () => {
const physicalFilenameChecker = sinon.spy(context => {
assert.strictEqual(context.getPhysicalFilename(), "<input>");
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);
assert.strictEqual(context.physicalFilename, "<input>");
return {};
});

Expand All @@ -11356,7 +11400,8 @@ describe("Linter with FlatConfigArray", () => {

it("should default physicalFilename to <input> when only two arguments are passed", () => {
const physicalFilenameChecker = sinon.spy(context => {
assert.strictEqual(context.getPhysicalFilename(), "<input>");
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);
assert.strictEqual(context.physicalFilename, "<input>");
return {};
});

Expand Down Expand Up @@ -15522,8 +15567,11 @@ var a = "test2";
create(context) {
return {
Program(ast) {
assert.strictEqual(context.getFilename(), context.filename);
assert.strictEqual(context.getPhysicalFilename(), context.physicalFilename);

receivedFilenames.push(context.filename);
receivedPhysicalFilenames.push(context.getPhysicalFilename());
receivedPhysicalFilenames.push(context.physicalFilename);
context.report({ node: ast, message: context.getSourceCode().text });
}
};
Expand Down

0 comments on commit 1468f5b

Please sign in to comment.