Skip to content

Commit

Permalink
Breaking: drop supports for Node 0.x
Browse files Browse the repository at this point in the history
  • Loading branch information
mysticatea committed Jan 28, 2017
1 parent 7f37c7c commit ba283df
Show file tree
Hide file tree
Showing 38 changed files with 514 additions and 620 deletions.
6 changes: 2 additions & 4 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{
"extends": ["mysticatea/es5", "mysticatea/node"],
"rules": {
"no-param-reassign": [2, {"props": false}]
}
"extends": ["mysticatea", "mysticatea/node"],
"rules": {}
}
6 changes: 0 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
sudo: false
language: node_js
node_js:
- "0.10"
- "0.12"
- "4"
- "6"
- "7"
before_script:
- npm install async
- npm install -g if-node-version
script:
- "if-node-version '>=4' npm test"
- "npm run test@2"
after_success:
- npm run codecov
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Additional ESLint's rules for Node.js
> npm install --save-dev eslint eslint-plugin-node
```

- Requires Node.js `^0.10.0 || ^0.12.0 || ^4.0.0 || >=6.0.0`
- Requires Node.js `^4.0.0 || >=6.0.0`
- Requires ESLint `>=2.0.0`

**Note:** It recommends a use of [the "engines" field of package.json](https://docs.npmjs.com/files/package.json#engines). The "engines" field is used by [no-unsupported-features](docs/rules/no-unsupported-features.md) rule.
Expand Down
106 changes: 34 additions & 72 deletions lib/rules/exports-style.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
/*istanbul ignore next */
/**
* This function is copied from https://github.com/eslint/eslint/blob/2355f8d0de1d6732605420d15ddd4f1eee3c37b6/lib/ast-utils.js#L648-L684
* (This utility had been added in v3.3.0)
*
* @param {ASTNode} node - The node to get.
* @returns {string|null} The property name if static. Otherwise, null.
* @private
*/
function getStaticPropertyName(node) {
var prop = null
let prop = null

switch (node && node.type) {
case "Property":
Expand Down Expand Up @@ -78,7 +78,7 @@ function isAssignee(node) {
* @returns {ASTNode|null} The top assignment expression node, or null.
*/
function getTopAssignment(leafNode) {
var node = leafNode
let node = leafNode

// Skip MemberExpressions.
while (node.parent.type === "MemberExpression" && node.parent.object === node) {
Expand Down Expand Up @@ -108,53 +108,23 @@ function createAssignmentList(nodes) {
return nodes.map(getTopAssignment).filter(Boolean)
}

/**
* Gets the parent node of the given reference.
*
* @param {escope.Reference} reference - The reference to get.
* @returns {ASTNode} The parent node of the reference.
*/
function getParentNodeOfReference(reference) {
return reference.identifier.parent
}

/**
* Gets the node of the given reference.
*
* @param {escope.Reference} reference - The reference to get.
* @returns {ASTNode} The node of the reference.
*/
function getNodeOfReference(reference) {
return reference.identifier
}

/**
* Checks whether the given node is the member access to `exports` property.
*
* @param {ASTNode} node - The node to check.
* @returns {boolean} `true` if the node is the member access to `exports` property.
*/
function isExportsMember(node) {
return (
node.type === "MemberExpression" &&
getStaticPropertyName(node) === "exports"
)
}

/**
* Gets the reference of `module.exports` from the given scope.
*
* @param {escope.Scope} scope - The scope to get.
* @returns {ASTNode[]} Gotten MemberExpression node list.
*/
function getModuleExportsNodes(scope) {
var variable = scope.set.get("module")
const variable = scope.set.get("module")
if (variable == null) {
return []
}
return variable.references
.map(getParentNodeOfReference)
.filter(isExportsMember)
.map(reference => reference.identifier.parent)
.filter(node => (
node.type === "MemberExpression" &&
getStaticPropertyName(node) === "exports"
))
}

/**
Expand All @@ -164,11 +134,11 @@ function getModuleExportsNodes(scope) {
* @returns {ASTNode[]} Gotten Identifier node list.
*/
function getExportsNodes(scope) {
var variable = scope.set.get("exports")
const variable = scope.set.get("exports")
if (variable == null) {
return []
}
return variable.references.map(getNodeOfReference)
return variable.references.map(reference => reference.identifier)
}

//------------------------------------------------------------------------------
Expand All @@ -193,9 +163,9 @@ module.exports = {
],
},

create: function(context) {
var mode = context.options[0] || "module.exports"
var batchAssignAllowed = Boolean(
create(context) {
const mode = context.options[0] || "module.exports"
const batchAssignAllowed = Boolean(
context.options[1] != null &&
context.options[1].allowBatchAssign
)
Expand All @@ -207,26 +177,24 @@ module.exports = {
* @returns {void}
*/
function enforceModuleExports() {
var globalScope = context.getScope()
var exportsNodes = getExportsNodes(globalScope)
var assignList = batchAssignAllowed
const globalScope = context.getScope()
const exportsNodes = getExportsNodes(globalScope)
const assignList = batchAssignAllowed
? createAssignmentList(getModuleExportsNodes(globalScope))
: []

for (var i = 0; i < exportsNodes.length; ++i) {
var exportsNode = exportsNodes[i]

for (const node of exportsNodes) {
// Skip if it's a batch assignment.
if (assignList.length > 0 &&
assignList.indexOf(getTopAssignment(exportsNode)) !== -1
assignList.indexOf(getTopAssignment(node)) !== -1
) {
continue
}

// Report.
context.report({
node: exportsNode,
loc: exportsNode.loc,
node,
loc: node.loc,
message:
"Unexpected access to 'exports'. " +
"Use 'module.exports' instead.",
Expand All @@ -241,22 +209,18 @@ module.exports = {
* @returns {void}
*/
function enforceExports() {
var globalScope = context.getScope()
var exportsNodes = getExportsNodes(globalScope)
var moduleExportsNodes = getModuleExportsNodes(globalScope)
var assignList = batchAssignAllowed
const globalScope = context.getScope()
const exportsNodes = getExportsNodes(globalScope)
const moduleExportsNodes = getModuleExportsNodes(globalScope)
const assignList = batchAssignAllowed
? createAssignmentList(exportsNodes)
: []
var batchAssignList = []

for (var i = 0; i < moduleExportsNodes.length; ++i) {
var moduleExportsNode = moduleExportsNodes[i]
const batchAssignList = []

for (const node of moduleExportsNodes) {
// Skip if it's a batch assignment.
if (assignList.length > 0) {
var found = assignList.indexOf(
getTopAssignment(moduleExportsNode)
)
const found = assignList.indexOf(getTopAssignment(node))
if (found !== -1) {
batchAssignList.push(assignList[found])
assignList.splice(found, 1)
Expand All @@ -266,30 +230,28 @@ module.exports = {

// Report.
context.report({
node: moduleExportsNode,
node,
message:
"Unexpected access to 'module.exports'. " +
"Use 'exports' instead.",
})
}

// Disallow direct assignment to `exports`.
for (var i = 0; i < exportsNodes.length; ++i) {
var exportsNode = exportsNodes[i]

for (const node of exportsNodes) {
// Skip if it's not assignee.
if (!isAssignee(exportsNode)) {
if (!isAssignee(node)) {
continue
}

// Check if it's a batch assignment.
if (batchAssignList.indexOf(getTopAssignment(exportsNode)) !== -1) {
if (batchAssignList.indexOf(getTopAssignment(node)) !== -1) {
continue
}

// Report.
context.report({
node: exportsNode,
node,
message:
"Unexpected assignment to 'exports'. " +
"Don't modify 'exports' itself.",
Expand All @@ -298,7 +260,7 @@ module.exports = {
}

return {
"Program:exit": function() {
"Program:exit"() {
switch (mode) {
case "module.exports":
enforceModuleExports()
Expand Down

0 comments on commit ba283df

Please sign in to comment.