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

Check module import validity with eslint-plugin-import #12303

Closed
wants to merge 17 commits into from

Conversation

jsnmoon
Copy link
Contributor

@jsnmoon jsnmoon commented Mar 19, 2017

(Assists #11688.)

This change adds eslint-plugin-import to our ESLint configuration. It uses either a Webpack resolver or a Node resolver depending on the path of the linted file.

This change helps us verify the validity of existing imports as well as ensuring correctness for any new imports we introduce into the project. This will be especially important as we begin migrating the client module notation from CommonJS to ES.

Todo List:

  • Correctly parse imports inside the /client/ directory
  • Correctly parse imports inside the /server/ directory
  • Correctly parse imports inside a /test/ directory

CC @ockham @aduth @ehg: Your input would be greatly appreciated!

@jsnmoon jsnmoon added [Status] In Progress [Type] Enhancement Changes to an existing feature — removing, adding, or changing parts of it labels Mar 19, 2017
@jsnmoon jsnmoon force-pushed the try/eslint-plugin-import branch 2 times, most recently from de34610 to 90f6502 Compare March 20, 2017 00:15
@jsnmoon jsnmoon force-pushed the try/eslint-plugin-import branch from 90f6502 to e85d027 Compare March 22, 2017 18:36
@oandregal
Copy link
Contributor

Howdy Jason, regarding the changes in .eslintrc: with the merge of #6945 you may set any new rules as errors. All new code will be reported as an error if it doesn't honor the rule, but the legacy code will be reported as warning, so our CI/hook tools won't complain about it.

@jsnmoon
Copy link
Contributor Author

jsnmoon commented Mar 25, 2017

Hey Andrés, thanks for the heads up! That's good to know :)

@jsnmoon jsnmoon force-pushed the try/eslint-plugin-import branch from 7c88a27 to df4944e Compare March 25, 2017 07:48
@matticbot matticbot added the [Size] M Medium sized issue label Mar 26, 2017
@jsnmoon jsnmoon force-pushed the try/eslint-plugin-import branch 2 times, most recently from c8bc0f0 to cb47d9f Compare March 27, 2017 22:10
@jsnmoon jsnmoon added [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. and removed [Status] In Progress labels Mar 27, 2017
@jsnmoon jsnmoon self-assigned this Mar 28, 2017
@matticbot matticbot added the [Size] M Medium sized issue label Mar 28, 2017
@@ -64,15 +65,7 @@ const webpackConfig = {
}
]
},
resolve: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this need to be moved to a separate config? Wouldn't it be enough to resolve using the webpack.config.js file from .eslint-resolver.js as-is?

Copy link
Contributor Author

@jsnmoon jsnmoon Apr 4, 2017

Choose a reason for hiding this comment

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

Hi @aduth, the main reason I had separated the resolve into its own separate file was due to the fact that the dependencies for webpack.config.js assumes a different root than the node paths ESLint is instantiated with. For example, webpack.config.js has lib/create-config, which is a dependency in the client folder; ESLint can't easily resolve this. (An easy way to repro this: node -e "var config = require('./webpack.config');")

I don't know of an easy way to modify the node paths for ESLint, which is why I decided to separate the resolve configs to a new file.


exports.interfaceVersion = 2

exports.resolve = function (source, file, config) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Ironically your ESLint resolver script has many lint errors 😄 (spacing after function, between parens).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

D'oh! 😅

Copy link
Contributor Author

@jsnmoon jsnmoon Apr 4, 2017

Choose a reason for hiding this comment

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

I realized that ESLint was ignoring the file due to the .eslint prefix. I went ahead and changed .eslintignore to force parsing .eslint-resolver.js so this shouldn't happen again.

*/
const log = debugFactory('eslint-plugin-import:resolver:wp-calypso-resolver');

const nodeResolverConfig = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you explain the need for separate resolving configs? Should this be pulled from webpack.config.node.js for server-side module importing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure - the reason why we need separate resolving configs is due to how files across our project assume a different root directory. For client files, this includes /client/
and /client/extensions/; for server files, this includes /, /client/, and /server/. Test files tend to add /test/ as a root directory as well.

I do think it should be pulling from webpack.config.node.js for server-side module importing. I'll push out a revision to address this shortly.

/* eslint-disable import/no-commonjs */

const path = require( 'path' );
const customResolverPath = path.join( __dirname, './.eslint-resolver.js' );
Copy link
Contributor

Choose a reason for hiding this comment

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

Won't the result of this join be simply "./.eslint-resolver.js" which we could instead define as a string key of the settings, not a computed property?

Copy link
Contributor Author

@jsnmoon jsnmoon Mar 30, 2017

Choose a reason for hiding this comment

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

Yes, you're absolutely correct. I'll fix this.

EDIT: I initially thought this was the case, but I overlooked the fact that the result of path.join is the absolute path of the resolver file (e.g. /Users/myUsername/wp-calypso/.eslint-resolver.js). Unless an absolute path is specified as the Object key, CircleCI fails to run run-lint properly.

.eslintrc.js Outdated
rules: {
camelcase: 0, // REST API objects include underscores
// NOTE: Some import rules are errors in client (Webpack's resolution) and
// warnings in server (Node's module resolution).
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't we still define these all as errors and expect the server-specific configuration to override them?

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, we can define all of these rules as errors and override them inside server/.eslintrc.json. The following rules are already overridden for the server:

  • Set to warn:
    • import/default
    • import/export
    • import/named
    • import/namespace
  • Set to ignore:
    - import/no-commonjs

Which rules would you recommend upgrading to error in .eslintrc.js? The following rules are currently set as warnings for the client:

  • import/no-commonjs
  • import/no-named-as-default-member
  • import/no-named-as-default
  • import/no-webpack-loader-syntax

index.js Outdated
@@ -1,4 +1,5 @@
/* eslint-disable no-console */
/* eslint-disable import/no-commonjs */
Copy link
Contributor

Choose a reason for hiding this comment

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

FYI you can comma-separate disabled rules in a single eslint-disable comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it 👍

@matticbot matticbot added [Size] L Large sized issue and removed [Size] M Medium sized issue labels Apr 4, 2017
@jsnmoon jsnmoon force-pushed the try/eslint-plugin-import branch from a236882 to 5fa8734 Compare April 4, 2017 04:37
@jsnmoon jsnmoon requested review from ockham and ehg April 4, 2017 19:51
@jsnmoon jsnmoon requested a review from oandregal April 4, 2017 20:35
@matticbot
Copy link
Contributor

@jsnmoon This PR needs a rebase

@jsnmoon
Copy link
Contributor Author

jsnmoon commented Jul 25, 2017

Given that we're beginning to rely more in Prettier, I think we can put this PR on hold indefinitely for now. I'll leave the branch alive for anyone who'd like to use this as a reference to integrate import path resolution with ESLint.

@jsnmoon jsnmoon closed this Jul 25, 2017
@matticbot matticbot removed the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Jul 25, 2017
@alisterscott alisterscott deleted the try/eslint-plugin-import branch October 16, 2017 03:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Build OSS Citizen [Size] L Large sized issue [Status] Needs Rebase [Type] Enhancement Changes to an existing feature — removing, adding, or changing parts of it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants