-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[New] add
no-import-module-exports
rule: report import declarations…
… with CommonJS exports Fixes #760
- Loading branch information
Showing
8 changed files
with
250 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# no-import-module-exports | ||
|
||
Reports the use of import declarations with CommonJS exports in any module | ||
except for the [main module](https://docs.npmjs.com/files/package.json#main). | ||
|
||
If you have multiple entry points or are using `js:next` this rule includes an | ||
`exceptions` option which you can use to exclude those files from the rule. | ||
|
||
## Options | ||
|
||
#### `exceptions` | ||
- An array of globs. The rule will be omitted from any file that matches a glob | ||
in the options array. For example, the following setting will omit the rule | ||
in the `some-file.js` file. | ||
|
||
```json | ||
"import/no-import-module-exports": ["error", { | ||
"exceptions": ["**/*/some-file.js"] | ||
}] | ||
``` | ||
|
||
## Rule Details | ||
|
||
### Fail | ||
|
||
```js | ||
import { stuff } from 'starwars' | ||
module.exports = thing | ||
|
||
import * as allThings from 'starwars' | ||
exports.bar = thing | ||
|
||
import thing from 'other-thing' | ||
exports.foo = bar | ||
|
||
import thing from 'starwars' | ||
const baz = module.exports = thing | ||
console.log(baz) | ||
``` | ||
|
||
### Pass | ||
Given the following package.json: | ||
|
||
```json | ||
{ | ||
"main": "lib/index.js", | ||
} | ||
``` | ||
|
||
```js | ||
import thing from 'other-thing' | ||
export default thing | ||
|
||
const thing = require('thing') | ||
module.exports = thing | ||
|
||
const thing = require('thing') | ||
exports.foo = bar | ||
|
||
import thing from 'otherthing' | ||
console.log(thing.module.exports) | ||
|
||
// in lib/index.js | ||
import foo from 'path'; | ||
module.exports = foo; | ||
|
||
// in some-file.js | ||
// eslint import/no-import-module-exports: ["error", {"exceptions": ["**/*/some-file.js"]}] | ||
import foo from 'path'; | ||
module.exports = foo; | ||
``` | ||
|
||
### Further Reading | ||
- [webpack issue #4039](https://github.com/webpack/webpack/issues/4039) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import minimatch from 'minimatch' | ||
import path from 'path' | ||
import pkgUp from 'pkg-up' | ||
|
||
function getEntryPoint(context) { | ||
const pkgPath = pkgUp.sync(context.getFilename()) | ||
return require.resolve(path.dirname(pkgPath)) | ||
} | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: 'Disallow import statements with module.exports', | ||
category: 'Best Practices', | ||
recommended: true, | ||
}, | ||
fixable: 'code', | ||
schema: [ | ||
{ | ||
'type': 'object', | ||
'properties': { | ||
'exceptions': { 'type': 'array' }, | ||
}, | ||
'additionalProperties': false, | ||
}, | ||
], | ||
}, | ||
create(context) { | ||
const importDeclarations = [] | ||
const entryPoint = getEntryPoint(context) | ||
const options = context.options[0] || {} | ||
let alreadyReported = false | ||
|
||
function report(node) { | ||
const fileName = context.getFilename() | ||
const isEntryPoint = entryPoint === fileName | ||
const isIdentifier = node.object.type === 'Identifier' | ||
const hasKeywords = (/^(module|exports)$/).test(node.object.name) | ||
const isException = options.exceptions && | ||
options.exceptions.some(glob => minimatch(fileName, glob)) | ||
|
||
if (isIdentifier && hasKeywords && !isEntryPoint && !isException) { | ||
importDeclarations.forEach(importDeclaration => { | ||
context.report({ | ||
node: importDeclaration, | ||
message: `Cannot use import declarations in modules that export using ` + | ||
`CommonJS (module.exports = 'foo' or exports.bar = 'hi')`, | ||
}) | ||
}) | ||
alreadyReported = true | ||
} | ||
} | ||
|
||
return { | ||
ImportDeclaration(node) { | ||
importDeclarations.push(node) | ||
}, | ||
MemberExpression(node) { | ||
if (!alreadyReported) { | ||
report(node) | ||
} | ||
}, | ||
} | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
{ | ||
"dummy": true, | ||
"main": "src-root/src-bar.js", | ||
"devDependencies": { | ||
"glob": "1.0.0", | ||
"eslint": "2.x" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import path from 'path' | ||
import { RuleTester } from 'eslint' | ||
|
||
import { test, testFilePath } from '../utils' | ||
|
||
const ruleTester = new RuleTester({ | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' } | ||
}) | ||
const rule = require('rules/no-import-module-exports') | ||
|
||
const error = { | ||
message: `Cannot use import declarations in modules that export using CommonJS ` + | ||
`(module.exports = 'foo' or exports.bar = 'hi')`, | ||
type: 'ImportDeclaration', | ||
} | ||
|
||
ruleTester.run('no-import-module-exports', rule, { | ||
valid: [ | ||
test({ | ||
code: ` | ||
const thing = require('thing') | ||
module.exports = thing | ||
`, | ||
}), | ||
test({ | ||
code: ` | ||
import thing from 'otherthing' | ||
console.log(thing.module.exports) | ||
`, | ||
}), | ||
test({ | ||
code: ` | ||
import thing from 'other-thing' | ||
export default thing | ||
`, | ||
}), | ||
test({ | ||
code: ` | ||
const thing = require('thing') | ||
exports.foo = bar | ||
`, | ||
}), | ||
test({ | ||
code: ` | ||
import foo from 'path'; | ||
module.exports = foo; | ||
`, | ||
// When the file matches the entry point defined in package.json | ||
// See tests/files/package.json | ||
filename: path.join(process.cwd(), 'tests/files/src-root/src-bar.js'), | ||
}), | ||
test({ | ||
code: ` | ||
import foo from 'path'; | ||
module.exports = foo; | ||
`, | ||
filename: path.join(process.cwd(), 'tests/files/some/other/entry-point.js'), | ||
options: [{ exceptions: ['**/*/other/entry-point.js'] }], | ||
}), | ||
], | ||
invalid: [ | ||
test({ | ||
code: ` | ||
import { stuff } from 'starwars' | ||
module.exports = thing | ||
`, | ||
errors: [error], | ||
}), | ||
test({ | ||
code: ` | ||
import thing from 'starwars' | ||
const baz = module.exports = thing | ||
console.log(baz) | ||
`, | ||
errors: [error], | ||
}), | ||
test({ | ||
code: ` | ||
import * as allThings from 'starwars' | ||
exports.bar = thing | ||
`, | ||
errors: [error], | ||
}), | ||
test({ | ||
code: ` | ||
import thing from 'other-thing' | ||
exports.foo = bar | ||
`, | ||
errors: [error], | ||
}), | ||
test({ | ||
code: ` | ||
import foo from 'path'; | ||
module.exports = foo; | ||
`, | ||
filename: path.join(process.cwd(), 'tests/files/some/other/entry-point.js'), | ||
options: [{ exceptions: ['**/*/other/file.js'] }], | ||
errors: [error], | ||
}), | ||
], | ||
}) |