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

No useless index in import paths #1290

Merged
merged 2 commits into from
Mar 16, 2019

Conversation

timkraut
Copy link
Contributor

@timkraut timkraut commented Feb 18, 2019

As discussed in #394, this PR adds an option noUselessIndex to detect (and fix) paths containing unnecessary index parts (with or without file extension):

Given the following file structure:

my-project
├── foo.js
└── foo
    └── index.js
└── bar
    └── index.js

Before:

import 'foo/index' // No warning
import 'bar/index' // No warning

After:

import './foo/index.js' // Warning (fixable to `./foo/`)
import './foo/index' // Warning (fixable to `./foo/`)
import './bar/index' // Warning (fixable to `./bar`)

Implementation detail:

I've replaced the sumBy function with reduce to get rid of Lodash (not necessary in this case IMO). A benchmark which compares these 2 alternatives shows no difference between them or a slight advantage for reduce: https://www.measurethat.net/Benchmarks/ShowResult/46787

Fixes #394.

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.

Let's put this behind an option, to avoid it being a breaking change.

@timkraut timkraut force-pushed the no-useless-index-in-import-paths branch 2 times, most recently from 6c97e3b to 1b1abc0 Compare February 19, 2019 16:39
@timkraut
Copy link
Contributor Author

timkraut commented Feb 19, 2019

@ljharb I've updated the PR to use an option detectUselessIndex to detect these issue. The rule tries to find ambiguous imports for all extensions provided in:

    'import/resolver': {
      'node': {
        'extensions': [
          // some extensions
        ],
      },
    },

If this setting is not set, ['.js'] will be assumed.

Let me know if that looks like a reasonable approach to you. I'm totally open for different ideas.

The tests are still failing. I'm not sure what to do about them. To make sure my changes pass the tests, I've only used the test suite for no-useless-path-segments locally. So this should be fine once the other failing tests have been fixed.

@timkraut timkraut marked this pull request as ready for review February 19, 2019 16:43
.gitignore Outdated Show resolved Hide resolved
docs/rules/no-useless-path-segments.md Outdated Show resolved Hide resolved
src/rules/no-useless-path-segments.js Outdated Show resolved Hide resolved
src/rules/no-useless-path-segments.js Show resolved Hide resolved
src/rules/no-useless-path-segments.js Outdated Show resolved Hide resolved
@timkraut timkraut force-pushed the no-useless-index-in-import-paths branch from 1b1abc0 to 29ad42c Compare February 20, 2019 10:25
@coveralls
Copy link

coveralls commented Feb 20, 2019

Coverage Status

Coverage increased (+0.02%) to 97.336% when pulling 4808942 on timkraut:no-useless-index-in-import-paths into 246be82 on benmosher:master.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.5%) to 93.651% when pulling 29ad42c on timkraut:no-useless-index-in-import-paths into bdc05aa on benmosher:master.

1 similar comment
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.5%) to 93.651% when pulling 29ad42c on timkraut:no-useless-index-in-import-paths into bdc05aa on benmosher:master.

@timkraut timkraut force-pushed the no-useless-index-in-import-paths branch 4 times, most recently from 60c9f11 to 26c60e4 Compare February 21, 2019 15:06

```js
// in my-project/app.js
import "./helpers/index"; // should be "./helpers" (not auto-fixable because of helpers.js)
Copy link
Member

Choose a reason for hiding this comment

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

this should be autofixable to ./helpers/

Copy link
Contributor Author

@timkraut timkraut Feb 26, 2019

Choose a reason for hiding this comment

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

Ah. I didn't even know that there is a difference between ./helpers/ --> ./helpers/index.js and ./helpers --> ./helpers.js.

Just to make sure we don't miss an option, these are all possible import paths:

./helpers.js --> ./helpers.js
./helpers --> ./helpers.js
./helpers/ --> ./helpers/index.js
./helpers/index.js --> ./helpers/index.js
./helpers/index --> ./helpers/index.js
./helpers/index/ --> ./helpers/index/index.js

If I'm not mistaken, this means that there is no possibility for ambiguous imports. Either it's an index.js file in an directory (in this case, we have a trailing /) or it's a file (in this case, we have no trailing /). Am I missing something?

Copy link
Member

@ljharb ljharb Feb 26, 2019

Choose a reason for hiding this comment

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

Yes.

In the presence of both helpers.js and helpers/index.js:

./helpers.js → ./helpers.js
./helpers → ./helpers.js (ambiguous)
./helpers/ → ./helpers/index.js
./helpers/index.js → ./helpers/index.js
./helpers/index → ./helpers/index.js
/.helpers/index/ → ./helpers/index/index.js (error, nonexistent here)

When there is only helpers.js:

./helpers.js → ./helpers.js
./helpers → ./helpers.js
./helpers/ → ./helpers/index.js (error, nonexistent here)
./helpers/index.js → ./helpers/index.js (error, nonexistent here)
./helpers/index → ./helpers/index.js (error, nonexistent here)
/.helpers/index/ → ./helpers/index/index.js (error, nonexistent here)

When there is only helpers/index.js:

./helpers.js → ./helpers.js  (error, nonexistent here)
./helpers → ./helpers/index.js
./helpers/ → ./helpers/index.js
./helpers/index.js → ./helpers/index.js
./helpers/index → ./helpers/index.js
/.helpers/index/ → ./helpers/index/index.js (error, nonexistent here)

Everything that exists is autofixable except the one ambiguous case.

Copy link
Contributor Author

@timkraut timkraut Mar 4, 2019

Choose a reason for hiding this comment

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

Thank you very much! That helped a lot!

I've extended the list by the expected result:

helpers.js and helpers/index.js exist

Import path (import '...') Resolves to Shortest possible path? (Explanation)
./helpers.js ./helpers.js ✅ (changing the path to ./helpers would make it ambiguous)
./helpers ./helpers.js (ambiguous) ✅ (path is ambiguous, but still decidedly resolves to the file, not the directory)
./helpers/ ./helpers/index.js ✅ (changing the path to ./helpers would make it ambiguous)
./helpers/index.js ./helpers/index.js ❌ (change to ./helpers/ possible)
./helpers/index ./helpers/index.js ❌ (change to ./helpers/ possible)
./helpers/index/ ./helpers/index/index.js (Not existent)

Only helpers.js exists:

Import path (import '...') Resolves to Shortest possible path? (Explanation)
./helpers.js ./helpers.js ✅ (no useless index part in this path - .js is not needed but could be detected by extensions rule)
./helpers ./helpers.js
./helpers/ ./helpers.js (Not existent)
./helpers/index.js ./helpers/index.js (Not existent)
./helpers/index ./helpers/index.js (Not existent)
./helpers/index/ ./helpers/index/index.js (Not existent)

Only helpers/index.js exists:

Import path (import '...') Resolves to Shortest possible path? (Explanation)
./helpers.js ./helpers.js (Not existent)
./helpers ./helpers/index.js
./helpers/ ./helpers/index.js ❌ (change to ./helpers possible)
./helpers/index.js ./helpers/index.js ❌ (change to ./helpers possible)
./helpers/index ./helpers/index.js ❌ (change to ./helpers possible)
./helpers/index/ ./helpers/index/index.js (Not existent)

I've added tests for all these cases and adapted the implementation to that. Would you prefer to see a dedicated warning for the ambiguous case or should this just be accepted as a valid import?

Copy link
Member

Choose a reason for hiding this comment

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

I've updated your table for two cases, otherwise looks good.

docs/rules/no-useless-path-segments.md Show resolved Hide resolved
@timkraut timkraut force-pushed the no-useless-index-in-import-paths branch 2 times, most recently from b2c17d0 to a8242dd Compare March 4, 2019 16:33
@timkraut
Copy link
Contributor Author

timkraut commented Mar 4, 2019

I've changed the name of the new option from detectUselessIndex to noUselessIndex and rebased the branch to the latest master commit.

@timkraut timkraut force-pushed the no-useless-index-in-import-paths branch 3 times, most recently from ed359c1 to 7fa9386 Compare March 5, 2019 10:22
@timkraut
Copy link
Contributor Author

timkraut commented Mar 5, 2019

I've updated the PR to include tests for getFileExtensions. As this function returns a Set, I've updated chai.js to the latest version to test for that. This resulted in failing tests which I've fixed as well. See chaijs/chai#781 for the breaking changes (in the case of this plugin, I had to rename .deep to .nested)

@timkraut timkraut force-pushed the no-useless-index-in-import-paths branch 2 times, most recently from 53a31b0 to 2d6c203 Compare March 5, 2019 10:52
@timkraut
Copy link
Contributor Author

timkraut commented Mar 5, 2019

I'm struggling a little bit with the support for ESLint 2 and 3. I've fixed the issue that message is missing which resulted in failing tests. ESLint 4 und 5 seem to understand the messageId property. But now newer versions of ESLint fail because I've provided both properties... Is there a way to detect the ESLint version so that I can use the new property for message (messageId) while still keep the support for old ESLint versions (message)?

It looks like the other failing tests are mostly due to the TypeScript/alternate parsers support which isn't working in ESLint 2 and 3 apparently.

I get messages like the following:

errors:
   [ TypeError: traverser.traverse is not a function
         at Object.parseForESLint (/Users/timkraut/Development/eslint-plugin-import/node_modules/typescript-eslint-parser/parser.js:41:15)
         at Object.exports.parse (/Users/timkraut/Development/eslint-plugin-import/node_modules/typescript-eslint-parser/parser.js:79:17)
         at parse (/Users/timkraut/Development/eslint-plugin-import/utils/parse.js:38:17)
         at Function.ExportMap.parse (/Users/timkraut/Development/eslint-plugin-import/src/ExportMap.js:339:15)
         at Function.ExportMap.for (/Users/timkraut/Development/eslint-plugin-import/src/ExportMap.js:323:25)
         at Function.ExportMap.get (/Users/timkraut/Development/eslint-plugin-import/src/ExportMap.js:286:10)
         at Context.<anonymous> (/Users/timkraut/Development/eslint-plugin-import/tests/src/core/getExports.js:332:31)
         at callFn (/Users/timkraut/Development/eslint-plugin-import/node_modules/mocha/lib/runnable.js:348:21)
         at Hook.Runnable.run (/Users/timkraut/Development/eslint-plugin-import/node_modules/mocha/lib/runnable.js:340:7)
         at next (/Users/timkraut/Development/eslint-plugin-import/node_modules/mocha/lib/runner.js:309:10)
         at Immediate.<anonymous> (/Users/timkraut/Development/eslint-plugin-import/node_modules/mocha/lib/runner.js:339:5)
         at processImmediate (timers.js:632:19) ],

Do you have an idea how I might fix those?

coveralls says that the test coverage decreased with this commit in the file no-cycle.js. I don't understand why this is the case as I haven't touched this file. If you have any idea, let me know.

@ljharb
Copy link
Member

ljharb commented Mar 5, 2019

@timkraut i've pulled out your chai change into a separate commit on master (it'll be pushed shortly)

If older eslints don't support messageId, let's not use it yet.

@ljharb ljharb force-pushed the no-useless-index-in-import-paths branch from 2d6c203 to f0025ec Compare March 6, 2019 06:45
@timkraut timkraut force-pushed the no-useless-index-in-import-paths branch from f0025ec to 4808942 Compare March 6, 2019 13:46
@timkraut
Copy link
Contributor Author

timkraut commented Mar 6, 2019

@ljharb I've removed the messageId property. Apparently, this was causing all the other failures. I guess from my side it's ok to be merged.

@timkraut
Copy link
Contributor Author

Is there anything else I can do to get this merged/released?

@ljharb ljharb merged commit 206d676 into import-js:master Mar 16, 2019
@timkraut timkraut deleted the no-useless-index-in-import-paths branch March 16, 2019 12:51
@timkraut
Copy link
Contributor Author

@ljharb Could you release this, too? Currently the documentation states something which isn't possible with the release from january.

@ljharb
Copy link
Member

ljharb commented Mar 20, 2019

Nope, only one person can release this package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

Proposal: disallow "index" in import paths
3 participants