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

Allow filename patterns for rule no-extraneous-dependencies. #527

Merged
merged 7 commits into from
Sep 1, 2016

Conversation

knpwrs
Copy link
Contributor

@knpwrs knpwrs commented Aug 27, 2016

Following the suggestion in #470 (comment).

Fixes #470.

@coveralls
Copy link

coveralls commented Aug 27, 2016

Coverage Status

Coverage increased (+0.008%) to 97.737% when pulling d9b9730 on knpwrs:no-extraneous-dependencies-regex into 8da6a5a on benmosher:master.

@coveralls
Copy link

coveralls commented Aug 28, 2016

Coverage Status

Coverage increased (+0.008%) to 97.737% when pulling c739798 on knpwrs:no-extraneous-dependencies-regex into 8da6a5a on benmosher:master.

"import/no-extraneous-dependencies": ["error", {"devDependencies": /test|spec/}]
```

When using a regular expression the result of running [`test`] against the name of the file being linted is used as the boolean value. For example, the above configurations will allow the import of `devDependencies` in files whose names include `test` or `spec`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

When using a regular expression --> When using a regular expression, (+ comma)

the result of running [test] against the name of the file being linted is used as the boolean value. --> the setting will be activated if the name of the file being linted matches the given regular expression.

@jfmengels
Copy link
Collaborator

jfmengels commented Aug 28, 2016

Hi @knpwrs! Thanks a lot for this, it looks great!

I'm asking myself now whether a glob configuration would not more appropriate (as we're adding minimatch in some other PR anyway), as I think it would give more control, and be easier to write than regex when things get a bit complicated. What do you think @benmosher @ljharb? If you're fine with only a regex (or waiting until requests come in and want to eventually support both regex and glob), then that's fine with me.

(sorry for being a party-pooper 😞)

@coveralls
Copy link

coveralls commented Aug 28, 2016

Coverage Status

Coverage increased (+0.008%) to 97.737% when pulling 1be4720 on knpwrs:no-extraneous-dependencies-regex into 8da6a5a on benmosher:master.

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 28, 2016

Yeah, I saw the discussion about glob vs regular expression but didn't see if it went anywhere. I could see it going either way. I've used globs for everything filename related until webpack came along.

Might be overkill, but maybe it would be worth supporting both? Would it be safe to assume that a string bookended by / and / is a regular expression? Essentially:

  • 'foo': glob (via string)
  • '/foo/': regex (via string)
  • /foo/: regex (literal, only from js configuration)
  • true or false: boolean (literal)

'peerDependencies': { 'type': 'boolean' },
'devDependencies': { 'type': ['boolean', 'string', 'object'] },
'optionalDependencies': { 'type': ['boolean', 'string', 'object'] },
'peerDependencies': { 'type': ['boolean', 'string', 'object'] },
Copy link
Collaborator

Choose a reason for hiding this comment

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

You're allowing object, because a regular expression value is an object, right? Just want confirmation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, AFAIK the schema is checked with typeof, and typeof /foo/ === 'object'.

@jfmengels
Copy link
Collaborator

jfmengels commented Aug 28, 2016

I like globs as you can decompose your allowance rules ['**/test/**.js', '*/*.test.js', '!**/fixtures/**']. Since you can do anything a regex does using this, I'd prefer this option. And having both options sounds like overkill, but why not, doesn't cost anything. But you're right that there may be a conflict in figuring out whether "test" is a glob or a regex...

And thanks for doing this, the bikeshedding may continue, but at least this is going forward :)

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 28, 2016

For two of those examples (**/test/**.js and !**/fixtures/**) I believe the current solution of a directory-level .eslintrc{,.yml,.js} is sufficient, no? The purpose this serves is for when test files live next to implementation files.

@jfmengels
Copy link
Collaborator

True, didn't think them through much ^^
But maybe you have a lot of directories in test/, each with their fixtures (or something else) subdirectory, in which the devdependency rule should be deactivated.

test/
  A/
    a.js
    a2.js
    fixtures/
      no-dev-deps.js
  B/
    b.js
    b2.js
    fixtures/
      no-dev-deps.js

If you have a lot of them, it gets tedious to add a .eslintrc file in each fixtures/ folder. You'd probably rather do that with ['**/test/**.js', '*/*.test.js', '!**/test/*/fixtures/**'].

Anyway, you'd make a clearer selection using globs than regexes IMO.

@coveralls
Copy link

coveralls commented Aug 28, 2016

Coverage Status

Coverage increased (+0.02%) to 97.745% when pulling 8ff322d on knpwrs:no-extraneous-dependencies-regex into 8da6a5a on benmosher:master.

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 28, 2016

Kaboom. No kill like overkill! Looks like everything new is covered.

"import/no-extraneous-dependencies": ["error", {"devDependencies": [/test/, '/spec/', '*.test.js', '*.spec.js']}]
```

When using an array of globs or regular expressions, the setting will be activated if the name of the file being linted matches a single glob or regular expression in the array.
Copy link
Collaborator

Choose a reason for hiding this comment

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

matches a single glob or regular expression in the array

Hmm... Not sure this part works. Globs as an array allows you to specify multiple things ['test/**/*.js', 'src/**/*.js'], but also to forbid elements allowed by previous "expressions": ['test/**/*.js', 'src/**/*.js', '!fixtures']. Here <root>/test/fixtures/a.js should not work, whereas from your docs (and guessing implementation), it would.

(This is a glob right? Or am I confusing terms?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Dang it. Back to the drawing board.

Maybe we should only support arrays for globs? But then what is excluded? Just things that contain an exclamation mark? In the case of ['*.test.js', '*.spec.js'], I'd want that to be additive. In the case of ['*.test.js', '!**/fixtures/**'], I'd want that to be subtractive.

This is approaching a point of complexity that may not be best for this plugin to handle. In your multiple test and fixture directory example we're already approaching a status of, "really, now?" At least IMHO.

A thought occurs. Maybe allow a function for configuration? Pass the name to the function and expect a boolean back. This plugin could support the most basic use cases and then people who need more complex functionality can implement it themselves.

Re: your closing question... Is what a glob? The string containing <root>? Not sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also worth noting that passing a function obviously requires a JavaScript configuration file. I think that's a reasonable requirement if somebody requires super-specific rules.

Copy link
Collaborator

Choose a reason for hiding this comment

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

['.test.js', '.spec.js'] I'd want that to be additive. In the case of ['.test.js', '!__/fixtures/*'], I'd want that to be subtractive.

That is the case. Imagine

[
  '**/*.test.js', // All the file ending with '.test.js'
  'test/**/*.js', // + All the files in test/
  '!**/fixtures/**' // Take all the files selected by the previous two selectors,
                    // and remove those in a fixtures (sub-)folder
]

This is approaching a point of complexity that may not be best for this plugin to handle.

I'm not sure I agree, but that's a subjective point a view ;)

Maybe allow a function for configuration

The function is doable, but then we're pushing the responsibility of doing the glob/regex logic to the user. I'd use functions as a last last resort.

Copy link
Member

Choose a reason for hiding this comment

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

These aren't ignore files - I don't think they need to be subtractive. There's nothing wrong with requiring people to nest .eslintrc files for things that can easily be achieved that way, but that would otherwise complicate the config.

@benmosher
Copy link
Member

having both options sounds like overkill, but why not, doesn't cost anything

I think we've found the cost of both is in the design discussion. 😅

I think it should be one or the other. There is precedent for both at this point (pending the PR @jfmengels referenced).

My gut says it should be globs, going forward, whenever we're defining configuration for sets of files. My suspicion is that one or two globs will be sufficient in 99% of the cases where this is used, i.e. [ "**/*.spec.js" ].

So, I propose that it be an array of globs, handled by minimatch, until such time as it can be shown that there is a prevalent use case that is solved well and simply by regex and not globs.

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 29, 2016

So let's say we drop regex, how do we want to handle the additive / subtractive problem with globs?

@jfmengels
Copy link
Collaborator

@knpwrs Sorry, what problem?

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 29, 2016

I'm just currently thinking in the mindset of how I implemented the array functionality using Array.prototype.some. If a single pattern matches, then the whole test passes. Simple. With globs it has to match any given pattern in the array but then if there are any patterns with exclamation marks then it has to be checked against those as well and negated. We can't use Array.prototype.every because a given file shouldn't be expected to match every pattern. Right now my initial thought is to separate the patterns into positive and negative patterns and then test positive.some(/* filename test */) && !negative.some(/* filename test */). But maybe I'm overthinking it.

@ljharb
Copy link
Member

ljharb commented Aug 29, 2016

That all seems overcomplicated. If you want to exempt a path, either use a nested .eslintrc, or write your "include" glob more precisely.

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 29, 2016

Unless there's something about glob composition I'm missing.

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 29, 2016

Right, okay, so that's going to a point I was making at #527 (comment). So is the current idea just to roll this back to nothing but matching some glob pattern?

@ljharb
Copy link
Member

ljharb commented Aug 29, 2016

That's what makes the most sense to me.

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 29, 2016

Cool, I'll knock it out when I get home. 😄

@knpwrs knpwrs changed the title Allow regular expressions for rule no-extraneous-dependencies. Allow filename patterns for rule no-extraneous-dependencies. Aug 29, 2016
@coveralls
Copy link

coveralls commented Aug 29, 2016

Coverage Status

Coverage increased (+0.007%) to 97.736% when pulling 8d16c08 on knpwrs:no-extraneous-dependencies-regex into 8da6a5a on benmosher:master.

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 30, 2016

ɯooqɐʞ

You can also use globs instead of literal booleans:

```js
"import/no-extraneous-dependencies": ["error", {"devDependencies": "*.test.js"}]
Copy link
Member

Choose a reason for hiding this comment

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

it seems like it'd be simpler to just require this to always be an array - eslint can enforce it, and that way the user would get an immediate indication that multiple globs were possible.

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, I'll go ahead and do that.

@coveralls
Copy link

coveralls commented Aug 30, 2016

Coverage Status

Coverage increased (+0.007%) to 97.736% when pulling 505aea8 on knpwrs:no-extraneous-dependencies-regex into 8da6a5a on benmosher:master.

@coveralls
Copy link

coveralls commented Aug 30, 2016

Coverage Status

Coverage increased (+0.007%) to 97.736% when pulling 2b9b500 on knpwrs:no-extraneous-dependencies-regex into 8da6a5a on benmosher:master.

@knpwrs
Copy link
Contributor Author

knpwrs commented Aug 31, 2016

How's this looking now?

@jfmengels
Copy link
Collaborator

LGTM 😄

@benmosher
Copy link
Member

:shipit:

@tristanbbq
Copy link
Contributor

@benmosher
My settings:
"import/no-extraneous-dependencies": ["error", {"devDependencies": ['*.test.js', '*.spec.js']}]

Filename: SOMETHING.test.js - still get this 'should be listed in the projects dependencies, not devDependencies' - something I'm missing here??

@benmosher
Copy link
Member

if it's deep, might need to be ['**/*.test.js'], otherwise it might only match if the file is in the CWD. not positive, though

@benmosher
Copy link
Member

if that works, let me know--we should update the example in the docs to that

@tristanbbq
Copy link
Contributor

tristanbbq commented Sep 14, 2016

@benmosher works 👍 - can confirm that glob '**/*.test.js' works but not '*.text.js'

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

Successfully merging this pull request may close these issues.

6 participants