Skip to content

Commit

Permalink
bump ESLint devDep to 3.x + new rule format
Browse files Browse the repository at this point in the history
- converted all rules using eslint-transforms tool
- updated no-unresolved + namespace to match tool output (module.exports vs. exports.{meta,create})
  • Loading branch information
benmosher committed Sep 15, 2016
1 parent ef1745a commit 20079c6
Show file tree
Hide file tree
Showing 25 changed files with 1,200 additions and 1,065 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@
"homepage": "https://github.com/benmosher/eslint-plugin-import",
"devDependencies": {
"babel-eslint": "next",
"babel-preset-es2015-argon": "latest",
"babel-plugin-istanbul": "^2.0.1",
"babel-preset-es2015-argon": "latest",
"babel-register": "6.9.0",
"chai": "^3.4.0",
"coveralls": "^2.11.4",
"cross-env": "^2.0.0",
"eslint": "2.x",
"eslint": "3.x",
"eslint-import-resolver-node": "file:./resolvers/node",
"eslint-import-resolver-webpack": "file:./resolvers/webpack",
"eslint-module-utils": "file:./utils",
Expand Down
50 changes: 28 additions & 22 deletions src/rules/default.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
import Exports from '../ExportMap'

module.exports = function (context) {
module.exports = {
meta: {
docs: {},
},

function checkDefault(specifierType, node) {
create: function (context) {

// poor man's Array.find
let defaultSpecifier
node.specifiers.some((n) => {
if (n.type === specifierType) {
defaultSpecifier = n
return true
}
})
function checkDefault(specifierType, node) {

// poor man's Array.find
let defaultSpecifier
node.specifiers.some((n) => {
if (n.type === specifierType) {
defaultSpecifier = n
return true
}
})

if (!defaultSpecifier) return
var imports = Exports.get(node.source.value, context)
if (imports == null) return
if (!defaultSpecifier) return
var imports = Exports.get(node.source.value, context)
if (imports == null) return

if (imports.errors.length) {
imports.reportErrors(context, node)
} else if (!imports.get('default')) {
context.report(defaultSpecifier, 'No default export found in module.')
if (imports.errors.length) {
imports.reportErrors(context, node)
} else if (!imports.get('default')) {
context.report(defaultSpecifier, 'No default export found in module.')
}
}
}

return {
'ImportDeclaration': checkDefault.bind(null, 'ImportDefaultSpecifier'),
'ExportNamedDeclaration': checkDefault.bind(null, 'ExportDefaultSpecifier'),
}
return {
'ImportDeclaration': checkDefault.bind(null, 'ImportDefaultSpecifier'),
'ExportNamedDeclaration': checkDefault.bind(null, 'ExportDefaultSpecifier'),
}
},
}
114 changes: 60 additions & 54 deletions src/rules/export.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,78 @@
import ExportMap, { recursivePatternCapture } from '../ExportMap'

module.exports = function (context) {
const named = new Map()
module.exports = {
meta: {
docs: {},
},

function addNamed(name, node) {
let nodes = named.get(name)
create: function (context) {
const named = new Map()

if (nodes == null) {
nodes = new Set()
named.set(name, nodes)
}
function addNamed(name, node) {
let nodes = named.get(name)

nodes.add(node)
}
if (nodes == null) {
nodes = new Set()
named.set(name, nodes)
}

return {
'ExportDefaultDeclaration': (node) => addNamed('default', node),
nodes.add(node)
}

'ExportSpecifier': function (node) {
addNamed(node.exported.name, node.exported)
},
return {
'ExportDefaultDeclaration': (node) => addNamed('default', node),

'ExportNamedDeclaration': function (node) {
if (node.declaration == null) return
'ExportSpecifier': function (node) {
addNamed(node.exported.name, node.exported)
},

if (node.declaration.id != null) {
addNamed(node.declaration.id.name, node.declaration.id)
}
'ExportNamedDeclaration': function (node) {
if (node.declaration == null) return

if (node.declaration.declarations != null) {
for (let declaration of node.declaration.declarations) {
recursivePatternCapture(declaration.id, v => addNamed(v.name, v))
if (node.declaration.id != null) {
addNamed(node.declaration.id.name, node.declaration.id)
}
}
},

'ExportAllDeclaration': function (node) {
if (node.source == null) return // not sure if this is ever true
if (node.declaration.declarations != null) {
for (let declaration of node.declaration.declarations) {
recursivePatternCapture(declaration.id, v => addNamed(v.name, v))
}
}
},

const remoteExports = ExportMap.get(node.source.value, context)
if (remoteExports == null) return
'ExportAllDeclaration': function (node) {
if (node.source == null) return // not sure if this is ever true

if (remoteExports.errors.length) {
remoteExports.reportErrors(context, node)
return
}
let any = false
remoteExports.forEach((v, name) =>
name !== 'default' &&
(any = true) && // poor man's filter
addNamed(name, node))

if (!any) {
context.report(node.source,
`No named exports found in module '${node.source.value}'.`)
}
},
const remoteExports = ExportMap.get(node.source.value, context)
if (remoteExports == null) return

'Program:exit': function () {
for (let [name, nodes] of named) {
if (nodes.size <= 1) continue
if (remoteExports.errors.length) {
remoteExports.reportErrors(context, node)
return
}
let any = false
remoteExports.forEach((v, name) =>
name !== 'default' &&
(any = true) && // poor man's filter
addNamed(name, node))

for (let node of nodes) {
if (name === 'default') {
context.report(node, 'Multiple default exports.')
} else context.report(node, `Multiple exports of name '${name}'.`)
if (!any) {
context.report(node.source,
`No named exports found in module '${node.source.value}'.`)
}
}
},
}
},

'Program:exit': function () {
for (let [name, nodes] of named) {
if (nodes.size <= 1) continue

for (let node of nodes) {
if (name === 'default') {
context.report(node, 'Multiple default exports.')
} else context.report(node, `Multiple exports of name '${name}'.`)
}
}
},
}
},
}
120 changes: 63 additions & 57 deletions src/rules/extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,79 @@ import endsWith from 'lodash.endswith'
import resolve from 'eslint-module-utils/resolve'
import { isBuiltIn } from '../core/importType'

module.exports = function (context) {
const configuration = context.options[0] || 'never'
module.exports = {
meta: {
docs: {},

function isUseOfExtensionEnforced(extension) {
if (typeof configuration === 'object') {
return configuration[extension] === 'always'
}
schema: [
{
oneOf: [
{
enum: [ 'always', 'never' ],
},
{
type: 'object',
patternProperties: {
'.*': { enum: [ 'always', 'never' ] },
},
},
],
},
],
},

return configuration === 'always'
}
create: function (context) {
const configuration = context.options[0] || 'never'

function isResolvableWithoutExtension(file) {
const extension = path.extname(file)
const fileWithoutExtension = file.slice(0, -extension.length)
const resolvedFileWithoutExtension = resolve(fileWithoutExtension, context)
function isUseOfExtensionEnforced(extension) {
if (typeof configuration === 'object') {
return configuration[extension] === 'always'
}

return resolvedFileWithoutExtension === resolve(file, context)
}
return configuration === 'always'
}

function checkFileExtension(node) {
const { source } = node
const importPath = source.value
function isResolvableWithoutExtension(file) {
const extension = path.extname(file)
const fileWithoutExtension = file.slice(0, -extension.length)
const resolvedFileWithoutExtension = resolve(fileWithoutExtension, context)

// don't enforce anything on builtins
if (isBuiltIn(importPath, context.settings)) return
return resolvedFileWithoutExtension === resolve(file, context)
}

const resolvedPath = resolve(importPath, context)
function checkFileExtension(node) {
const { source } = node
const importPath = source.value

// get extension from resolved path, if possible.
// for unresolved, use source value.
const extension = path.extname(resolvedPath || importPath).substring(1)
// don't enforce anything on builtins
if (isBuiltIn(importPath, context.settings)) return

if (!extension || !endsWith(importPath, extension)) {
if (isUseOfExtensionEnforced(extension)) {
context.report({
node: source,
message:
`Missing file extension ${extension ? `"${extension}" ` : ''}for "${importPath}"`,
})
}
} else if (extension) {
if (!isUseOfExtensionEnforced(extension) && isResolvableWithoutExtension(importPath)) {
context.report({
node: source,
message: `Unexpected use of file extension "${extension}" for "${importPath}"`,
})
const resolvedPath = resolve(importPath, context)

// get extension from resolved path, if possible.
// for unresolved, use source value.
const extension = path.extname(resolvedPath || importPath).substring(1)

if (!extension || !endsWith(importPath, extension)) {
if (isUseOfExtensionEnforced(extension)) {
context.report({
node: source,
message:
`Missing file extension ${extension ? `"${extension}" ` : ''}for "${importPath}"`,
})
}
} else if (extension) {
if (!isUseOfExtensionEnforced(extension) && isResolvableWithoutExtension(importPath)) {
context.report({
node: source,
message: `Unexpected use of file extension "${extension}" for "${importPath}"`,
})
}
}
}
}

return {
ImportDeclaration: checkFileExtension,
}
}

module.exports.schema = [
{
oneOf: [
{
enum: [ 'always', 'never' ],
},
{
type: 'object',
patternProperties: {
'.*': { enum: [ 'always', 'never' ] },
},
},
],
return {
ImportDeclaration: checkFileExtension,
}
},
]
}

0 comments on commit 20079c6

Please sign in to comment.