diff --git a/.eslintrc.yml b/.eslintrc.yml index e32fffe384..f14ffb6e80 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,11 +1,17 @@ --- -extends: eslint:recommended +extends: + - eslint:recommended + - plugin:import/errors + - plugin:import/warnings + env: node: true es6: true + parserOptions: sourceType: module ecmaVersion: 6 + rules: max-len: [1, 99, 2] semi: [2, "never"] @@ -17,3 +23,8 @@ rules: - 2 - single - allowTemplateLiterals: true + +settings: + import/resolver: + node: + paths: [ src ] diff --git a/.gitignore b/.gitignore index 00d37364ef..24ceac8ff2 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,4 @@ node_modules # generated output lib/ -/.nyc_output/ +**/.nyc_output/ diff --git a/.travis.yml b/.travis.yml index aae667d50f..81cf39c233 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - 0.10 + # - 0.10 # testing locally only for 0.10 (nyc fails) # - 0.12 # assume 0.12 works if 0.10 does. - 4 - 6 diff --git a/CHANGELOG.md b/CHANGELOG.md index 572b33d0b9..9013c8dbd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel ## [Unreleased] +## [1.11.0] - 2016-07-17 +### Added +- Added an `peerDependencies` option to [`no-extraneous-dependencies`] to allow/forbid peer dependencies ([#423], [#428], thanks [@jfmengels]!). + +### Fixed +- [`newline-after-import`] exception for multiple `require`s in an arrow + function expression (e.g. `() => require('a') || require('b')`). ([#441], thanks [@ljharb]) ## [1.10.3] - 2016-07-08 ### Fixed @@ -252,6 +259,7 @@ for info on changes for earlier releases. [`prefer-default-export`]: ./docs/rules/prefer-default-export.md [`no-restricted-paths`]: ./docs/rules/no-restricted-paths.md +[#428]: https://github.com/benmosher/eslint-plugin-import/pull/428 [#395]: https://github.com/benmosher/eslint-plugin-import/pull/395 [#371]: https://github.com/benmosher/eslint-plugin-import/pull/371 [#365]: https://github.com/benmosher/eslint-plugin-import/pull/365 @@ -285,6 +293,8 @@ for info on changes for earlier releases. [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157 [#314]: https://github.com/benmosher/eslint-plugin-import/pull/314 +[#441]: https://github.com/benmosher/eslint-plugin-import/issues/441 +[#423]: https://github.com/benmosher/eslint-plugin-import/issues/423 [#415]: https://github.com/benmosher/eslint-plugin-import/issues/415 [#386]: https://github.com/benmosher/eslint-plugin-import/issues/386 [#373]: https://github.com/benmosher/eslint-plugin-import/issues/373 @@ -313,7 +323,8 @@ for info on changes for earlier releases. [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89 -[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v1.10.3...HEAD +[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v1.11.0...HEAD +[1.11.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.10.3...v1.11.0 [1.10.3]: https://github.com/benmosher/eslint-plugin-import/compare/v1.10.2...v1.10.3 [1.10.2]: https://github.com/benmosher/eslint-plugin-import/compare/v1.10.1...v1.10.2 [1.10.1]: https://github.com/benmosher/eslint-plugin-import/compare/v1.10.0...v1.10.1 diff --git a/README.md b/README.md index 34b2024667..f3e3c39109 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # eslint-plugin-import [![build status](https://travis-ci.org/benmosher/eslint-plugin-import.svg?branch=master)](https://travis-ci.org/benmosher/eslint-plugin-import) -[![Coverage Status](https://coveralls.io/repos/benmosher/eslint-plugin-import/badge.svg?branch=master&service=github)](https://coveralls.io/github/benmosher/eslint-plugin-import?branch=coverage) +[![Coverage Status](https://coveralls.io/repos/github/benmosher/eslint-plugin-import/badge.svg?branch=master)](https://coveralls.io/github/benmosher/eslint-plugin-import?branch=master) [![win32 build status](https://ci.appveyor.com/api/projects/status/3mw2fifalmjlqf56/branch/master?svg=true)](https://ci.appveyor.com/project/benmosher/eslint-plugin-import/branch/master) [![npm](https://img.shields.io/npm/v/eslint-plugin-import.svg)](https://www.npmjs.com/package/eslint-plugin-import) diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md index 2504c0320c..9f83d496b9 100644 --- a/docs/rules/no-extraneous-dependencies.md +++ b/docs/rules/no-extraneous-dependencies.md @@ -1,6 +1,6 @@ # Forbid the use of extraneous packages -Forbid the import of external modules that are not declared in the `package.json`'s `dependencies` or `devDependencies`. +Forbid the import of external modules that are not declared in the `package.json`'s `dependencies`, `devDependencies`, `optionalDependencies` or `peerDependencies`. The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. ### Options @@ -9,11 +9,12 @@ This rule supports the following options: `devDependencies`: If set to `false`, then the rule will show an error when `devDependencies` are imported. Defaults to `true`. `optionalDependencies`: If set to `false`, then the rule will show an error when `optionalDependencies` are imported. Defaults to `true`. +`peerDependencies`: If set to `false`, then the rule will show an error when `peerDependencies` are imported. Defaults to `false`. You can set the options like this: ```js -"import/no-extraneous-dependencies": ["error", {"devDependencies": false, "optionalDependencies": false}] +"import/no-extraneous-dependencies": ["error", {"devDependencies": false, "optionalDependencies": false, "peerDependencies": false}] ``` @@ -38,6 +39,9 @@ Given the following `package.json`: }, "optionalDependencies": { "lodash.isarray": "^4.0.0" + }, + "peerDependencies": { + "react": ">=15.0.0 <16.0.0" } } ``` @@ -49,6 +53,8 @@ Given the following `package.json`: var _ = require('lodash'); import _ from 'lodash'; +import react from 'react'; + /* eslint import/no-extraneous-dependencies: ["error", {"devDependencies": false}] */ import test from 'ava'; var test = require('ava'); @@ -69,6 +75,9 @@ var foo = require('./foo'); import test from 'ava'; import find from 'lodash.find'; import find from 'lodash.isarray'; + +/* eslint import/no-extraneous-dependencies: ["error", {"peerDependencies": true}] */ +import react from 'react'; ``` diff --git a/import.sublime-project b/import.sublime-project index 92fe2e1dfd..2db05e0164 100644 --- a/import.sublime-project +++ b/import.sublime-project @@ -5,5 +5,15 @@ "path": ".", "folder_exclude_patterns": ["reports", "node_modules", "lib"] } - ] + ], + "SublimeLinter": + { + "linters": + { + "eslint": + { + "chdir": "${project}/" + } + } + } } diff --git a/package.json b/package.json index 2e45a5954a..13a9b5eacf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-import", - "version": "1.10.3", + "version": "1.11.0", "description": "Import with sanity.", "main": "lib/index.js", "directories": { @@ -15,7 +15,8 @@ "watch": "cross-env NODE_PATH=./lib gulp watch-test", "cover": "gulp pretest && cross-env NODE_PATH=./lib istanbul cover --dir reports/coverage _mocha tests/lib/ -- --recursive -R progress", "posttest": "eslint ./src", - "test": "cross-env BABEL_ENV=test NODE_PATH=./src nyc mocha --recursive tests/src -R progress -t 5s", + "test": "cross-env BABEL_ENV=test NODE_PATH=./src nyc mocha --recursive tests/src -t 5s", + "test-compiled": "npm run prepublish && NODE_PATH=./lib mocha --compilers js:babel-register --recursive tests/src", "coverage-report": "npm t && nyc report --reporter html", "test-all": "npm test && for resolver in ./resolvers/*; do cd $resolver && npm test && cd ../..; done", "ci-test": "eslint ./src && gulp pretest && cross-env NODE_PATH=./lib istanbul cover --report lcovonly --dir reports/coverage _mocha tests/lib/ -- --recursive --reporter dot", @@ -50,8 +51,9 @@ "babel-register": "6.9.0", "chai": "^3.4.0", "coveralls": "^2.11.4", - "cross-env": "^1.0.7", + "cross-env": "^2.0.0", "eslint": "2.x", + "eslint-plugin-import": "next", "eslint-import-resolver-node": "file:./resolvers/node", "eslint-import-resolver-webpack": "file:./resolvers/webpack", "gulp": "^3.9.0", diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md index 3dc191bb71..5838849712 100644 --- a/resolvers/node/CHANGELOG.md +++ b/resolvers/node/CHANGELOG.md @@ -3,6 +3,21 @@ All notable changes to this resolver will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com). +## v0.2.2 - 2016-07-14 +### Fixed +- Node resolver no longer declares the import plugin as a `peerDependency`. See [#437] + for a well-articulated and thoughtful expression of why this doesn't make sense. + Thanks [@jasonkarns] for the issue and the PR to fix it ([#438]). + + Also, apologies to the others who expressed this before, but I never understood + what the problem was.😅 + ## v0.2.1 ### Fixed - find files with `.json` extensions (#333, thanks for noticing @jfmengels) + +[#438]: https://github.com/benmosher/eslint-plugin-import/pull/438 + +[#437]: https://github.com/benmosher/eslint-plugin-import/issues/437 + +[@jasonkarns]: https://github.com/jasonkarns diff --git a/resolvers/node/package.json b/resolvers/node/package.json index c61ce63580..3cdb79b24b 100644 --- a/resolvers/node/package.json +++ b/resolvers/node/package.json @@ -1,10 +1,10 @@ { "name": "eslint-import-resolver-node", - "version": "0.2.1", + "version": "0.2.2", "description": "Node default behavior import resolution plugin for eslint-plugin-import.", "main": "index.js", "scripts": { - "test": "mocha" + "test": "nyc mocha" }, "repository": { "type": "git", @@ -27,11 +27,9 @@ "object-assign": "^4.0.1", "resolve": "^1.1.6" }, - "peerDependencies": { - "eslint-plugin-import": ">=1.4.0" - }, "devDependencies": { "chai": "^3.4.1", - "mocha": "^2.3.4" + "mocha": "^2.3.4", + "nyc": "^7.0.0" } } diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md index 32c657a10b..b88a2a2b7e 100644 --- a/resolvers/webpack/CHANGELOG.md +++ b/resolvers/webpack/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this resolver will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com). +## Unreleased +### Changed +- don't swallow errors, assume config exists ([#435], thanks [@Kovensky]) + +## 0.4.0 - 2016-07-17 +### Added +- support for `webpack.ResolverPlugin` ([#377], thanks [@Rogeres]) + +### Fixed +- provide string `context` to `externals` functions ([#411] + [#413], thanks [@Satyam]) + ## 0.3.2 - 2016-06-30 ### Added - shared config ([config.js](./config.js)) with barebones settings needed to use this resolver. ([#283]) @@ -38,6 +49,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel - `interpret` configs (such as `.babel.js`). Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]). +[#413]: https://github.com/benmosher/eslint-plugin-import/pull/413 +[#377]: https://github.com/benmosher/eslint-plugin-import/pull/377 [#363]: https://github.com/benmosher/eslint-plugin-import/pull/363 [#289]: https://github.com/benmosher/eslint-plugin-import/pull/289 [#287]: https://github.com/benmosher/eslint-plugin-import/pull/287 @@ -45,6 +58,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel [#181]: https://github.com/benmosher/eslint-plugin-import/pull/181 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164 +[#435]: https://github.com/benmosher/eslint-plugin-import/issues/435 +[#411]: https://github.com/benmosher/eslint-plugin-import/issues/411 [#357]: https://github.com/benmosher/eslint-plugin-import/issues/357 [#286]: https://github.com/benmosher/eslint-plugin-import/issues/286 [#283]: https://github.com/benmosher/eslint-plugin-import/issues/283 @@ -55,3 +70,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel [@GreenGremlin]: https://github.com/GreenGremlin [@daltones]: https://github.com/daltones [@kesne]: https://github.com/kesne +[@Satyam]: https://github.com/Satyam +[@Rogeres]: https://github.com/Rogeres +[@Kovensky]: https://github.com/Kovensky diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 2e2d8becd4..611bb4935f 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -8,7 +8,7 @@ var findRoot = require('find-root') , fs = require('fs') , coreLibs = require('node-libs-browser') -const log = require('debug')('eslint-plugin-import:resolver:webpack') +var log = require('debug')('eslint-plugin-import:resolver:webpack') exports.interfaceVersion = 2 @@ -42,32 +42,27 @@ exports.resolve = function (source, file, settings) { var webpackConfig - try { - var configPath = get(settings, 'config') - , configIndex = get(settings, 'config-index') - , packageDir + var configPath = get(settings, 'config') + , configIndex = get(settings, 'config-index') + , packageDir - if (configPath) log('Config path from settings:', configPath) + log('Config path from settings:', configPath) - // see if we've got an absolute path - if (!configPath || !isAbsolute(configPath)) { - // if not, find ancestral package.json and use its directory as base for the path - packageDir = findRoot(path.resolve(file)) - if (!packageDir) throw new Error('package not found above ' + file) - } + // see if we've got an absolute path + if (!configPath || !isAbsolute(configPath)) { + // if not, find ancestral package.json and use its directory as base for the path + packageDir = findRoot(path.resolve(file)) + if (!packageDir) throw new Error('package not found above ' + file) + } - configPath = findConfigPath(configPath, packageDir) + configPath = findConfigPath(configPath, packageDir) - log('Config path resolved to:', configPath) - webpackConfig = require(configPath) + log('Config path resolved to:', configPath) + webpackConfig = require(configPath) - if (webpackConfig && webpackConfig.default) { - log('Using ES6 module "default" key instead of module.exports.') - webpackConfig = webpackConfig.default - } - } catch (err) { - log('Error during config lookup:', err) - webpackConfig = {} + if (webpackConfig && webpackConfig.default) { + log('Using ES6 module "default" key instead of module.exports.') + webpackConfig = webpackConfig.default } if (Array.isArray(webpackConfig)) { @@ -84,11 +79,21 @@ exports.resolve = function (source, file, settings) { log('Using config: ', webpackConfig) // externals - if (findExternal(source, webpackConfig.externals)) return { found: true, path: null } + if (findExternal(source, webpackConfig.externals, path.dirname(file))) return { found: true, path: null } + var otherPlugins = [] + + // support webpack.ResolverPlugin + if (webpackConfig.plugins) { + webpackConfig.plugins.forEach(function (plugin) { + if (plugin.constructor && plugin.constructor.name === 'ResolverPlugin' && Array.isArray(plugin.plugins)) { + otherPlugins.push.apply(otherPlugins, plugin.plugins); + } + }); + } // otherwise, resolve "normally" - var resolver = createResolver(webpackConfig.resolve || {}) + var resolver = createResolver(webpackConfig.resolve || {}, otherPlugins) try { return { found: true, path: resolver.resolveSync(path.dirname(file), source) } } catch (err) { @@ -116,7 +121,7 @@ var DirectoryDescriptionFileFieldAliasPlugin = // adapted from tests & // https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L322 -function createResolver(resolve) { +function createResolver(resolve, otherPlugins) { var resolver = new Resolver(syncFS) resolver.apply( @@ -135,6 +140,8 @@ function createResolver(resolve) { new ResultSymlinkPlugin() ) + resolver.apply.apply(resolver, otherPlugins); + return resolver } @@ -154,7 +161,7 @@ function makeRootPlugin(name, root) { } /* eslint-enable */ -function findExternal(source, externals) { +function findExternal(source, externals, context) { if (!externals) return false // string match @@ -162,7 +169,7 @@ function findExternal(source, externals) { // array: recurse if (externals instanceof Array) { - return externals.some(function (e) { return findExternal(source, e) }) + return externals.some(function (e) { return findExternal(source, e, context) }) } if (externals instanceof RegExp) { @@ -171,11 +178,11 @@ function findExternal(source, externals) { if (typeof externals === 'function') { var functionExternalFound = false - externals.call(null, null, source, function(err, value) { + externals.call(null, context, source, function(err, value) { if (err) { functionExternalFound = false } else { - functionExternalFound = findExternal(source, value) + functionExternalFound = findExternal(source, value, context) } }) return functionExternalFound diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json index 2b3b371a1f..0b7768dc5c 100644 --- a/resolvers/webpack/package.json +++ b/resolvers/webpack/package.json @@ -1,10 +1,11 @@ { "name": "eslint-import-resolver-webpack", - "version": "0.3.2", + "version": "0.4.0", "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.", "main": "index.js", "scripts": { - "test": "mocha" + "test": "nyc mocha -t 5s", + "report": "nyc report --reporter=html" }, "repository": { "type": "git", @@ -38,6 +39,7 @@ }, "devDependencies": { "chai": "^3.4.1", - "mocha": "^2.3.3" + "mocha": "^2.3.3", + "nyc": "^7.0.0" } } diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js index 1d00bf4876..bb448c426c 100644 --- a/resolvers/webpack/test/config.js +++ b/resolvers/webpack/test/config.js @@ -16,6 +16,7 @@ describe("config", function () { expect(resolve('main-module', file)).to.have.property('path') .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js')) }) + it("finds absolute webpack.config.js files", function () { expect(resolve('foo', file, absoluteSettings)).to.have.property('path') .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js')) @@ -55,4 +56,11 @@ describe("config", function () { expect(resolve('foo', file, settings)).to.have.property('path') .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js')) }) + + it("doesn't swallow config load errors (#435)", function () { + var settings = { + config: path.join(__dirname, './files/webpack.config.garbage.js'), + } + expect(function () { resolve('foo', file, settings) }).to.throw(Error) + }) }) diff --git a/resolvers/webpack/test/files/node_modules/webpack-resolver-plugin-test/index.js b/resolvers/webpack/test/files/node_modules/webpack-resolver-plugin-test/index.js new file mode 100644 index 0000000000..2989f9bab3 --- /dev/null +++ b/resolvers/webpack/test/files/node_modules/webpack-resolver-plugin-test/index.js @@ -0,0 +1,57 @@ +var path = require('path'); + +/** + * ResolverPlugin + * + * @param plugins + * @param types + * @constructor + */ + +function ResolverPlugin(plugins, types) { + if(!Array.isArray(plugins)) plugins = [plugins]; + if(!types) types = ["normal"]; + else if(!Array.isArray(types)) types = [types]; + + this.plugins = plugins; + this.types = types; +} + +module.exports.ResolverPlugin = ResolverPlugin; + + +/** + * SimpleResolver for testing + * + * @param file + * @param source + * @constructor + */ + +function SimpleResolver(file, source) { + this.file = file; + this.source = source; +} + +SimpleResolver.prototype.apply = function (resolver) { + + var file = this.file; + var source = this.source; + + resolver.plugin('directory', function (request, done) { + + var absolutePath = path.resolve(request.path, request.request); + + if (absolutePath === source) { + resolver.doResolve('file', { request: file }, function (error, result) { + return done(undefined, result || undefined); + }); + } + + return done(); + + }); + +} + +module.exports.SimpleResolver = SimpleResolver; diff --git a/resolvers/webpack/test/files/some/bar/bar.js b/resolvers/webpack/test/files/some/bar/bar.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/resolvers/webpack/test/files/webpack.config.garbage.js b/resolvers/webpack/test/files/webpack.config.garbage.js new file mode 100644 index 0000000000..043b375628 --- /dev/null +++ b/resolvers/webpack/test/files/webpack.config.garbage.js @@ -0,0 +1 @@ +throw new Error("this config is garbage") \ No newline at end of file diff --git a/resolvers/webpack/test/files/webpack.config.js b/resolvers/webpack/test/files/webpack.config.js index 5bc10be97d..6dcbbf4e3a 100644 --- a/resolvers/webpack/test/files/webpack.config.js +++ b/resolvers/webpack/test/files/webpack.config.js @@ -1,9 +1,11 @@ var path = require('path') +var pluginsTest = require('webpack-resolver-plugin-test') module.exports = { resolve: { alias: { 'foo': path.join(__dirname, 'some', 'goofy', 'path', 'foo.js'), + 'some-alias': path.join(__dirname, 'some') }, modulesDirectories: ['node_modules', 'bower_components'], root: path.join(__dirname, 'src'), @@ -20,4 +22,13 @@ module.exports = { callback(); } ], + + plugins: [ + new pluginsTest.ResolverPlugin([ + new pluginsTest.SimpleResolver( + path.join(__dirname, 'some', 'bar', 'bar.js'), + path.join(__dirname, 'some', 'bar') + ) + ]) + ] } diff --git a/resolvers/webpack/test/plugins.js b/resolvers/webpack/test/plugins.js new file mode 100644 index 0000000000..f37b945183 --- /dev/null +++ b/resolvers/webpack/test/plugins.js @@ -0,0 +1,29 @@ +var chai = require('chai') + , expect = chai.expect + , path = require('path') + +var webpack = require('../index') + +var file = path.join(__dirname, 'files', 'dummy.js') + +describe("plugins", function () { + var resolved, aliasResolved + + before(function () { + resolved = webpack.resolve('./some/bar', file) + aliasResolved = webpack.resolve('some-alias/bar', file) + }) + + it("work", function () { + expect(resolved).to.have.property('found', true) + }) + + it("is correct", function () { + expect(resolved).to.have.property('path') + .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js')) + }) + + it("work with alias", function () { + expect(aliasResolved).to.have.property('found', true) + }) +}) diff --git a/src/core/getExports.js b/src/core/getExports.js index ae2ca4d892..518b19beba 100644 --- a/src/core/getExports.js +++ b/src/core/getExports.js @@ -6,7 +6,7 @@ import { createHash } from 'crypto' import * as doctrine from 'doctrine' import parse from './parse' -import resolve from './resolve' +import resolve, { relative as resolveRelative } from './resolve' import isIgnored from './ignore' import { hashObject } from './hash' @@ -118,7 +118,7 @@ export default class ExportMap { const namespaces = new Map() function remotePath(node) { - return resolve.relative(node.source.value, path, context.settings) + return resolveRelative(node.source.value, path, context.settings) } function resolveImport(node) { diff --git a/src/importDeclaration.js b/src/importDeclaration.js index b7560f11da..69af65d978 100644 --- a/src/importDeclaration.js +++ b/src/importDeclaration.js @@ -1,6 +1,4 @@ -'use strict' - -module.exports = function importDeclaration(context) { +export default function importDeclaration(context) { var ancestors = context.getAncestors() return ancestors[ancestors.length - 1] } diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js index 2048872d80..ebd769dfb4 100644 --- a/src/rules/newline-after-import.js +++ b/src/rules/newline-after-import.js @@ -86,8 +86,12 @@ module.exports = function (context) { }, 'Program:exit': function () { scopes.forEach(function ({ scope, requireCalls }) { + const scopeBody = getScopeBody(scope) + + // skip non-array scopes (i.e. arrow function expressions) + if (!(scopeBody instanceof Array)) return + requireCalls.forEach(function (node, index) { - const scopeBody = getScopeBody(scope) const nodePosition = findNodeIndexInScopeBody(scopeBody, node) const statementWithRequireCall = scopeBody[nodePosition] const nextStatement = scopeBody[nodePosition + 1] diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js index becbad0926..059307e043 100644 --- a/src/rules/no-extraneous-dependencies.js +++ b/src/rules/no-extraneous-dependencies.js @@ -15,6 +15,7 @@ function getDependencies(context) { dependencies: packageContent.dependencies || {}, devDependencies: packageContent.devDependencies || {}, optionalDependencies: packageContent.optionalDependencies || {}, + peerDependencies: packageContent.peerDependencies || {}, } } catch (e) { return null @@ -35,7 +36,7 @@ function optDepErrorMessage(packageName) { `not optionalDependencies.` } -function reportIfMissing(context, deps, allowDevDeps, allowOptDeps, node, name) { +function reportIfMissing(context, deps, depsOptions, node, name) { if (importType(name, context) !== 'external') { return } @@ -47,20 +48,22 @@ function reportIfMissing(context, deps, allowDevDeps, allowOptDeps, node, name) const isInDeps = deps.dependencies[packageName] !== undefined const isInDevDeps = deps.devDependencies[packageName] !== undefined const isInOptDeps = deps.optionalDependencies[packageName] !== undefined + const isInPeerDeps = deps.peerDependencies[packageName] !== undefined if (isInDeps || - (allowDevDeps && isInDevDeps) || - (allowOptDeps && isInOptDeps) + (depsOptions.allowDevDeps && isInDevDeps) || + (depsOptions.allowPeerDeps && isInPeerDeps) || + (depsOptions.allowOptDeps && isInOptDeps) ) { return } - if (isInDevDeps && !allowDevDeps) { + if (isInDevDeps && !depsOptions.allowDevDeps) { context.report(node, devDepErrorMessage(packageName)) return } - if (isInOptDeps && !allowOptDeps) { + if (isInOptDeps && !depsOptions.allowOptDeps) { context.report(node, optDepErrorMessage(packageName)) return } @@ -70,22 +73,26 @@ function reportIfMissing(context, deps, allowDevDeps, allowOptDeps, node, name) module.exports = function (context) { const options = context.options[0] || {} - const allowDevDeps = options.devDependencies !== false - const allowOptDeps = options.optionalDependencies !== false const deps = getDependencies(context) if (!deps) { return {} } + const depsOptions = { + allowDevDeps: options.devDependencies !== false, + allowOptDeps: options.optionalDependencies !== false, + allowPeerDeps: options.peerDependencies !== false, + } + // todo: use module visitor from module-utils core return { ImportDeclaration: function (node) { - reportIfMissing(context, deps, allowDevDeps, allowOptDeps, node, node.source.value) + reportIfMissing(context, deps, depsOptions, node, node.source.value) }, CallExpression: function handleRequires(node) { if (isStaticRequire(node)) { - reportIfMissing(context, deps, allowDevDeps, allowOptDeps, node, node.arguments[0].value) + reportIfMissing(context, deps, depsOptions, node, node.arguments[0].value) } }, } @@ -97,6 +104,7 @@ module.exports.schema = [ 'properties': { 'devDependencies': { 'type': 'boolean' }, 'optionalDependencies': { 'type': 'boolean' }, + 'peerDependencies': { 'type': 'boolean' }, }, 'additionalProperties': false, }, diff --git a/tests/files/package.json b/tests/files/package.json index d0ef9601b4..7aaed30f33 100644 --- a/tests/files/package.json +++ b/tests/files/package.json @@ -1,6 +1,7 @@ { "dummy": true, "devDependencies": { + "glob": "1.0.0", "eslint": "2.x" }, "peerDependencies": { diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js index 95025b34d0..4e6845d863 100644 --- a/tests/src/core/resolve.js +++ b/tests/src/core/resolve.js @@ -1,6 +1,6 @@ import { expect } from 'chai' -import resolve, { CASE_INSENSITIVE } from 'core/resolve' +import resolve, { CASE_SENSITIVE_FS } from 'core/resolve' import * as fs from 'fs' import * as utils from '../utils' @@ -66,7 +66,7 @@ describe('resolve', function () { // these tests fail on a case-sensitive file system // because nonexistent files aren't cached - if (CASE_INSENSITIVE) { + if (!CASE_SENSITIVE_FS) { it('gets cached values within cache lifetime', function () { // get cached values initially expect(resolve(original, context)).to.exist diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js index ccefca6512..49279ba422 100644 --- a/tests/src/rules/newline-after-import.js +++ b/tests/src/rules/newline-after-import.js @@ -8,6 +8,20 @@ const ruleTester = new RuleTester() ruleTester.run('newline-after-import', require('rules/newline-after-import'), { valid: [ "var path = require('path');\nvar foo = require('foo');\n", + "require('foo');", + "switch ('foo') { case 'bar': require('baz'); }", + { + code: ` + const x = () => require('baz') + , y = () => require('bar')`, + parserOptions: { ecmaVersion: 6 } , + }, + { + code: `const x = () => require('baz') && require('bar')`, + parserOptions: { ecmaVersion: 6 } , + }, + "function x(){ require('baz'); }", + "a(require('b'), require('c'), require('d'));", `function foo() { switch (renderData.modalViewKey) { diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js index 6694464143..f0b43b09be 100644 --- a/tests/src/rules/no-extraneous-dependencies.js +++ b/tests/src/rules/no-extraneous-dependencies.js @@ -24,6 +24,11 @@ ruleTester.run('no-extraneous-dependencies', rule, { test({ code: 'import "@scope/core"'}), test({ code: 'import "electron"', settings: { 'import/core-modules': ['electron'] } }), + test({ code: 'import "eslint"' }), + test({ + code: 'import "eslint"', + options: [{peerDependencies: true}], + }), // 'project' type test({ @@ -55,7 +60,7 @@ ruleTester.run('no-extraneous-dependencies', rule, { }), test({ code: 'import "eslint"', - options: [{devDependencies: false}], + options: [{devDependencies: false, peerDependencies: false}], errors: [{ ruleId: 'no-extraneous-dependencies', message: '\'eslint\' should be listed in the project\'s dependencies, not devDependencies.', @@ -77,11 +82,11 @@ ruleTester.run('no-extraneous-dependencies', rule, { }], }), test({ - code: 'var eslint = require("eslint")', + code: 'var glob = require("glob")', options: [{devDependencies: false}], errors: [{ ruleId: 'no-extraneous-dependencies', - message: '\'eslint\' should be listed in the project\'s dependencies, not devDependencies.', + message: '\'glob\' should be listed in the project\'s dependencies, not devDependencies.', }], }), test({