Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use getPhysicalFilename() instead of getFilename() if available (ESLint 7.28+) #2160

Merged
merged 1 commit into from Aug 3, 2021

Conversation

pmcelhaney
Copy link
Contributor

Starting with 7.28.0, ESLint has a new feature distinguishing the physical filename from the virtual filename.

context.getPhysicalFilename()

Rules can now use the new method getPhysicalFilename() on the context object to get the full path of the file on disk without any code block information.

The difference between getPhysicalFilename and getFilename is observable when ESLint is used with processors:

context.getPhysicalFilename() // "/project/example.md"        - original file
context.getFilename()         // "/project/example.md/0_0.js" - virtual filename assigned to a code block

When there's a difference, this plugin needs the real, physical filename. (See
eslint/eslint#11989)

I ran into the problem when I noticed no-unresolved was yielding false positives inside of code blocks in Storybook / Markdown files and helped push the necessary change through in ESLint.

To maintain backwards compatibility, this change uses context.getPhysicalFilename() if available and otherwise falls back to getFilename().

Comment on lines 52 to 64
it('falls back to getFilename() when getPhysicalFileName() is not available (ESLint < 7.28)', function () {
const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' });

expect(resolve( '../files/foo'
, Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
)).to.equal(utils.testFilePath('./bar.jsx'));

expect(resolve( '../files/foo'
, Object.assign({}, testContext, { getFilename: function () { throw new Error('Should call getPhysicalFilename() instead of getFilename()'); }, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
)).to.equal(utils.testFilePath('./bar.jsx'));


});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this test to make sure the fallback behavior is working. Otherwise the tests have been updated to use getPhysicalFilename() instead of getFilename().

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

please swap all the a && a() || b() for a ? a() : b(); plus the tests comment

@@ -4,7 +4,7 @@ import readPkgUp from 'read-pkg-up';


export function getContextPackagePath(context) {
return getFilePackagePath(context.getFilename());
return getFilePackagePath((context.getPhysicalFilename && context.getPhysicalFilename()) || context.getFilename());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return getFilePackagePath((context.getPhysicalFilename && context.getPhysicalFilename()) || context.getFilename());
return getFilePackagePath(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());

@@ -43,7 +43,7 @@ module.exports = {
if (!deepLookup.found) {
if (deepLookup.path.length > 1) {
const deepPath = deepLookup.path
.map(i => path.relative(path.dirname(context.getFilename()), i.path))
.map(i => path.relative(path.dirname((context.getPhysicalFilename && context.getPhysicalFilename()) || context.getFilename()), i.path))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.map(i => path.relative(path.dirname((context.getPhysicalFilename && context.getPhysicalFilename()) || context.getFilename()), i.path))
.map(i => path.relative(path.dirname(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename()), i.path))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's better. Let me know how you want to proceed on the tests and I'll make both changes at the same time. Thanks for the feedback!

, Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
, Object.assign({}, testContext, { getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than modifying the existing tests, please leave these alone, so that the new getPhysicalFilename duplicated tests are clearly additions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, which do you prefer?

  1. Duplicate all of the existing tests so that the only difference is getFilename() vs. getPhysicalFilename()
  2. Revert the changes so that we're testing all of the use cases for getFilename() and not exercising getPhysicalFilename() except for the couple of tests demonstrating that getPhysicalFilename() is the preferred API and getFIlename() is a fallback.
  3. Same as 1, but add getFilename() { throw new Error(...) } to the mock context on all the new tests rather than have a separate test for the fallback.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was originally thinking option 1, but i really do like option 3.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ljharb These changes are done.

@ljharb ljharb added the package: utils eslint-module-utils package label Aug 3, 2021
@ljharb ljharb force-pushed the physical-filename branch 2 times, most recently from a4c0ab4 to bfab4cc Compare August 3, 2021 15:40
@ljharb
Copy link
Member

ljharb commented Aug 3, 2021

(Had to update the tests so the getPhysicalFilename stuff only applies in eslint v7.28+)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package: utils eslint-module-utils package
Development

Successfully merging this pull request may close these issues.

None yet

2 participants