Skip to content

Commit feec4d2

Browse files
committed
no-extraneous-dependencies: add support/option for optionalDependencies (fixes import-js#266)
1 parent c74d97d commit feec4d2

File tree

5 files changed

+73
-19
lines changed

5 files changed

+73
-19
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
66
## [Unreleased]
77
### Added
88
- [`newline-after-import`], new rule. ([#245], thanks [@singles])
9+
- Added an `optionalDependencies` option to [`no-extraneous-dependencies`] to allow/forbid optional dependencies ([#266], thanks [@jfmengels]).
910

1011
## resolvers/webpack/0.2.4 - 2016-04-29
1112
### Changed
@@ -210,6 +211,7 @@ for info on changes for earlier releases.
210211
[#286]: https://github.com/benmosher/eslint-plugin-import/issues/286
211212
[#281]: https://github.com/benmosher/eslint-plugin-import/issues/281
212213
[#272]: https://github.com/benmosher/eslint-plugin-import/issues/272
214+
[#266]: https://github.com/benmosher/eslint-plugin-import/issues/266
213215
[#216]: https://github.com/benmosher/eslint-plugin-import/issues/216
214216
[#214]: https://github.com/benmosher/eslint-plugin-import/issues/214
215217
[#210]: https://github.com/benmosher/eslint-plugin-import/issues/210

docs/rules/no-extraneous-dependencies.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ The closest parent `package.json` will be used. If no `package.json` is found, t
88
This rule supports the following options:
99

1010
`devDependencies`: If set to `false`, then the rule will show an error when `devDependencies` are imported. Defaults to `true`.
11+
`optionalDependencies`: If set to `false`, then the rule will show an error when `optionalDependencies` are imported. Defaults to `true`.
1112

1213
You can set the options like this:
1314

1415
```js
15-
"import/no-extraneous-dependencies": ["error", {"devDependencies": false}]
16+
"import/no-extraneous-dependencies": ["error", {"devDependencies": false, "optionalDependencies": false}]
1617
```
1718

1819

@@ -34,6 +35,9 @@ Given the following `package.json`:
3435
"eslint": "^2.4.0",
3536
"eslint-plugin-ava": "^1.3.0",
3637
"xo": "^0.13.0"
38+
},
39+
"optionalDependencies": {
40+
"lodash.isarray": "^4.0.0"
3741
}
3842
}
3943
```
@@ -48,6 +52,10 @@ import _ from 'lodash';
4852
/* eslint import/no-extraneous-dependencies: ["error", {"devDependencies": false}] */
4953
import test from 'ava';
5054
var test = require('ava');
55+
56+
/* eslint import/no-extraneous-dependencies: ["error", {"optionalDependencies": false}] */
57+
import isArray from 'lodash.isarray';
58+
var isArray = require('lodash.isarray');
5159
```
5260

5361

@@ -60,6 +68,7 @@ var foo = require('./foo');
6068

6169
import test from 'ava';
6270
import find from 'lodash.find';
71+
import find from 'lodash.isarray';
6372
```
6473

6574

src/rules/no-extraneous-dependencies.js

+35-12
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,61 @@ function getDependencies(context) {
1414
return {
1515
dependencies: packageContent.dependencies || {},
1616
devDependencies: packageContent.devDependencies || {},
17+
optionalDependencies: packageContent.optionalDependencies || {},
1718
}
1819
} catch (e) {
1920
return null
2021
}
2122
}
2223

2324
function missingErrorMessage(packageName) {
24-
return `'${packageName}' is not listed in the project's dependencies. ` +
25-
`Run 'npm i -S ${packageName}' to add it`
25+
return `'${packageName}' should be listed in the project's dependencies. ` +
26+
`Run 'npm i -S ${packageName}' to add it`
2627
}
2728

2829
function devDepErrorMessage(packageName) {
29-
return `'${packageName}' is not listed in the project's dependencies, not devDependencies.`
30+
return `'${packageName}' should be listed in the project's dependencies, not devDependencies.`
3031
}
3132

32-
function reportIfMissing(context, deps, allowDevDeps, node, name) {
33+
function optDepErrorMessage(packageName) {
34+
return `'${packageName}' should be listed in the project's dependencies, ` +
35+
`not optionalDependencies.`
36+
}
37+
38+
function reportIfMissing(context, deps, allowDevDeps, allowOptDeps, node, name) {
3339
if (importType(name, context) !== 'external') {
3440
return
3541
}
3642
const packageName = name.split('/')[0]
3743

38-
if (deps.dependencies[packageName] === undefined) {
39-
if (!allowDevDeps) {
40-
context.report(node, devDepErrorMessage(packageName))
41-
} else if (deps.devDependencies[packageName] === undefined) {
42-
context.report(node, missingErrorMessage(packageName))
43-
}
44+
const isInDeps = deps.dependencies[packageName] !== undefined
45+
const isInDevDeps = deps.devDependencies[packageName] !== undefined
46+
const isInOptDeps = deps.optionalDependencies[packageName] !== undefined
47+
48+
if (isInDeps ||
49+
(allowDevDeps && isInDevDeps) ||
50+
(allowOptDeps && isInOptDeps)
51+
) {
52+
return
53+
}
54+
55+
if (isInDevDeps && !allowDevDeps) {
56+
context.report(node, devDepErrorMessage(packageName))
57+
return
58+
}
59+
60+
if (isInOptDeps && !allowOptDeps) {
61+
context.report(node, optDepErrorMessage(packageName))
62+
return
4463
}
64+
65+
context.report(node, missingErrorMessage(packageName))
4566
}
4667

4768
module.exports = function (context) {
4869
const options = context.options[0] || {}
4970
const allowDevDeps = options.devDependencies !== false
71+
const allowOptDeps = options.optionalDependencies !== false
5072
const deps = getDependencies(context)
5173

5274
if (!deps) {
@@ -56,11 +78,11 @@ module.exports = function (context) {
5678
// todo: use module visitor from module-utils core
5779
return {
5880
ImportDeclaration: function (node) {
59-
reportIfMissing(context, deps, allowDevDeps, node, node.source.value)
81+
reportIfMissing(context, deps, allowDevDeps, allowOptDeps, node, node.source.value)
6082
},
6183
CallExpression: function handleRequires(node) {
6284
if (isStaticRequire(node)) {
63-
reportIfMissing(context, deps, allowDevDeps, node, node.arguments[0].value)
85+
reportIfMissing(context, deps, allowDevDeps, allowOptDeps, node, node.arguments[0].value)
6486
}
6587
},
6688
}
@@ -71,6 +93,7 @@ module.exports.schema = [
7193
'type': 'object',
7294
'properties': {
7395
'devDependencies': { 'type': 'boolean' },
96+
'optionalDependencies': { 'type': 'boolean' },
7497
},
7598
'additionalProperties': false,
7699
},

tests/files/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@
99
"dependencies": {
1010
"lodash.cond": "^4.3.0",
1111
"pkg-up": "^1.0.0"
12+
},
13+
"optionalDependencies": {
14+
"lodash.isarray": "^4.0.0"
1215
}
1316
}

tests/src/rules/no-extraneous-dependencies.js

+23-6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
2020
test({ code: 'var foo = require("pkg-up")'}),
2121
test({ code: 'import "fs"'}),
2222
test({ code: 'import "./foo"'}),
23+
test({ code: 'import "lodash.isarray"'}),
2324

2425
// 'project' type
2526
test({
@@ -32,30 +33,46 @@ ruleTester.run('no-extraneous-dependencies', rule, {
3233
code: 'import "not-a-dependency"',
3334
errors: [{
3435
ruleId: 'no-extraneous-dependencies',
35-
message: '\'not-a-dependency\' is not listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
36+
message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
3637
}],
3738
}),
3839
test({
3940
code: 'import "eslint"',
4041
options: [{devDependencies: false}],
4142
errors: [{
4243
ruleId: 'no-extraneous-dependencies',
43-
message: '\'eslint\' is not listed in the project\'s dependencies, not devDependencies.',
44+
message: '\'eslint\' should be listed in the project\'s dependencies, not devDependencies.',
4445
}],
4546
}),
4647
test({
47-
code: 'var foo = require("not-a-dependency");',
48+
code: 'import "lodash.isarray"',
49+
options: [{optionalDependencies: false}],
4850
errors: [{
4951
ruleId: 'no-extraneous-dependencies',
50-
message: '\'not-a-dependency\' is not listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
52+
message: '\'lodash.isarray\' should be listed in the project\'s dependencies, not optionalDependencies.',
5153
}],
5254
}),
5355
test({
54-
code: 'var eslint = require("eslint");',
56+
code: 'var foo = require("not-a-dependency")',
57+
errors: [{
58+
ruleId: 'no-extraneous-dependencies',
59+
message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
60+
}],
61+
}),
62+
test({
63+
code: 'var eslint = require("eslint")',
5564
options: [{devDependencies: false}],
5665
errors: [{
5766
ruleId: 'no-extraneous-dependencies',
58-
message: '\'eslint\' is not listed in the project\'s dependencies, not devDependencies.',
67+
message: '\'eslint\' should be listed in the project\'s dependencies, not devDependencies.',
68+
}],
69+
}),
70+
test({
71+
code: 'var eslint = require("lodash.isarray")',
72+
options: [{optionalDependencies: false}],
73+
errors: [{
74+
ruleId: 'no-extraneous-dependencies',
75+
message: '\'lodash.isarray\' should be listed in the project\'s dependencies, not optionalDependencies.',
5976
}],
6077
}),
6178
],

0 commit comments

Comments
 (0)