eslint-plugin-node
Advanced tools
Comparing version 3.0.5 to 4.0.0
@@ -15,9 +15,9 @@ /** | ||
* 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 | ||
@@ -82,3 +82,3 @@ switch (node && node.type) { | ||
function getTopAssignment(leafNode) { | ||
var node = leafNode | ||
let node = leafNode | ||
@@ -114,35 +114,2 @@ // Skip MemberExpressions. | ||
/** | ||
* 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. | ||
@@ -154,3 +121,3 @@ * | ||
function getModuleExportsNodes(scope) { | ||
var variable = scope.set.get("module") | ||
const variable = scope.set.get("module") | ||
if (variable == null) { | ||
@@ -160,4 +127,7 @@ return [] | ||
return variable.references | ||
.map(getParentNodeOfReference) | ||
.filter(isExportsMember) | ||
.map(reference => reference.identifier.parent) | ||
.filter(node => ( | ||
node.type === "MemberExpression" && | ||
getStaticPropertyName(node) === "exports" | ||
)) | ||
} | ||
@@ -172,150 +142,174 @@ | ||
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) | ||
} | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
/** | ||
* The definition of this rule. | ||
* | ||
* @param {RuleContext} context - The rule context to check. | ||
* @returns {object} The definition of this rule. | ||
*/ | ||
function create(context) { | ||
const mode = context.options[0] || "module.exports" | ||
const batchAssignAllowed = Boolean( | ||
context.options[1] != null && | ||
context.options[1].allowBatchAssign | ||
) | ||
const sourceCode = context.getSourceCode() | ||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: "enforce either `module.exports` or `exports`.", | ||
category: "Stylistic Issues", | ||
recommended: false, | ||
}, | ||
fixable: false, | ||
schema: [ | ||
{enum: ["module.exports", "exports"]}, | ||
{ | ||
type: "object", | ||
properties: {allowBatchAssign: {type: "boolean"}}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
/** | ||
* Gets the location info of reports. | ||
* | ||
* exports = foo | ||
* ^^^^^^^^^ | ||
* | ||
* module.exports = foo | ||
* ^^^^^^^^^^^^^^^^ | ||
* | ||
* @param {ASTNode} node - The node of `exports`/`module.exports`. | ||
* @returns {Location} The location info of reports. | ||
*/ | ||
function getLocation(node) { | ||
const token = sourceCode.getTokenAfter(node) | ||
return { | ||
start: node.loc.start, | ||
end: token.loc.end, | ||
} | ||
} | ||
create: function(context) { | ||
var mode = context.options[0] || "module.exports" | ||
var batchAssignAllowed = Boolean( | ||
context.options[1] != null && | ||
context.options[1].allowBatchAssign | ||
) | ||
/** | ||
* Enforces `module.exports`. | ||
* This warns references of `exports`. | ||
* | ||
* @returns {void} | ||
*/ | ||
function enforceModuleExports() { | ||
const globalScope = context.getScope() | ||
const exportsNodes = getExportsNodes(globalScope) | ||
const assignList = batchAssignAllowed | ||
? createAssignmentList(getModuleExportsNodes(globalScope)) | ||
: [] | ||
/** | ||
* Enforces `module.exports`. | ||
* This warns references of `exports`. | ||
* | ||
* @returns {void} | ||
*/ | ||
function enforceModuleExports() { | ||
var globalScope = context.getScope() | ||
var exportsNodes = getExportsNodes(globalScope) | ||
var assignList = batchAssignAllowed | ||
? createAssignmentList(getModuleExportsNodes(globalScope)) | ||
: [] | ||
for (const node of exportsNodes) { | ||
// Skip if it's a batch assignment. | ||
if (assignList.length > 0 && | ||
assignList.indexOf(getTopAssignment(node)) !== -1 | ||
) { | ||
continue | ||
} | ||
for (var i = 0; i < exportsNodes.length; ++i) { | ||
var exportsNode = exportsNodes[i] | ||
// Report. | ||
context.report({ | ||
node, | ||
loc: getLocation(node), | ||
message: | ||
"Unexpected access to 'exports'. " + | ||
"Use 'module.exports' instead.", | ||
}) | ||
} | ||
} | ||
// Skip if it's a batch assignment. | ||
if (assignList.length > 0 && | ||
assignList.indexOf(getTopAssignment(exportsNode)) !== -1 | ||
) { | ||
/** | ||
* Enforces `exports`. | ||
* This warns references of `module.exports`. | ||
* | ||
* @returns {void} | ||
*/ | ||
function enforceExports() { | ||
const globalScope = context.getScope() | ||
const exportsNodes = getExportsNodes(globalScope) | ||
const moduleExportsNodes = getModuleExportsNodes(globalScope) | ||
const assignList = batchAssignAllowed | ||
? createAssignmentList(exportsNodes) | ||
: [] | ||
const batchAssignList = [] | ||
for (const node of moduleExportsNodes) { | ||
// Skip if it's a batch assignment. | ||
if (assignList.length > 0) { | ||
const found = assignList.indexOf(getTopAssignment(node)) | ||
if (found !== -1) { | ||
batchAssignList.push(assignList[found]) | ||
assignList.splice(found, 1) | ||
continue | ||
} | ||
} | ||
// Report. | ||
context.report({ | ||
node: exportsNode, | ||
loc: exportsNode.loc, | ||
message: | ||
"Unexpected access to 'exports'. " + | ||
"Use 'module.exports' instead.", | ||
}) | ||
} | ||
// Report. | ||
context.report({ | ||
node, | ||
loc: getLocation(node), | ||
message: | ||
"Unexpected access to 'module.exports'. " + | ||
"Use 'exports' instead.", | ||
}) | ||
} | ||
/** | ||
* Enforces `exports`. | ||
* This warns references of `module.exports`. | ||
* | ||
* @returns {void} | ||
*/ | ||
function enforceExports() { | ||
var globalScope = context.getScope() | ||
var exportsNodes = getExportsNodes(globalScope) | ||
var moduleExportsNodes = getModuleExportsNodes(globalScope) | ||
var assignList = batchAssignAllowed | ||
? createAssignmentList(exportsNodes) | ||
: [] | ||
var batchAssignList = [] | ||
// Disallow direct assignment to `exports`. | ||
for (const node of exportsNodes) { | ||
// Skip if it's not assignee. | ||
if (!isAssignee(node)) { | ||
continue | ||
} | ||
for (var i = 0; i < moduleExportsNodes.length; ++i) { | ||
var moduleExportsNode = moduleExportsNodes[i] | ||
// Skip if it's a batch assignment. | ||
if (assignList.length > 0) { | ||
var found = assignList.indexOf( | ||
getTopAssignment(moduleExportsNode) | ||
) | ||
if (found !== -1) { | ||
batchAssignList.push(assignList[found]) | ||
assignList.splice(found, 1) | ||
continue | ||
} | ||
} | ||
// Report. | ||
context.report({ | ||
node: moduleExportsNode, | ||
message: | ||
"Unexpected access to 'module.exports'. " + | ||
"Use 'exports' instead.", | ||
}) | ||
// Check if it's a batch assignment. | ||
if (batchAssignList.indexOf(getTopAssignment(node)) !== -1) { | ||
continue | ||
} | ||
// Disallow direct assignment to `exports`. | ||
for (var i = 0; i < exportsNodes.length; ++i) { | ||
var exportsNode = exportsNodes[i] | ||
// Report. | ||
context.report({ | ||
node, | ||
loc: getLocation(node), | ||
message: | ||
"Unexpected assignment to 'exports'. " + | ||
"Don't modify 'exports' itself.", | ||
}) | ||
} | ||
} | ||
// Skip if it's not assignee. | ||
if (!isAssignee(exportsNode)) { | ||
continue | ||
} | ||
return { | ||
"Program:exit"() { | ||
switch (mode) { | ||
case "module.exports": | ||
enforceModuleExports() | ||
break | ||
case "exports": | ||
enforceExports() | ||
break | ||
// Check if it's a batch assignment. | ||
if (batchAssignList.indexOf(getTopAssignment(exportsNode)) !== -1) { | ||
continue | ||
} | ||
// Report. | ||
context.report({ | ||
node: exportsNode, | ||
message: | ||
"Unexpected assignment to 'exports'. " + | ||
"Don't modify 'exports' itself.", | ||
}) | ||
// no default | ||
} | ||
} | ||
}, | ||
} | ||
} | ||
return { | ||
"Program:exit": function() { | ||
switch (mode) { | ||
case "module.exports": | ||
enforceModuleExports() | ||
break | ||
case "exports": | ||
enforceExports() | ||
break | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
// no default | ||
} | ||
module.exports = { | ||
create, | ||
meta: { | ||
docs: { | ||
description: "enforce either `module.exports` or `exports`", | ||
category: "Stylistic Issues", | ||
recommended: false, | ||
}, | ||
fixable: false, | ||
schema: [ | ||
{ // | ||
enum: ["module.exports", "exports"], | ||
}, | ||
} | ||
{ | ||
type: "object", | ||
properties: {allowBatchAssign: {type: "boolean"}}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
} |
@@ -13,7 +13,7 @@ /** | ||
var dirname = require("path").dirname | ||
var assign = require("object-assign") | ||
var resolve = require("resolve").sync | ||
var deprecatedApis = require("../util/deprecated-apis") | ||
var getValueIfString = require("../util/get-value-if-string") | ||
const dirname = require("path").dirname | ||
const assign = require("object-assign") | ||
const resolve = require("resolve").sync | ||
const deprecatedApis = require("../util/deprecated-apis") | ||
const getValueIfString = require("../util/get-value-if-string") | ||
@@ -24,5 +24,45 @@ //------------------------------------------------------------------------------ | ||
var SENTINEL_TYPE = /^(?:.+?Statement|.+?Declaration|(?:Array|ArrowFunction|Assignment|Call|Class|Function|Member|New|Object)Expression|AssignmentPattern|Program|VariableDeclarator)$/ | ||
const SENTINEL_TYPE = /^(?:.+?Statement|.+?Declaration|(?:Array|ArrowFunction|Assignment|Call|Class|Function|Member|New|Object)Expression|AssignmentPattern|Program|VariableDeclarator)$/ | ||
const MODULE_ITEMS = getDeprecatedItems(deprecatedApis.modules, [], []) | ||
const GLOBAL_ITEMS = getDeprecatedItems(deprecatedApis.globals, [], []) | ||
/** | ||
* Gets the array of deprecated items. | ||
* | ||
* It's the paths which are separated by dots. | ||
* E.g. `buffer.Buffer`, `events.EventEmitter.listenerCount` | ||
* | ||
* @param {object} definition - The definition of deprecated APIs. | ||
* @param {string[]} result - The array of the result. | ||
* @param {string[]} stack - The array to manage the stack of paths. | ||
* @returns {string[]} `result`. | ||
*/ | ||
function getDeprecatedItems(definition, result, stack) { | ||
for (const key of Object.keys(definition)) { | ||
const item = definition[key] | ||
if (key === "$call") { | ||
result.push(`${stack.join(".")}()`) | ||
} | ||
else if (key === "$constructor") { | ||
result.push(`new ${stack.join(".")}()`) | ||
} | ||
else { | ||
stack.push(key) | ||
if (item.$deprecated) { | ||
result.push(stack.join(".")) | ||
} | ||
else { | ||
getDeprecatedItems(item, result, stack) | ||
} | ||
stack.pop() | ||
} | ||
} | ||
return result | ||
} | ||
/** | ||
* Converts from a version number to a version text to display. | ||
@@ -50,3 +90,3 @@ * | ||
function toReplaceMessage(replacedBy) { | ||
return replacedBy ? " Use " + replacedBy + " instead." : "" | ||
return replacedBy ? ` Use ${replacedBy} instead.` : "" | ||
} | ||
@@ -85,12 +125,2 @@ | ||
/** | ||
* Checks a given reference is readable. | ||
* | ||
* @param {escope.Reference} reference - A reference to check. | ||
* @returns {boolean} `true` if the reference is readable. | ||
*/ | ||
function isReadReference(reference) { | ||
return reference.isRead() | ||
} | ||
/** | ||
* Checks a given node is a ImportDeclaration node. | ||
@@ -113,9 +143,8 @@ * | ||
function findVariable(node, initialScope) { | ||
var location = node.range[0] | ||
var variable = null | ||
const location = node.range[0] | ||
let variable = null | ||
// Dive into the scope that the node exists. | ||
for (var i = 0; i < initialScope.childScopes.length; ++i) { | ||
var childScope = initialScope.childScopes[i] | ||
var range = childScope.block.range | ||
for (const childScope of initialScope.childScopes) { | ||
const range = childScope.block.range | ||
@@ -131,3 +160,3 @@ if (range[0] <= location && location < range[1]) { | ||
// Find the variable of that name in this scope or ancestor scopes. | ||
var scope = initialScope | ||
let scope = initialScope | ||
while (scope != null) { | ||
@@ -146,19 +175,32 @@ variable = scope.set.get(node.name) | ||
/** | ||
* Traverses the references of a given variable as calling a given predicate. | ||
* Gets the top member expression node. | ||
* | ||
* @param {escope.Variable} variable - A variable to traverse references. | ||
* @param {function} f - A predicate to call. | ||
* @returns {void} | ||
* @param {ASTNode} identifier - The node to get. | ||
* @returns {ASTNode} The top member expression node. | ||
*/ | ||
function eachReadReferences(variable, f) { | ||
variable.references.filter(isReadReference).forEach(f) | ||
function getTopMemberExpression(identifier) { | ||
if (identifier.type !== "Identifier" && identifier.type !== "Literal") { | ||
return identifier | ||
} | ||
let node = identifier | ||
while (node.parent.type === "MemberExpression") { | ||
node = node.parent | ||
} | ||
return node | ||
} | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
/** | ||
* The definition of this rule. | ||
* | ||
* @param {RuleContext} context - The rule context to check. | ||
* @returns {object} The definition of this rule. | ||
*/ | ||
function create(context) { | ||
const options = context.options[0] || {} | ||
const ignoredModuleItems = options.ignoreModuleItems || [] | ||
const ignoredGlobalItems = options.ignoreGlobalItems || [] | ||
let globalScope = null | ||
module.exports = function(context) { | ||
var globalScope = null | ||
/** | ||
@@ -173,6 +215,6 @@ * Checks whether the third party module of the given module ID exists or | ||
try { | ||
var fileName = context.getFilename() | ||
const fileName = context.getFilename() | ||
if (fileName !== "<input>") { | ||
var basedir = dirname(fileName) | ||
return resolve(moduleId, {basedir: basedir}) !== moduleId | ||
const basedir = dirname(fileName) | ||
return resolve(moduleId, {basedir}) !== moduleId | ||
} | ||
@@ -197,6 +239,7 @@ } | ||
context.report({ | ||
node: node, | ||
node, | ||
loc: getTopMemberExpression(node).loc, | ||
message: "{{name}} was deprecated since v{{version}}.{{replace}}", | ||
data: { | ||
name: name, | ||
name, | ||
version: toVersionText(info.since), | ||
@@ -213,7 +256,9 @@ replace: toReplaceMessage(info.replacedBy), | ||
* @param {string} name - The name of a deprecated module. | ||
* @param {{since: number, replacedBy: string}} info - Information of the module. | ||
* @param {{since: number, replacedBy: string, global: boolean}} info - Information of the module. | ||
* @returns {void} | ||
*/ | ||
function reportModule(node, name, info) { | ||
report(node, "'" + name + "' module", info) | ||
if (ignoredModuleItems.indexOf(name) === -1) { | ||
report(node, `'${name}' module`, info) | ||
} | ||
} | ||
@@ -226,7 +271,29 @@ | ||
* @param {string[]} path - The path to a deprecated property. | ||
* @param {{since: number, replacedBy: string}} info - Information of the property. | ||
* @param {{since: number, replacedBy: string, global: boolean}} info - Information of the property. | ||
* @returns {void} | ||
*/ | ||
function reportCall(node, path, info) { | ||
const ignored = info.global ? ignoredGlobalItems : ignoredModuleItems | ||
const name = `${path.join(".")}()` | ||
if (ignored.indexOf(name) === -1) { | ||
report(node, `'${name}'`, info) | ||
} | ||
} | ||
/** | ||
* Reports a use of a deprecated property. | ||
* | ||
* @param {ASTNode} node - A node to report. | ||
* @param {string[]} path - The path to a deprecated property. | ||
* @param {{since: number, replacedBy: string, global: boolean}} info - Information of the property. | ||
* @returns {void} | ||
*/ | ||
function reportConstructor(node, path, info) { | ||
report(node, "'" + path.join(".") + "' constructor", info) | ||
const ignored = info.global ? ignoredGlobalItems : ignoredModuleItems | ||
const name = `new ${path.join(".")}()` | ||
if (ignored.indexOf(name) === -1) { | ||
report(node, `'${name}'`, info) | ||
} | ||
} | ||
@@ -240,7 +307,12 @@ | ||
* @param {string} key - The name of the property. | ||
* @param {{since: number, replacedBy: string}} info - Information of the property. | ||
* @param {{since: number, replacedBy: string, global: boolean}} info - Information of the property. | ||
* @returns {void} | ||
*/ | ||
function reportProperty(node, path, key, info) { | ||
report(node, "'" + path.join(".") + "." + key + "'", info) | ||
const ignored = info.global ? ignoredGlobalItems : ignoredModuleItems | ||
const name = `${path.join(".")}.${key}` | ||
if (ignored.indexOf(name) === -1) { | ||
report(node, `'${name}'`, info) | ||
} | ||
} | ||
@@ -262,4 +334,4 @@ | ||
case "Identifier": | ||
var variable = findVariable(node, globalScope) | ||
case "Identifier": { | ||
const variable = findVariable(node, globalScope) | ||
if (variable != null) { | ||
@@ -269,8 +341,8 @@ checkVariable(variable, path, infoMap) | ||
break | ||
} | ||
case "ObjectPattern": | ||
node.properties.forEach(function(property) { | ||
var key = getPropertyName(property) | ||
for (const property of node.properties) { | ||
const key = getPropertyName(property) | ||
if (key != null && hasOwnProperty.call(infoMap, key)) { | ||
var keyInfo = infoMap[key] | ||
const keyInfo = infoMap[key] | ||
if (keyInfo.$deprecated) { | ||
@@ -285,3 +357,3 @@ reportProperty(property.key, path, key, keyInfo) | ||
} | ||
}) | ||
} | ||
break | ||
@@ -302,3 +374,3 @@ | ||
function checkProperties(root, path, infoMap) { | ||
var node = root | ||
let node = root | ||
while (!SENTINEL_TYPE.test(node.parent.type)) { | ||
@@ -308,12 +380,13 @@ node = node.parent | ||
var parent = node.parent | ||
const parent = node.parent | ||
switch (parent.type) { | ||
case "CallExpression": | ||
if (parent.callee === node && infoMap.$call != null) { | ||
reportCall(parent, path, infoMap.$call) | ||
} | ||
break | ||
case "NewExpression": | ||
var ctorInfo = infoMap.$constructor | ||
if (parent.callee === node && | ||
ctorInfo != null && | ||
(parent.type === "NewExpression" || ctorInfo.omittableNew) | ||
) { | ||
reportConstructor(parent, path, ctorInfo) | ||
if (parent.callee === node && infoMap.$constructor != null) { | ||
reportConstructor(parent, path, infoMap.$constructor) | ||
} | ||
@@ -324,5 +397,5 @@ break | ||
if (parent.object === node) { | ||
var key = getPropertyName(parent) | ||
const key = getPropertyName(parent) | ||
if (key != null && hasOwnProperty.call(infoMap, key)) { | ||
var keyInfo = infoMap[key] | ||
const keyInfo = infoMap[key] | ||
if (keyInfo.$deprecated) { | ||
@@ -372,5 +445,5 @@ reportProperty(parent.property, path, key, keyInfo) | ||
function checkVariable(variable, path, infoMap) { | ||
eachReadReferences(variable, function(reference) { | ||
for (const reference of variable.references.filter(r => r.isRead())) { | ||
checkProperties(reference.identifier, path, infoMap) | ||
}) | ||
} | ||
} | ||
@@ -388,6 +461,6 @@ | ||
switch (node.type) { | ||
case "ImportSpecifier": | ||
var key = node.imported.name | ||
case "ImportSpecifier": { | ||
const key = node.imported.name | ||
if (hasOwnProperty.call(infoMap, key)) { | ||
var keyInfo = infoMap[key] | ||
const keyInfo = infoMap[key] | ||
if (keyInfo.$deprecated) { | ||
@@ -407,3 +480,3 @@ reportProperty(node.imported, path, key, keyInfo) | ||
break | ||
} | ||
case "ImportDefaultSpecifier": | ||
@@ -434,26 +507,28 @@ checkVariable( | ||
function checkCommonJsModules() { | ||
var infoMap = deprecatedApis.modules | ||
var variable = globalScope.set.get("require") | ||
const infoMap = deprecatedApis.modules | ||
const variable = globalScope.set.get("require") | ||
if (variable != null && variable.defs.length === 0) { | ||
eachReadReferences(variable, function(reference) { | ||
var id = reference.identifier | ||
var node = id.parent | ||
if (variable == null || variable.defs.length !== 0) { | ||
return | ||
} | ||
if (node.type === "CallExpression" && node.callee === id) { | ||
var key = getValueIfString(node.arguments[0]) | ||
if (key != null && | ||
hasOwnProperty.call(infoMap, key) && | ||
!isThirdPartyInstalled(key) | ||
) { | ||
var moduleInfo = infoMap[key] | ||
if (moduleInfo.$deprecated) { | ||
reportModule(node, key, moduleInfo) | ||
} | ||
else { | ||
checkProperties(node, [key], moduleInfo) | ||
} | ||
for (const reference of variable.references.filter(r => r.isRead())) { | ||
const id = reference.identifier | ||
const node = id.parent | ||
if (node.type === "CallExpression" && node.callee === id) { | ||
const key = getValueIfString(node.arguments[0]) | ||
if (key != null && | ||
hasOwnProperty.call(infoMap, key) && | ||
!isThirdPartyInstalled(key) | ||
) { | ||
const moduleInfo = infoMap[key] | ||
if (moduleInfo.$deprecated) { | ||
reportModule(node, key, moduleInfo) | ||
} | ||
else { | ||
checkProperties(node, [key], moduleInfo) | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
@@ -468,10 +543,10 @@ } | ||
function checkES2015Modules(programNode) { | ||
var infoMap = deprecatedApis.modules | ||
const infoMap = deprecatedApis.modules | ||
programNode.body.filter(isImportDeclaration).forEach(function(node) { | ||
var key = node.source.value | ||
for (const node of programNode.body.filter(isImportDeclaration)) { | ||
const key = node.source.value | ||
if (hasOwnProperty.call(infoMap, key) && | ||
!isThirdPartyInstalled(key) | ||
) { | ||
var moduleInfo = infoMap[key] | ||
const moduleInfo = infoMap[key] | ||
if (moduleInfo.$deprecated) { | ||
@@ -481,8 +556,8 @@ reportModule(node, key, moduleInfo) | ||
else { | ||
node.specifiers.forEach(function(specifier) { | ||
for (const specifier of node.specifiers) { | ||
checkImportSpecifier(specifier, [key], moduleInfo) | ||
}) | ||
} | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
@@ -495,7 +570,7 @@ | ||
function checkGlobals() { | ||
var infoMap = deprecatedApis.globals | ||
const infoMap = deprecatedApis.globals | ||
Object.keys(infoMap).forEach(function(key) { | ||
var keyInfo = infoMap[key] | ||
var variable = globalScope.set.get(key) | ||
for (const key of Object.keys(infoMap)) { | ||
const keyInfo = infoMap[key] | ||
const variable = globalScope.set.get(key) | ||
@@ -505,7 +580,7 @@ if (variable != null && variable.defs.length === 0) { | ||
} | ||
}) | ||
} | ||
} | ||
return { | ||
"Program:exit": function(node) { | ||
"Program:exit"(node) { | ||
globalScope = context.getScope() | ||
@@ -520,2 +595,36 @@ | ||
module.exports.schema = [] | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
module.exports = { | ||
create, | ||
meta: { | ||
docs: { | ||
description: "disallow deprecated APIs", | ||
category: "Best Practices", | ||
recommended: false, | ||
}, | ||
fixable: false, | ||
schema: [ | ||
{ | ||
type: "object", | ||
properties: { | ||
ignoreModuleItems: { | ||
type: "array", | ||
items: {enum: MODULE_ITEMS}, | ||
additionalItems: false, | ||
uniqueItems: true, | ||
}, | ||
ignoreGlobalItems: { | ||
type: "array", | ||
items: {enum: GLOBAL_ITEMS}, | ||
additionalItems: false, | ||
uniqueItems: true, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
} |
@@ -12,11 +12,19 @@ /** | ||
var checkExistence = require("../util/check-existence") | ||
var getImportExportTargets = require("../util/get-import-export-targets") | ||
const checkExistence = require("../util/check-existence") | ||
const getAllowModules = require("../util/get-allow-modules") | ||
const getImportExportTargets = require("../util/get-import-export-targets") | ||
const getTryExtensions = require("../util/get-try-extensions") | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// Helpers | ||
//------------------------------------------------------------------------------ | ||
module.exports = function(context) { | ||
var filePath = context.getFilename() | ||
/** | ||
* The definition of this rule. | ||
* | ||
* @param {RuleContext} context - The rule context to check. | ||
* @returns {object} The definition of this rule. | ||
*/ | ||
function create(context) { | ||
const filePath = context.getFilename() | ||
if (filePath === "<input>") { | ||
@@ -27,3 +35,3 @@ return {} | ||
return { | ||
"Program:exit": function(node) { | ||
"Program:exit"(node) { | ||
checkExistence( | ||
@@ -38,25 +46,26 @@ context, | ||
module.exports.schema = [ | ||
{ | ||
type: "object", | ||
properties: { | ||
allowModules: { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^(?:@[a-zA-Z0-9_\\-.]+/)?[a-zA-Z0-9_\\-.]+$", | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
module.exports = { | ||
create, | ||
meta: { | ||
docs: { | ||
description: "disallow import declarations for files that don't exist", | ||
category: "Possible Errors", | ||
recommended: false, | ||
}, | ||
fixable: false, | ||
schema: [ | ||
{ | ||
type: "object", | ||
properties: { | ||
allowModules: getAllowModules.schema, | ||
tryExtensions: getTryExtensions.schema, | ||
}, | ||
uniqueItems: true, | ||
additionalProperties: false, | ||
}, | ||
tryExtensions: { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^\\.", | ||
}, | ||
uniqueItems: true, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
], | ||
}, | ||
] | ||
} |
@@ -12,11 +12,19 @@ /** | ||
var checkExistence = require("../util/check-existence") | ||
var getRequireTargets = require("../util/get-require-targets") | ||
const checkExistence = require("../util/check-existence") | ||
const getAllowModules = require("../util/get-allow-modules") | ||
const getRequireTargets = require("../util/get-require-targets") | ||
const getTryExtensions = require("../util/get-try-extensions") | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// Helpers | ||
//------------------------------------------------------------------------------ | ||
module.exports = function(context) { | ||
var filePath = context.getFilename() | ||
/** | ||
* The definition of this rule. | ||
* | ||
* @param {RuleContext} context - The rule context to check. | ||
* @returns {object} The definition of this rule. | ||
*/ | ||
function create(context) { | ||
const filePath = context.getFilename() | ||
if (filePath === "<input>") { | ||
@@ -27,3 +35,3 @@ return {} | ||
return { | ||
"Program:exit": function() { | ||
"Program:exit"() { | ||
checkExistence( | ||
@@ -38,25 +46,26 @@ context, | ||
module.exports.schema = [ | ||
{ | ||
type: "object", | ||
properties: { | ||
allowModules: { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^(?:@[a-zA-Z0-9_\\-.]+/)?[a-zA-Z0-9_\\-.]+$", | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
module.exports = { | ||
create, | ||
meta: { | ||
docs: { | ||
description: "disallow `require()` expressions for files that don't exist", | ||
category: "Possible Errors", | ||
recommended: false, | ||
}, | ||
fixable: false, | ||
schema: [ | ||
{ | ||
type: "object", | ||
properties: { | ||
allowModules: getAllowModules.schema, | ||
tryExtensions: getTryExtensions.schema, | ||
}, | ||
uniqueItems: true, | ||
additionalProperties: false, | ||
}, | ||
tryExtensions: { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^\\.", | ||
}, | ||
uniqueItems: true, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
], | ||
}, | ||
] | ||
} |
@@ -12,6 +12,6 @@ /** | ||
var path = require("path") | ||
var getConvertPath = require("../util/get-convert-path") | ||
var getNpmignore = require("../util/get-npmignore") | ||
var getPackageJson = require("../util/get-package-json") | ||
const path = require("path") | ||
const getConvertPath = require("../util/get-convert-path") | ||
const getNpmignore = require("../util/get-npmignore") | ||
const getPackageJson = require("../util/get-package-json") | ||
@@ -37,7 +37,57 @@ //------------------------------------------------------------------------------ | ||
} | ||
return Object.keys(binField).some(function(key) { | ||
return filePath === path.resolve(basedir, binField[key]) | ||
}) | ||
return Object.keys(binField).some(key => filePath === path.resolve(basedir, binField[key])) | ||
} | ||
/** | ||
* The definition of this rule. | ||
* | ||
* @param {RuleContext} context - The rule context to check. | ||
* @returns {object} The definition of this rule. | ||
*/ | ||
function create(context) { | ||
return { | ||
Program(node) { | ||
// Check file path. | ||
let rawFilePath = context.getFilename() | ||
if (rawFilePath === "<input>") { | ||
return | ||
} | ||
rawFilePath = path.resolve(rawFilePath) | ||
// Find package.json | ||
const p = getPackageJson(rawFilePath) | ||
if (!p) { | ||
return | ||
} | ||
// Convert by convertPath option | ||
const basedir = path.dirname(p.filePath) | ||
const relativePath = getConvertPath(context)( | ||
path.relative(basedir, rawFilePath).replace(/\\/g, "/") | ||
) | ||
const filePath = path.join(basedir, relativePath) | ||
// Check this file is bin. | ||
if (!isBinFile(filePath, p.bin, basedir)) { | ||
return | ||
} | ||
// Check ignored or not | ||
const npmignore = getNpmignore(filePath) | ||
if (!npmignore.match(relativePath)) { | ||
return | ||
} | ||
// Report. | ||
context.report({ | ||
node, | ||
message: | ||
"npm ignores '{{name}}'. " + | ||
"Check 'files' field of 'package.json' or '.npmignore'.", | ||
data: {name: relativePath}, | ||
}) | ||
}, | ||
} | ||
} | ||
//------------------------------------------------------------------------------ | ||
@@ -48,2 +98,3 @@ // Rule Definition | ||
module.exports = { | ||
create, | ||
meta: { | ||
@@ -59,16 +110,4 @@ docs: { | ||
type: "object", | ||
properties: { | ||
convertPath: { | ||
type: "object", | ||
properties: {}, | ||
patternProperties: { | ||
"^.+$": { | ||
type: "array", | ||
items: {type: "string"}, | ||
minItems: 2, | ||
maxItems: 2, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
properties: { // | ||
convertPath: getConvertPath.schema, | ||
}, | ||
@@ -78,48 +117,2 @@ }, | ||
}, | ||
create: function(context) { | ||
return { | ||
Program: function(node) { | ||
// Check file path. | ||
var rawFilePath = context.getFilename() | ||
if (rawFilePath === "<input>") { | ||
return | ||
} | ||
rawFilePath = path.resolve(rawFilePath) | ||
// Find package.json | ||
var p = getPackageJson(rawFilePath) | ||
if (!p) { | ||
return | ||
} | ||
// Convert by convertPath option | ||
var basedir = path.dirname(p.filePath) | ||
var relativePath = getConvertPath(context)( | ||
path.relative(basedir, rawFilePath).replace(/\\/g, "/") | ||
) | ||
var filePath = path.join(basedir, relativePath) | ||
// Check this file is bin. | ||
if (!isBinFile(filePath, p.bin, basedir)) { | ||
return | ||
} | ||
// Check ignored or not | ||
var npmignore = getNpmignore(filePath) | ||
if (!npmignore.match(relativePath)) { | ||
return | ||
} | ||
// Report. | ||
context.report({ | ||
node: node, | ||
message: | ||
"npm ignores '{{name}}'. " + | ||
"Check 'files' field of 'package.json' or '.npmignore'.", | ||
data: {name: relativePath}, | ||
}) | ||
}, | ||
} | ||
}, | ||
} |
@@ -12,11 +12,20 @@ /** | ||
var checkPublish = require("../util/check-publish") | ||
var getImportExportTargets = require("../util/get-import-export-targets") | ||
const checkPublish = require("../util/check-publish") | ||
const getAllowModules = require("../util/get-allow-modules") | ||
const getConvertPath = require("../util/get-convert-path") | ||
const getImportExportTargets = require("../util/get-import-export-targets") | ||
const getTryExtensions = require("../util/get-try-extensions") | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// Helpers | ||
//------------------------------------------------------------------------------ | ||
module.exports = function(context) { | ||
var filePath = context.getFilename() | ||
/** | ||
* The definition of this rule. | ||
* | ||
* @param {RuleContext} context - The rule context to check. | ||
* @returns {object} The definition of this rule. | ||
*/ | ||
function create(context) { | ||
const filePath = context.getFilename() | ||
if (filePath === "<input>") { | ||
@@ -27,3 +36,3 @@ return {} | ||
return { | ||
"Program:exit": function(node) { | ||
"Program:exit"(node) { | ||
checkPublish( | ||
@@ -38,38 +47,27 @@ context, | ||
module.exports.schema = [ | ||
{ | ||
type: "object", | ||
properties: { | ||
allowModules: { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^(?:@[a-zA-Z0-9_\\-.]+/)?[a-zA-Z0-9_\\-.]+$", | ||
}, | ||
uniqueItems: true, | ||
}, | ||
convertPath: { | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
module.exports = { | ||
create, | ||
meta: { | ||
docs: { | ||
description: "disallow import declarations for files that npm ignores", | ||
category: "Possible Errors", | ||
recommended: false, | ||
}, | ||
fixable: false, | ||
schema: [ | ||
{ | ||
type: "object", | ||
properties: {}, | ||
patternProperties: { | ||
"^.+$": { | ||
type: "array", | ||
items: {type: "string"}, | ||
minItems: 2, | ||
maxItems: 2, | ||
}, | ||
properties: { | ||
allowModules: getAllowModules.schema, | ||
convertPath: getConvertPath.schema, | ||
tryExtensions: getTryExtensions.schema, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
tryExtensions: { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^\\.", | ||
}, | ||
uniqueItems: true, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
], | ||
}, | ||
] | ||
} |
@@ -12,11 +12,20 @@ /** | ||
var checkPublish = require("../util/check-publish") | ||
var getRequireTargets = require("../util/get-require-targets") | ||
const checkPublish = require("../util/check-publish") | ||
const getAllowModules = require("../util/get-allow-modules") | ||
const getConvertPath = require("../util/get-convert-path") | ||
const getRequireTargets = require("../util/get-require-targets") | ||
const getTryExtensions = require("../util/get-try-extensions") | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// Helpers | ||
//------------------------------------------------------------------------------ | ||
module.exports = function(context) { | ||
var filePath = context.getFilename() | ||
/** | ||
* The definition of this rule. | ||
* | ||
* @param {RuleContext} context - The rule context to check. | ||
* @returns {object} The definition of this rule. | ||
*/ | ||
function create(context) { | ||
const filePath = context.getFilename() | ||
if (filePath === "<input>") { | ||
@@ -27,3 +36,3 @@ return {} | ||
return { | ||
"Program:exit": function() { | ||
"Program:exit"() { | ||
checkPublish( | ||
@@ -38,38 +47,27 @@ context, | ||
module.exports.schema = [ | ||
{ | ||
type: "object", | ||
properties: { | ||
allowModules: { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^(?:@[a-zA-Z0-9_\\-.]+/)?[a-zA-Z0-9_\\-.]+$", | ||
}, | ||
uniqueItems: true, | ||
}, | ||
convertPath: { | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
module.exports = { | ||
create, | ||
meta: { | ||
docs: { | ||
description: "disallow `require()` expressions for files that npm ignores", | ||
category: "Possible Errors", | ||
recommended: false, | ||
}, | ||
fixable: false, | ||
schema: [ | ||
{ | ||
type: "object", | ||
properties: {}, | ||
patternProperties: { | ||
"^.+$": { | ||
type: "array", | ||
items: {type: "string"}, | ||
minItems: 2, | ||
maxItems: 2, | ||
}, | ||
properties: { | ||
allowModules: getAllowModules.schema, | ||
convertPath: getConvertPath.schema, | ||
tryExtensions: getTryExtensions.schema, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
tryExtensions: { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^\\.", | ||
}, | ||
uniqueItems: true, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
], | ||
}, | ||
] | ||
} |
@@ -12,6 +12,6 @@ /** | ||
var semver = require("semver") | ||
var features = require("../util/features") | ||
var getPackageJson = require("../util/get-package-json") | ||
var getValueIfString = require("../util/get-value-if-string") | ||
const semver = require("semver") | ||
const features = require("../util/features") | ||
const getPackageJson = require("../util/get-package-json") | ||
const getValueIfString = require("../util/get-value-if-string") | ||
@@ -22,13 +22,13 @@ //------------------------------------------------------------------------------ | ||
var VERSIONS = [0.10, 0.12, 4, 5, 6, 7] | ||
var OPTIONS = Object.keys(features) | ||
var FUNC_TYPE = /^(?:Arrow)?Function(?:Declaration|Expression)$/ | ||
var CLASS_TYPE = /^Class(?:Declaration|Expression)$/ | ||
var DESTRUCTURING_PARENT_TYPE = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression|AssignmentExpression|VariableDeclarator)$/ | ||
var TOPLEVEL_SCOPE_TYPE = /^(?:global|function|module)$/ | ||
var BINARY_NUMBER = /^0[bB]/ | ||
var OCTAL_NUMBER = /^0[oO]/ | ||
var UNICODE_ESC = /(\\+)u\{[0-9a-fA-F]+?\}/g | ||
var GET_OR_SET = /^(?:g|s)et$/ | ||
var NEW_BUILTIN_TYPES = [ | ||
const VERSIONS = [0.10, 0.12, 4, 5, 6, 7] | ||
const OPTIONS = Object.keys(features) | ||
const FUNC_TYPE = /^(?:Arrow)?Function(?:Declaration|Expression)$/ | ||
const CLASS_TYPE = /^Class(?:Declaration|Expression)$/ | ||
const DESTRUCTURING_PARENT_TYPE = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression|AssignmentExpression|VariableDeclarator)$/ | ||
const TOPLEVEL_SCOPE_TYPE = /^(?:global|function|module)$/ | ||
const BINARY_NUMBER = /^0[bB]/ | ||
const OCTAL_NUMBER = /^0[oO]/ | ||
const UNICODE_ESC = /(\\+)u\{[0-9a-fA-F]+?\}/g | ||
const GET_OR_SET = /^(?:g|s)et$/ | ||
const NEW_BUILTIN_TYPES = [ | ||
"Int8Array", "Uint8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array", | ||
@@ -38,7 +38,7 @@ "Int32Array", "Uint32Array", "Float32Array", "Float64Array", "DataView", | ||
] | ||
var SUBCLASSING_TEST_TARGETS = [ | ||
const SUBCLASSING_TEST_TARGETS = [ | ||
"Array", "RegExp", "Function", "Promise", "Boolean", "Number", "String", | ||
"Map", "Set", | ||
] | ||
var PROPERTY_TEST_TARGETS = { | ||
const PROPERTY_TEST_TARGETS = { | ||
Object: [ | ||
@@ -72,4 +72,4 @@ "assign", "is", "getOwnPropertySymbols", "setPrototypeOf", "values", | ||
function parseVersion(comparator) { | ||
var major = comparator.semver.major | ||
var minor = comparator.semver.minor | ||
const major = comparator.semver.major | ||
const minor = comparator.semver.minor | ||
@@ -80,3 +80,3 @@ if (major >= 1) { | ||
if (minor >= 10) { | ||
return parseFloat("0." + minor) | ||
return parseFloat(`0.${minor}`) | ||
} | ||
@@ -96,11 +96,11 @@ return 0.10 | ||
function getDefaultVersion(filename) { | ||
var info = getPackageJson(filename) | ||
var nodeVersion = info && info.engines && info.engines.node | ||
const info = getPackageJson(filename) | ||
const nodeVersion = info && info.engines && info.engines.node | ||
try { | ||
var range = new semver.Range(nodeVersion) | ||
var comparators = Array.prototype.concat.apply([], range.set) | ||
var version = comparators.reduce( | ||
function(minVersion, comparator) { | ||
var op = comparator.operator | ||
const range = new semver.Range(nodeVersion) | ||
const comparators = Array.prototype.concat.apply([], range.set) | ||
const version = comparators.reduce( | ||
(minVersion, comparator) => { | ||
const op = comparator.operator | ||
@@ -133,6 +133,6 @@ if (op === "" || op === ">" || op === ">=") { | ||
return Object.keys(OPTIONS.reduce( | ||
function(retv, key) { | ||
features[key].alias.forEach(function(alias) { | ||
(retv, key) => { | ||
for (const alias of features[key].alias) { | ||
retv[alias] = true | ||
}) | ||
} | ||
retv[key] = true | ||
@@ -155,5 +155,3 @@ return retv | ||
ignores.indexOf(key) !== -1 || | ||
features[key].alias.some(function(alias) { | ||
return ignores.indexOf(alias) !== -1 | ||
}) | ||
features[key].alias.some(alias => ignores.indexOf(alias) !== -1) | ||
) | ||
@@ -170,4 +168,4 @@ } | ||
function parseOptions(options, defaultVersion) { | ||
var version = 0 | ||
var ignores = null | ||
let version = 0 | ||
let ignores = null | ||
@@ -190,4 +188,4 @@ if (typeof options === "number") { | ||
features: Object.freeze(OPTIONS.reduce( | ||
function(retv, key) { | ||
var feature = features[key] | ||
(retv, key) => { | ||
const feature = features[key] | ||
@@ -234,4 +232,4 @@ if (isIgnored(key, ignores)) { | ||
function checkSpecialLexicalEnvironment(context) { | ||
var parserOptions = context.parserOptions | ||
var ecmaFeatures = parserOptions.ecmaFeatures | ||
const parserOptions = context.parserOptions | ||
const ecmaFeatures = parserOptions.ecmaFeatures | ||
return Boolean( | ||
@@ -260,3 +258,3 @@ parserOptions.sourceType === "module" || | ||
function hasUnicodeCodePointEscape(raw) { | ||
var match = null | ||
let match = null | ||
@@ -273,30 +271,30 @@ UNICODE_ESC.lastIndex = 0 | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
module.exports = function(context) { | ||
var sourceCode = context.getSourceCode() | ||
var supportInfo = parseOptions( | ||
/** | ||
* The definition of this rule. | ||
* | ||
* @param {RuleContext} context - The rule context to check. | ||
* @returns {object} The definition of this rule. | ||
*/ | ||
function create(context) { | ||
const sourceCode = context.getSourceCode() | ||
const supportInfo = parseOptions( | ||
context.options[0], | ||
getDefaultVersion(context.getFilename()) | ||
) | ||
var hasSpecialLexicalEnvironment = checkSpecialLexicalEnvironment(context) | ||
const hasSpecialLexicalEnvironment = checkSpecialLexicalEnvironment(context) | ||
/** | ||
* Does an given action for each reference of the specified global variables. | ||
* Gets the references of the specified global variables. | ||
* | ||
* @param {string[]} names - Variable names to get. | ||
* @param {function} f - An action for each reference. | ||
* @returns {void} | ||
*/ | ||
function eachReferences(names, f) { | ||
var globalScope = context.getScope() | ||
function* getReferences(names) { | ||
const globalScope = context.getScope() | ||
for (var i = 0; i < names.length; ++i) { | ||
var name = names[i] | ||
var variable = globalScope.set.get(name) | ||
for (const name of names) { | ||
const variable = globalScope.set.get(name) | ||
if (variable && variable.defs.length === 0) { | ||
variable.references.forEach(f) | ||
yield* variable.references | ||
} | ||
@@ -313,3 +311,3 @@ } | ||
function isStrict() { | ||
var scope = context.getScope() | ||
let scope = context.getScope() | ||
if (scope.type === "global" && hasSpecialLexicalEnvironment) { | ||
@@ -328,3 +326,3 @@ scope = scope.childScopes[0] | ||
function hasTrailingCommaForFunction(node) { | ||
var length = node.params.length | ||
const length = node.params.length | ||
@@ -372,4 +370,4 @@ return ( | ||
function report(node, key) { | ||
var version = supportInfo.version | ||
var feature = supportInfo.features[key] | ||
const version = supportInfo.version | ||
const feature = supportInfo.features[key] | ||
if (feature.supported) { | ||
@@ -381,3 +379,3 @@ return | ||
context.report({ | ||
node: node, | ||
node, | ||
message: "{{feature}} {{be}} not supported yet on Node v{{version}}.", | ||
@@ -387,3 +385,3 @@ data: { | ||
be: feature.singular ? "is" : "are", | ||
version: version, | ||
version, | ||
}, | ||
@@ -394,8 +392,8 @@ }) | ||
context.report({ | ||
node: node, | ||
node, | ||
message: "{{feature}} {{be}} not supported yet on Node v{{version}}.", | ||
data: { | ||
feature: feature.name + " in non-strict mode", | ||
feature: `${feature.name} in non-strict mode`, | ||
be: feature.singular ? "is" : "are", | ||
version: version, | ||
version, | ||
}, | ||
@@ -411,44 +409,38 @@ }) | ||
"Program:exit": function() { | ||
"Program:exit"() { | ||
// Check new global variables. | ||
NEW_BUILTIN_TYPES.forEach(function(name) { | ||
eachReferences([name], function(reference) { | ||
for (const name of NEW_BUILTIN_TYPES) { | ||
for (const reference of getReferences([name])) { | ||
report(reference.identifier, name) | ||
}) | ||
}) | ||
} | ||
} | ||
// Check static methods. | ||
eachReferences( | ||
Object.keys(PROPERTY_TEST_TARGETS), | ||
function(reference) { | ||
var node = reference.identifier | ||
var parentNode = node.parent | ||
if (parentNode.type !== "MemberExpression" || | ||
parentNode.object !== node | ||
) { | ||
return | ||
} | ||
for (const reference of getReferences(Object.keys(PROPERTY_TEST_TARGETS))) { | ||
const node = reference.identifier | ||
const parentNode = node.parent | ||
if (parentNode.type !== "MemberExpression" || | ||
parentNode.object !== node | ||
) { | ||
continue | ||
} | ||
var objectName = node.name | ||
var properties = PROPERTY_TEST_TARGETS[objectName] | ||
var propertyName = (parentNode.computed ? getValueIfString : getIdentifierName)(parentNode.property) | ||
if (propertyName && properties.indexOf(propertyName) !== -1) { | ||
report(parentNode, objectName + "." + propertyName) | ||
} | ||
const objectName = node.name | ||
const properties = PROPERTY_TEST_TARGETS[objectName] | ||
const propertyName = (parentNode.computed ? getValueIfString : getIdentifierName)(parentNode.property) | ||
if (propertyName && properties.indexOf(propertyName) !== -1) { | ||
report(parentNode, `${objectName}.${propertyName}`) | ||
} | ||
) | ||
} | ||
// Check subclassing | ||
eachReferences( | ||
SUBCLASSING_TEST_TARGETS, | ||
function(reference) { | ||
var node = reference.identifier | ||
var parentNode = node.parent | ||
if (CLASS_TYPE.test(parentNode.type) && | ||
parentNode.superClass === node | ||
) { | ||
report(node, "extends" + node.name) | ||
} | ||
for (const reference of getReferences(SUBCLASSING_TEST_TARGETS)) { | ||
const node = reference.identifier | ||
const parentNode = node.parent | ||
if (CLASS_TYPE.test(parentNode.type) && | ||
parentNode.superClass === node | ||
) { | ||
report(node, `extends${node.name}`) | ||
} | ||
) | ||
} | ||
}, | ||
@@ -460,3 +452,3 @@ | ||
"ArrowFunctionExpression": function(node) { | ||
"ArrowFunctionExpression"(node) { | ||
report(node, "arrowFunctions") | ||
@@ -471,3 +463,3 @@ if (node.async) { | ||
"AssignmentPattern": function(node) { | ||
"AssignmentPattern"(node) { | ||
if (FUNC_TYPE.test(node.parent.type)) { | ||
@@ -478,4 +470,4 @@ report(node, "defaultParameters") | ||
"FunctionDeclaration": function(node) { | ||
var scope = context.getScope().upper | ||
"FunctionDeclaration"(node) { | ||
const scope = context.getScope().upper | ||
if (!TOPLEVEL_SCOPE_TYPE.test(scope.type)) { | ||
@@ -495,3 +487,3 @@ report(node, "blockScopedFunctions") | ||
"FunctionExpression": function(node) { | ||
"FunctionExpression"(node) { | ||
if (node.generator) { | ||
@@ -508,5 +500,5 @@ report(node, "generatorFunctions") | ||
"MetaProperty": function(node) { | ||
var meta = node.meta.name || node.meta | ||
var property = node.property.name || node.property | ||
"MetaProperty"(node) { | ||
const meta = node.meta.name || node.meta | ||
const property = node.property.name || node.property | ||
if (meta === "new" && property === "target") { | ||
@@ -517,3 +509,3 @@ report(node, "new.target") | ||
"RestElement": function(node) { | ||
"RestElement"(node) { | ||
if (FUNC_TYPE.test(node.parent.type)) { | ||
@@ -528,3 +520,3 @@ report(node, "restParameters") | ||
"ClassDeclaration": function(node) { | ||
"ClassDeclaration"(node) { | ||
report(node, "classes") | ||
@@ -537,3 +529,3 @@ | ||
"ClassExpression": function(node) { | ||
"ClassExpression"(node) { | ||
report(node, "classes") | ||
@@ -550,7 +542,7 @@ | ||
"ForOfStatement": function(node) { | ||
"ForOfStatement"(node) { | ||
report(node, "forOf") | ||
}, | ||
"VariableDeclaration": function(node) { | ||
"VariableDeclaration"(node) { | ||
if (node.kind === "const") { | ||
@@ -568,3 +560,3 @@ report(node, "const") | ||
"ArrayPattern": function(node) { | ||
"ArrayPattern"(node) { | ||
if (DESTRUCTURING_PARENT_TYPE.test(node.parent.type)) { | ||
@@ -575,3 +567,3 @@ report(node, "destructuring") | ||
"AssignmentExpression": function(node) { | ||
"AssignmentExpression"(node) { | ||
if (node.operator === "**=") { | ||
@@ -582,7 +574,7 @@ report(node, "exponentialOperators") | ||
"AwaitExpression": function(node) { | ||
"AwaitExpression"(node) { | ||
report(node, "asyncAwait") | ||
}, | ||
"BinaryExpression": function(node) { | ||
"BinaryExpression"(node) { | ||
if (node.operator === "**") { | ||
@@ -593,3 +585,3 @@ report(node, "exponentialOperators") | ||
"CallExpression": function(node) { | ||
"CallExpression"(node) { | ||
if (hasTrailingCommaForCall(node)) { | ||
@@ -600,4 +592,4 @@ report(node, "trailingCommasInFunctionSyntax") | ||
"Identifier": function(node) { | ||
var raw = sourceCode.getText(node) | ||
"Identifier"(node) { | ||
const raw = sourceCode.getText(node) | ||
if (hasUnicodeCodePointEscape(raw)) { | ||
@@ -608,3 +600,3 @@ report(node, "unicodeCodePointEscapes") | ||
"Literal": function(node) { | ||
"Literal"(node) { | ||
if (typeof node.value === "number") { | ||
@@ -633,3 +625,3 @@ if (BINARY_NUMBER.test(node.raw)) { | ||
"NewExpression": function(node) { | ||
"NewExpression"(node) { | ||
if (node.callee.type === "Identifier" && | ||
@@ -653,3 +645,3 @@ node.callee.name === "RegExp" && | ||
"ObjectPattern": function(node) { | ||
"ObjectPattern"(node) { | ||
if (DESTRUCTURING_PARENT_TYPE.test(node.parent.type)) { | ||
@@ -660,3 +652,3 @@ report(node, "destructuring") | ||
"Property": function(node) { | ||
"Property"(node) { | ||
if (node.parent.type === "ObjectExpression" && | ||
@@ -674,7 +666,7 @@ (node.computed || node.shorthand || node.method) | ||
"SpreadElement": function(node) { | ||
"SpreadElement"(node) { | ||
report(node, "spreadOperators", 5) | ||
}, | ||
"TemplateLiteral": function(node) { | ||
"TemplateLiteral"(node) { | ||
report(node, "templateStrings") | ||
@@ -687,15 +679,15 @@ }, | ||
"ExportAllDeclaration": function(node) { | ||
"ExportAllDeclaration"(node) { | ||
report(node, "modules") | ||
}, | ||
"ExportDefaultDeclaration": function(node) { | ||
"ExportDefaultDeclaration"(node) { | ||
report(node, "modules") | ||
}, | ||
"ExportNamedDeclaration": function(node) { | ||
"ExportNamedDeclaration"(node) { | ||
report(node, "modules") | ||
}, | ||
"ImportDeclaration": function(node) { | ||
"ImportDeclaration"(node) { | ||
report(node, "modules") | ||
@@ -706,20 +698,35 @@ }, | ||
module.exports.schema = [ | ||
{ | ||
oneOf: [ | ||
{enum: VERSIONS}, | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
module.exports = { | ||
create, | ||
meta: { | ||
docs: { | ||
description: "disallow unsupported ECMAScript features on the specified version", | ||
category: "Possible Errors", | ||
recommended: false, | ||
}, | ||
fixable: false, | ||
schema: [ | ||
{ | ||
type: "object", | ||
properties: { | ||
version: {enum: VERSIONS}, | ||
ignores: { | ||
type: "array", | ||
items: {enum: getIgnoresEnum()}, | ||
uniqueItems: true, | ||
oneOf: [ | ||
{enum: VERSIONS}, | ||
{ | ||
type: "object", | ||
properties: { | ||
version: {enum: VERSIONS}, | ||
ignores: { | ||
type: "array", | ||
items: {enum: getIgnoresEnum()}, | ||
uniqueItems: true, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
], | ||
}, | ||
], | ||
}, | ||
] | ||
} |
@@ -12,5 +12,5 @@ /** | ||
var CodePathAnalyzer = safeRequire("eslint/lib/code-path-analysis/code-path-analyzer") | ||
var CodePath = safeRequire("eslint/lib/code-path-analysis/code-path") | ||
var CodePathSegment = safeRequire("eslint/lib/code-path-analysis/code-path-segment") | ||
const CodePathAnalyzer = safeRequire("eslint/lib/code-path-analysis/code-path-analyzer") | ||
const CodePath = safeRequire("eslint/lib/code-path-analysis/code-path") | ||
const CodePathSegment = safeRequire("eslint/lib/code-path-analysis/code-path-segment") | ||
@@ -21,3 +21,3 @@ //------------------------------------------------------------------------------ | ||
var originalLeaveNode = CodePathAnalyzer && CodePathAnalyzer.prototype.leaveNode | ||
const originalLeaveNode = CodePathAnalyzer && CodePathAnalyzer.prototype.leaveNode | ||
@@ -48,10 +48,10 @@ /** | ||
function forwardCurrentToHead(analyzer, node) { | ||
var codePath = analyzer.codePath | ||
var state = CodePath.getState(codePath) | ||
var currentSegments = state.currentSegments | ||
var headSegments = state.headSegments | ||
var end = Math.max(currentSegments.length, headSegments.length) | ||
var i = 0 | ||
var currentSegment = null | ||
var headSegment = null | ||
const codePath = analyzer.codePath | ||
const state = CodePath.getState(codePath) | ||
const currentSegments = state.currentSegments | ||
const headSegments = state.headSegments | ||
const end = Math.max(currentSegments.length, headSegments.length) | ||
let i = 0 | ||
let currentSegment = null | ||
let headSegment = null | ||
@@ -134,3 +134,3 @@ // Fires leaving events. | ||
var visitor = CodePathAnalyzer == null ? {} : { | ||
const visitor = CodePathAnalyzer == null ? {} : { | ||
"Program": function installProcessExitAsThrow() { | ||
@@ -150,8 +150,14 @@ CodePathAnalyzer.prototype.leaveNode = overrideLeaveNode | ||
meta: { | ||
docs: { | ||
description: "make the same code path as `throw` at `process.exit()`", | ||
category: "Possible Errors", | ||
recommended: false, | ||
}, | ||
fixable: false, | ||
schema: [], | ||
supported: CodePathAnalyzer != null, | ||
schema: [], | ||
}, | ||
create: function() { | ||
create() { | ||
return visitor | ||
}, | ||
} |
@@ -12,5 +12,5 @@ /** | ||
var path = require("path") | ||
var getConvertPath = require("../util/get-convert-path") | ||
var getPackageJson = require("../util/get-package-json") | ||
const path = require("path") | ||
const getConvertPath = require("../util/get-convert-path") | ||
const getPackageJson = require("../util/get-package-json") | ||
@@ -21,5 +21,5 @@ //------------------------------------------------------------------------------ | ||
var NODE_SHEBANG = "#!/usr/bin/env node\n" | ||
var SHEBANG_PATTERN = /^(#!.+?)?(\r)?\n/ | ||
var NODE_SHEBANG_PATTERN = /#!\/usr\/bin\/env node(?: [^\r\n]+?)?\n/ | ||
const NODE_SHEBANG = "#!/usr/bin/env node\n" | ||
const SHEBANG_PATTERN = /^(#!.+?)?(\r)?\n/ | ||
const NODE_SHEBANG_PATTERN = /#!\/usr\/bin\/env node(?: [^\r\n]+?)?\n/ | ||
@@ -41,5 +41,3 @@ /** | ||
} | ||
return Object.keys(binField).some(function(key) { | ||
return filePath === path.resolve(basedir, binField[key]) | ||
}) | ||
return Object.keys(binField).some(key => filePath === path.resolve(basedir, binField[key])) | ||
} | ||
@@ -56,3 +54,3 @@ | ||
function getShebangInfo(sourceCode) { | ||
var m = SHEBANG_PATTERN.exec(sourceCode.text) | ||
const m = SHEBANG_PATTERN.exec(sourceCode.text) | ||
@@ -63,13 +61,15 @@ return { | ||
length: (m && m[0].length) || 0, | ||
shebang: (m && m[1] && (m[1] + "\n")) || "", | ||
shebang: (m && m[1] && (`${m[1]}\n`)) || "", | ||
} | ||
} | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
module.exports = function(context) { | ||
var sourceCode = context.getSourceCode() | ||
var filePath = context.getFilename() | ||
/** | ||
* The definition of this rule. | ||
* | ||
* @param {RuleContext} context - The rule context to check. | ||
* @returns {object} The definition of this rule. | ||
*/ | ||
function create(context) { | ||
const sourceCode = context.getSourceCode() | ||
let filePath = context.getFilename() | ||
if (filePath === "<input>") { | ||
@@ -80,3 +80,3 @@ return {} | ||
var p = getPackageJson(filePath) | ||
const p = getPackageJson(filePath) | ||
if (!p) { | ||
@@ -86,3 +86,3 @@ return {} | ||
var basedir = path.dirname(p.filePath) | ||
const basedir = path.dirname(p.filePath) | ||
filePath = path.join( | ||
@@ -93,7 +93,7 @@ basedir, | ||
var needsShebang = isBinFile(filePath, p.bin, basedir) | ||
var info = getShebangInfo(sourceCode) | ||
const needsShebang = isBinFile(filePath, p.bin, basedir) | ||
const info = getShebangInfo(sourceCode) | ||
return { | ||
Program: function(node) { | ||
Program(node) { | ||
if (needsShebang ? NODE_SHEBANG_PATTERN.test(info.shebang) : !info.shebang) { | ||
@@ -104,5 +104,5 @@ // Good the shebang target. | ||
context.report({ | ||
node: node, | ||
node, | ||
message: "This file must not have Unicode BOM.", | ||
fix: function(fixer) { | ||
fix(fixer) { | ||
return fixer.removeRange([-1, 0]) | ||
@@ -114,6 +114,6 @@ }, | ||
context.report({ | ||
node: node, | ||
node, | ||
message: "This file must have Unix linebreaks (LF).", | ||
fix: function(fixer) { | ||
var index = sourceCode.text.indexOf("\r") | ||
fix(fixer) { | ||
const index = sourceCode.text.indexOf("\r") | ||
return fixer.removeRange([index, index + 1]) | ||
@@ -127,5 +127,5 @@ }, | ||
context.report({ | ||
node: node, | ||
node, | ||
message: "This file needs shebang \"#!/usr/bin/env node\".", | ||
fix: function(fixer) { | ||
fix(fixer) { | ||
return fixer.replaceTextRange([-1, info.length], NODE_SHEBANG) | ||
@@ -138,5 +138,5 @@ }, | ||
context.report({ | ||
node: node, | ||
node, | ||
message: "This file needs no shebang.", | ||
fix: function(fixer) { | ||
fix(fixer) { | ||
return fixer.removeRange([0, info.length]) | ||
@@ -150,19 +150,25 @@ }, | ||
module.exports.schema = [ | ||
{ | ||
type: "object", | ||
properties: { | ||
convertPath: { | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
module.exports = { | ||
create, | ||
meta: { | ||
docs: { | ||
description: "enforce the correct usage of shebang", | ||
category: "Possible Errors", | ||
recommended: false, | ||
}, | ||
fixable: "code", | ||
schema: [ | ||
{ | ||
type: "object", | ||
properties: {}, | ||
additionalProperties: { | ||
type: "array", | ||
items: {type: "string"}, | ||
minItems: 2, | ||
maxItems: 2, | ||
properties: { // | ||
convertPath: getConvertPath.schema, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
], | ||
}, | ||
] | ||
} |
@@ -12,3 +12,3 @@ /** | ||
var SKIP_TIME = 5000 | ||
const SKIP_TIME = 5000 | ||
@@ -26,3 +26,3 @@ //------------------------------------------------------------------------------ | ||
*/ | ||
var Cache = module.exports = function Cache() { | ||
const Cache = module.exports = function Cache() { | ||
this.map = Object.create(null) | ||
@@ -34,4 +34,4 @@ } | ||
value: function get(key) { | ||
var entry = this.map[key] | ||
var now = Date.now() | ||
const entry = this.map[key] | ||
const now = Date.now() | ||
@@ -50,4 +50,4 @@ if (entry && entry.expire - now > 0) { | ||
value: function put(key, value) { | ||
var entry = this.map[key] | ||
var now = Date.now() | ||
const entry = this.map[key] | ||
const now = Date.now() | ||
@@ -60,3 +60,3 @@ if (entry) { | ||
this.map[key] = { | ||
value: value, | ||
value, | ||
expire: now + SKIP_TIME, | ||
@@ -63,0 +63,0 @@ } |
@@ -13,6 +13,6 @@ /** | ||
var path = require("path") | ||
var resolve = require("resolve") | ||
var exists = require("./exists") | ||
var getAllowModules = require("./get-allow-modules") | ||
const path = require("path") | ||
const resolve = require("resolve") | ||
const exists = require("./exists") | ||
const getAllowModules = require("./get-allow-modules") | ||
@@ -35,8 +35,6 @@ //------------------------------------------------------------------------------ | ||
module.exports = function checkForExistence(context, filePath, targets) { | ||
var allowed = getAllowModules(context) | ||
var opts = {basedir: path.dirname(path.resolve(filePath))} | ||
const allowed = getAllowModules(context) | ||
const opts = {basedir: path.dirname(path.resolve(filePath))} | ||
for (var i = 0; i < targets.length; ++i) { | ||
var target = targets[i] | ||
for (const target of targets) { | ||
// Workaround for https://github.com/substack/node-resolve/issues/78 | ||
@@ -63,2 +61,3 @@ if (target.filePath) { | ||
node: target.node, | ||
loc: target.node.loc, | ||
message: "\"{{name}}\" is not found.", | ||
@@ -65,0 +64,0 @@ data: target, |
@@ -13,8 +13,8 @@ /** | ||
var path = require("path") | ||
var assign = require("object-assign") | ||
var getAllowModules = require("./get-allow-modules") | ||
var getConvertPath = require("./get-convert-path") | ||
var getNpmignore = require("./get-npmignore") | ||
var getPackageJson = require("./get-package-json") | ||
const path = require("path") | ||
const assign = require("object-assign") | ||
const getAllowModules = require("./get-allow-modules") | ||
const getConvertPath = require("./get-convert-path") | ||
const getNpmignore = require("./get-npmignore") | ||
const getPackageJson = require("./get-package-json") | ||
@@ -36,3 +36,3 @@ //------------------------------------------------------------------------------ | ||
module.exports = function checkForPublish(context, filePath, targets) { | ||
var packageInfo = getPackageJson(filePath) | ||
const packageInfo = getPackageJson(filePath) | ||
if (!packageInfo) { | ||
@@ -42,11 +42,11 @@ return | ||
var allowed = getAllowModules(context) | ||
var convertPath = getConvertPath(context) | ||
var basedir = path.dirname(packageInfo.filePath) | ||
var toRelative = function(fullPath) { // eslint-disable-line func-style | ||
var retv = path.relative(basedir, fullPath).replace(/\\/g, "/") | ||
const allowed = getAllowModules(context) | ||
const convertPath = getConvertPath(context) | ||
const basedir = path.dirname(packageInfo.filePath) | ||
const toRelative = function(fullPath) { // eslint-disable-line func-style | ||
const retv = path.relative(basedir, fullPath).replace(/\\/g, "/") | ||
return convertPath(retv) | ||
} | ||
var npmignore = getNpmignore(filePath) | ||
var dependencies = assign( | ||
const npmignore = getNpmignore(filePath) | ||
const dependencies = assign( | ||
Object.create(null), | ||
@@ -56,8 +56,8 @@ packageInfo.peerDependencies || {}, | ||
) | ||
var devDependencies = assign( | ||
const devDependencies = assign( | ||
Object.create(null), | ||
packageInfo.devDependencies || {} | ||
) | ||
var i = 0 | ||
var target = null | ||
let i = 0 | ||
let target = null | ||
@@ -76,2 +76,3 @@ if (npmignore.match(toRelative(filePath))) { | ||
node: target.node, | ||
loc: target.node.loc, | ||
message: "\"{{name}}\" is not published.", | ||
@@ -94,2 +95,3 @@ data: {name: target.moduleName}, | ||
node: target.node, | ||
loc: target.node.loc, | ||
message: "\"{{name}}\" is not published.", | ||
@@ -96,0 +98,0 @@ data: {name: target.moduleName || target.name}, |
@@ -20,4 +20,8 @@ /** | ||
replacedBy: "'buffer.Buffer.alloc()' or 'buffer.Buffer.from()' (use 'https://www.npmjs.com/package/safe-buffer' for '<6.0.0')", | ||
omittableNew: true, | ||
}, | ||
$call: { | ||
$deprecated: true, | ||
since: 6, | ||
replacedBy: "'buffer.Buffer.alloc()' or 'buffer.Buffer.from()' (use 'https://www.npmjs.com/package/safe-buffer' for '<6.0.0')", | ||
}, | ||
}, | ||
@@ -264,6 +268,12 @@ SlowBuffer: { | ||
$deprecated: true, | ||
global: true, | ||
since: 6, | ||
replacedBy: "'Buffer.alloc()' or 'Buffer.from()'", | ||
omittableNew: true, | ||
replacedBy: "'Buffer.alloc()' or 'Buffer.from()' (use 'https://www.npmjs.com/package/safe-buffer' for '<6.0.0')", | ||
}, | ||
$call: { | ||
$deprecated: true, | ||
global: true, | ||
since: 6, | ||
replacedBy: "'Buffer.alloc()' or 'Buffer.from()' (use 'https://www.npmjs.com/package/safe-buffer' for '<6.0.0')", | ||
}, | ||
}, | ||
@@ -273,2 +283,3 @@ Intl: { | ||
$deprecated: true, | ||
global: true, | ||
since: 7, | ||
@@ -281,2 +292,3 @@ replacedBy: null, | ||
$deprecated: true, | ||
global: true, | ||
since: 0.12, | ||
@@ -289,2 +301,3 @@ replacedBy: "compiling them ahead of time", | ||
$deprecated: true, | ||
global: true, | ||
since: 0.6, | ||
@@ -296,2 +309,3 @@ replacedBy: "'require(\"events\")'", | ||
$deprecated: true, | ||
global: true, | ||
since: 4, | ||
@@ -298,0 +312,0 @@ replacedBy: "'NODE_REPL_HISTORY'", |
@@ -12,3 +12,3 @@ /** | ||
var fs = require("fs") | ||
const fs = require("fs") | ||
@@ -15,0 +15,0 @@ //------------------------------------------------------------------------------ |
@@ -12,3 +12,3 @@ /** | ||
var DEFAULT_VALUE = Object.freeze([]) | ||
const DEFAULT_VALUE = Object.freeze([]) | ||
@@ -49,1 +49,10 @@ /** | ||
} | ||
module.exports.schema = { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^(?:@[a-zA-Z0-9_\\-.]+/)?[a-zA-Z0-9_\\-.]+$", | ||
}, | ||
uniqueItems: true, | ||
} |
@@ -12,3 +12,3 @@ /** | ||
var Minimatch = require("minimatch").Minimatch | ||
const Minimatch = require("minimatch").Minimatch | ||
@@ -28,2 +28,49 @@ //------------------------------------------------------------------------------ | ||
/** | ||
* Converts old-style value to new-style value. | ||
* | ||
* @param {any} x - The value to convert. | ||
* @returns {({include: string[], exclude: string[], replace: string[]})[]} Normalized value. | ||
*/ | ||
function normalizeValue(x) { | ||
if (Array.isArray(x)) { | ||
return x | ||
} | ||
return Object.keys(x).map(pattern => ({ | ||
include: [pattern], | ||
exclude: [], | ||
replace: x[pattern], | ||
})) | ||
} | ||
/** | ||
* Ensures the given value is a string array. | ||
* | ||
* @param {any} x - The value to ensure. | ||
* @returns {string[]} The string array. | ||
*/ | ||
function toStringArray(x) { | ||
if (Array.isArray(x)) { | ||
return x.map(String) | ||
} | ||
return [] | ||
} | ||
/** | ||
* Creates the function which checks whether a file path is matched with the given pattern or not. | ||
* | ||
* @param {string[]} includePatterns - The glob patterns to include files. | ||
* @param {string[]} excludePatterns - The glob patterns to exclude files. | ||
* @returns {function} Created predicate function. | ||
*/ | ||
function createMatch(includePatterns, excludePatterns) { | ||
const include = includePatterns.map(pattern => new Minimatch(pattern)) | ||
const exclude = excludePatterns.map(pattern => new Minimatch(pattern)) | ||
return (filePath) => | ||
include.some(m => m.match(filePath)) && | ||
!exclude.some(m => m.match(filePath)) | ||
} | ||
/** | ||
* Creates a function which replaces a given path. | ||
@@ -36,5 +83,4 @@ * | ||
function defineConvert(fromRegexp, toStr) { | ||
return function(filePath) { | ||
return filePath.replace(fromRegexp, toStr) | ||
} | ||
return (filePath) => | ||
filePath.replace(fromRegexp, toStr) | ||
} | ||
@@ -50,6 +96,4 @@ | ||
function combine(converters) { | ||
return function(filePath) { | ||
for (var i = 0; i < converters.length; ++i) { | ||
var converter = converters[i] | ||
return (filePath) => { | ||
for (const converter of converters) { | ||
if (converter.match(filePath)) { | ||
@@ -77,13 +121,11 @@ return converter.convert(filePath) | ||
var converters = [] | ||
var patterns = Object.keys(option.convertPath) | ||
for (var i = 0; i < patterns.length; ++i) { | ||
var pattern = patterns[i] | ||
var replacer = option.convertPath[pattern] || [] | ||
var matcher = new Minimatch(pattern) | ||
var fromRegexp = new RegExp(String(replacer[0])) | ||
var toStr = String(replacer[1]) | ||
const converters = [] | ||
for (const pattern of normalizeValue(option.convertPath)) { | ||
const include = toStringArray(pattern.include) | ||
const exclude = toStringArray(pattern.exclude) | ||
const fromRegexp = new RegExp(String(pattern.replace[0])) | ||
const toStr = String(pattern.replace[1]) | ||
converters.push({ | ||
match: matcher.match.bind(matcher), | ||
match: createMatch(include, exclude), | ||
convert: defineConvert(fromRegexp, toStr), | ||
@@ -117,1 +159,50 @@ }) | ||
} | ||
/** | ||
* JSON Schema for `convertPath` option. | ||
*/ | ||
module.exports.schema = { | ||
anyOf: [ | ||
{ | ||
type: "object", | ||
properties: {}, | ||
patternProperties: { | ||
"^.+$": { | ||
type: "array", | ||
items: {type: "string"}, | ||
minItems: 2, | ||
maxItems: 2, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
{ | ||
type: "array", | ||
items: { | ||
type: "object", | ||
properties: { | ||
include: { | ||
type: "array", | ||
items: {type: "string"}, | ||
minItems: 1, | ||
uniqueItems: true, | ||
}, | ||
exclude: { | ||
type: "array", | ||
items: {type: "string"}, | ||
uniqueItems: true, | ||
}, | ||
replace: { | ||
type: "array", | ||
items: {type: "string"}, | ||
minItems: 2, | ||
maxItems: 2, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
required: ["include", "replace"], | ||
}, | ||
minItems: 1, | ||
}, | ||
], | ||
} |
@@ -12,7 +12,7 @@ /** | ||
var path = require("path") | ||
var resolve = require("resolve") | ||
var getTryExtensions = require("./get-try-extensions") | ||
var ImportTarget = require("./import-target") | ||
var stripImportPathParams = require("./strip-import-path-params") | ||
const path = require("path") | ||
const resolve = require("resolve") | ||
const getTryExtensions = require("./get-try-extensions") | ||
const ImportTarget = require("./import-target") | ||
const stripImportPathParams = require("./strip-import-path-params") | ||
@@ -23,3 +23,3 @@ //------------------------------------------------------------------------------ | ||
var MODULE_TYPE = /^(?:Import|Export(?:Named|Default|All))Declaration$/ | ||
const MODULE_TYPE = /^(?:Import|Export(?:Named|Default|All))Declaration$/ | ||
@@ -40,10 +40,7 @@ //------------------------------------------------------------------------------ | ||
module.exports = function getImportExportTargets(context, programNode) { | ||
var retv = [] | ||
var basedir = path.dirname(path.resolve(context.getFilename())) | ||
var statements = programNode.body | ||
var extensions = getTryExtensions(context) | ||
const retv = [] | ||
const basedir = path.dirname(path.resolve(context.getFilename())) | ||
const extensions = getTryExtensions(context) | ||
for (var i = 0; i < statements.length; ++i) { | ||
var statement = statements[i] | ||
for (const statement of programNode.body) { | ||
// Skip if it's not a module declaration. | ||
@@ -55,4 +52,4 @@ if (!MODULE_TYPE.test(statement.type)) { | ||
// Gets the target module. | ||
var node = statement.source | ||
var name = node && stripImportPathParams(node.value) | ||
const node = statement.source | ||
const name = node && stripImportPathParams(node.value) | ||
if (name && !resolve.isCore(name)) { | ||
@@ -59,0 +56,0 @@ retv.push(new ImportTarget(node, name, basedir, extensions)) |
@@ -12,8 +12,8 @@ /** | ||
var fs = require("fs") | ||
var path = require("path") | ||
var ignore = require("ignore") | ||
var Cache = require("./cache") | ||
var exists = require("./exists") | ||
var getPackageJson = require("./get-package-json") | ||
const fs = require("fs") | ||
const path = require("path") | ||
const ignore = require("ignore") | ||
const Cache = require("./cache") | ||
const exists = require("./exists") | ||
const getPackageJson = require("./get-package-json") | ||
@@ -24,6 +24,6 @@ //------------------------------------------------------------------------------ | ||
var cache = new Cache() | ||
var SLASH_AT_BEGIN_END = /(?:^\/+|\/+$)/g | ||
var PARENT_RELATIVE_PATH = /^\.\./ | ||
var NEVER_IGNORED = /^(?:readme\.[^.]*|(?:licen[cs]e|changes|changelog|history)(?:\.[^.]*)?)$/i | ||
const cache = new Cache() | ||
const SLASH_AT_BEGIN_END = /(?:^\/+|\/+$)/g | ||
const PARENT_RELATIVE_PATH = /^\.\./ | ||
const NEVER_IGNORED = /^(?:readme\.[^.]*|(?:licen[cs]e|changes|changelog|history)(?:\.[^.]*)?)$/i | ||
@@ -48,5 +48,3 @@ /** | ||
function and(f, g) { | ||
return function(filePath) { | ||
return f(filePath) && g(filePath) | ||
} | ||
return (filePath) => f(filePath) && g(filePath) | ||
} | ||
@@ -61,5 +59,3 @@ | ||
function or(f, g, h) { | ||
return function(filePath) { | ||
return f(filePath) || g(filePath) || (h && h(filePath)) | ||
} | ||
return (filePath) => f(filePath) || g(filePath) || (h && h(filePath)) | ||
} | ||
@@ -72,5 +68,3 @@ | ||
function not(f) { | ||
return function(filePath) { | ||
return !f(filePath) | ||
} | ||
return (filePath) => !f(filePath) | ||
} | ||
@@ -85,12 +79,10 @@ | ||
function filterNeverIgnoredFiles(p) { | ||
var basedir = path.dirname(p.filePath) | ||
var mainFilePath = (typeof p.main === "string") ? path.join(basedir, p.main) : null | ||
const basedir = path.dirname(p.filePath) | ||
const mainFilePath = (typeof p.main === "string") ? path.join(basedir, p.main) : null | ||
return function(filePath) { | ||
return ( | ||
path.join(basedir, filePath) !== mainFilePath && | ||
filePath !== "package.json" && | ||
!NEVER_IGNORED.test(path.basename(filePath)) | ||
) | ||
} | ||
return (filePath) => ( | ||
path.join(basedir, filePath) !== mainFilePath && | ||
filePath !== "package.json" && | ||
!NEVER_IGNORED.test(path.basename(filePath)) | ||
) | ||
} | ||
@@ -109,12 +101,10 @@ | ||
var ig = ignore() | ||
const ig = ignore() | ||
ig.add("*") | ||
for (var i = 0; i < files.length; ++i) { | ||
var file = files[i] | ||
for (const file of files) { | ||
if (typeof file === "string") { | ||
file = "/" + file.replace(SLASH_AT_BEGIN_END, "") | ||
ig.add("!" + file) | ||
ig.add("!" + file + "/**") | ||
const normalized = `/${file.replace(SLASH_AT_BEGIN_END, "")}` | ||
ig.add(`!${normalized}`) | ||
ig.add(`!${normalized}/**`) | ||
} | ||
@@ -134,3 +124,3 @@ } | ||
function parseNpmignore(basedir, filesFieldExists) { | ||
var filePath = path.join(basedir, ".npmignore") | ||
let filePath = path.join(basedir, ".npmignore") | ||
if (!exists(filePath)) { | ||
@@ -147,3 +137,3 @@ if (filesFieldExists) { | ||
var ig = ignore() | ||
const ig = ignore() | ||
ig.add(fs.readFileSync(filePath, "utf8")) | ||
@@ -171,7 +161,7 @@ return not(ig.createFilter()) | ||
module.exports = function getNpmignore(startPath) { | ||
var retv = {match: notAncestorFiles} | ||
const retv = {match: notAncestorFiles} | ||
var p = getPackageJson(startPath) | ||
const p = getPackageJson(startPath) | ||
if (p) { | ||
var data = cache.get(p.filePath) | ||
const data = cache.get(p.filePath) | ||
if (data) { | ||
@@ -181,4 +171,4 @@ return data | ||
var filesIgnore = parseWhiteList(p.files) | ||
var npmignoreIgnore = parseNpmignore(path.dirname(p.filePath), Boolean(filesIgnore)) | ||
const filesIgnore = parseWhiteList(p.files) | ||
const npmignoreIgnore = parseNpmignore(path.dirname(p.filePath), Boolean(filesIgnore)) | ||
@@ -185,0 +175,0 @@ if (filesIgnore && npmignoreIgnore) { |
@@ -12,5 +12,5 @@ /** | ||
var fs = require("fs") | ||
var path = require("path") | ||
var Cache = require("./cache") | ||
const fs = require("fs") | ||
const path = require("path") | ||
const Cache = require("./cache") | ||
@@ -21,3 +21,3 @@ //------------------------------------------------------------------------------ | ||
var cache = new Cache() | ||
const cache = new Cache() | ||
@@ -33,6 +33,6 @@ /** | ||
function readPackageJson(dir) { | ||
var filePath = path.join(dir, "package.json") | ||
const filePath = path.join(dir, "package.json") | ||
try { | ||
var text = fs.readFileSync(filePath, "utf8") | ||
var data = JSON.parse(text) | ||
const text = fs.readFileSync(filePath, "utf8") | ||
const data = JSON.parse(text) | ||
@@ -64,6 +64,6 @@ if (typeof data === "object" && data !== null) { | ||
module.exports = function getPackageJson(startPath) { | ||
var startDir = path.dirname(path.resolve(startPath)) | ||
var dir = startDir | ||
var prevDir = "" | ||
var data = null | ||
const startDir = path.dirname(path.resolve(startPath)) | ||
let dir = startDir | ||
let prevDir = "" | ||
let data = null | ||
@@ -70,0 +70,0 @@ do { |
@@ -12,8 +12,8 @@ /** | ||
var path = require("path") | ||
var resolve = require("resolve") | ||
var getTryExtensions = require("./get-try-extensions") | ||
var getValueIfString = require("./get-value-if-string") | ||
var ImportTarget = require("./import-target") | ||
var stripImportPathParams = require("./strip-import-path-params") | ||
const path = require("path") | ||
const resolve = require("resolve") | ||
const getTryExtensions = require("./get-try-extensions") | ||
const getValueIfString = require("./get-value-if-string") | ||
const ImportTarget = require("./import-target") | ||
const stripImportPathParams = require("./strip-import-path-params") | ||
@@ -41,3 +41,3 @@ //------------------------------------------------------------------------------ | ||
function getReferencesOfRequire(scope) { | ||
var variable = scope.set.get("require") | ||
const variable = scope.set.get("require") | ||
if (!variable) { | ||
@@ -63,10 +63,9 @@ // Not found. | ||
module.exports = function getRequireTargets(context) { | ||
var retv = [] | ||
var basedir = path.dirname(path.resolve(context.getFilename())) | ||
var references = getReferencesOfRequire(context.getScope()) | ||
var extensions = getTryExtensions(context) | ||
const retv = [] | ||
const basedir = path.dirname(path.resolve(context.getFilename())) | ||
const references = getReferencesOfRequire(context.getScope()) | ||
const extensions = getTryExtensions(context) | ||
for (var i = 0; i < references.length; ++i) { | ||
var reference = references[i] | ||
var node = reference.identifier | ||
for (const reference of references) { | ||
const node = reference.identifier | ||
@@ -79,5 +78,5 @@ // Skips if it's not a call of `require`. | ||
// Gets the target module. | ||
var targetNode = node.parent.arguments[0] | ||
var rawName = getValueIfString(targetNode) | ||
var name = rawName && stripImportPathParams(rawName) | ||
const targetNode = node.parent.arguments[0] | ||
const rawName = getValueIfString(targetNode) | ||
const name = rawName && stripImportPathParams(rawName) | ||
if (name && !resolve.isCore(name)) { | ||
@@ -84,0 +83,0 @@ retv.push(new ImportTarget(targetNode, name, basedir, extensions)) |
@@ -12,3 +12,3 @@ /** | ||
var DEFAULT_VALUE = Object.freeze([".js", ".json", ".node"]) | ||
const DEFAULT_VALUE = Object.freeze([".js", ".json", ".node"]) | ||
@@ -49,1 +49,10 @@ /** | ||
} | ||
module.exports.schema = { | ||
type: "array", | ||
items: { | ||
type: "string", | ||
pattern: "^\\.", | ||
}, | ||
uniqueItems: true, | ||
} |
@@ -12,6 +12,6 @@ /** | ||
var fs = require("fs") | ||
var path = require("path") | ||
var exists = require("./exists") | ||
var getPackageJson = require("./get-package-json") | ||
const fs = require("fs") | ||
const path = require("path") | ||
const exists = require("./exists") | ||
const getPackageJson = require("./get-package-json") | ||
@@ -45,4 +45,3 @@ //------------------------------------------------------------------------------ | ||
function tryExtentions(filePath, exts) { | ||
for (var i = 0; i < exts.length; ++i) { | ||
var ext = exts[i] | ||
for (const ext of exts) { | ||
if (exists(filePath + ext)) { | ||
@@ -82,3 +81,3 @@ return filePath + ext | ||
var p = getPackageJson(path.join(filePath, "package.json")) | ||
const p = getPackageJson(path.join(filePath, "package.json")) | ||
if (p && path.dirname(p.filePath) === filePath && p.main) { | ||
@@ -99,3 +98,3 @@ return resolveAsFile(path.join(filePath, p.main), exts) | ||
function resolve(basedir, name, exts) { | ||
var resolvedPath = path.resolve(basedir, name) | ||
const resolvedPath = path.resolve(basedir, name) | ||
return ( | ||
@@ -117,3 +116,3 @@ resolveAsFile(resolvedPath, exts) || | ||
function getModuleName(nameOrPath) { | ||
var end = nameOrPath.indexOf("/") | ||
let end = nameOrPath.indexOf("/") | ||
if (end !== -1 && nameOrPath[0] === "@") { | ||
@@ -140,3 +139,3 @@ end = nameOrPath.indexOf("/", 1 + end) | ||
module.exports = function ImportTarget(node, name, basedir, exts) { | ||
var relative = /^\./.test(name) | ||
const relative = /^\./.test(name) | ||
@@ -143,0 +142,0 @@ /** |
@@ -13,4 +13,4 @@ /** | ||
module.exports = function stripImportPathParams(path) { | ||
var i = path.indexOf("!") | ||
const i = path.indexOf("!") | ||
return i === -1 ? path : path.slice(0, i) | ||
} |
{ | ||
"name": "eslint-plugin-node", | ||
"version": "3.0.5", | ||
"version": "4.0.0", | ||
"description": "Additional ESLint's rules for Node.js", | ||
@@ -11,19 +11,19 @@ "files": [ | ||
"scripts": { | ||
"preversion": "run-s -sn clean build test:*", | ||
"build": "node scripts/generate-index.js", | ||
"clean": "rimraf .nyc_output coverage index.js", | ||
"codecov": "nyc report -r lcovonly && codecov", | ||
"coverage": "nyc report -r lcov && opener ./coverage/lcov-report/index.html", | ||
"lint": "eslint lib tests/lib index.js", | ||
"postversion": "git push && git push --tags", | ||
"clean": "rimraf .nyc_output coverage index.js", | ||
"build": "node scripts/generate-index.js", | ||
"test": "run-s -sn clean build test:*", | ||
"test:lint": "if-node-version \">=4\" eslint lib tests/lib index.js", | ||
"test:mocha": "nyc mocha tests/lib/**/*.js --reporter progress", | ||
"coverage": "nyc report --reporter=lcov && opener ./coverage/lcov-report/index.html", | ||
"watch": "mocha tests/lib/**/*.js --reporter progress --watch --growl", | ||
"test@2": "rimraf \"node_modules/eslint-{config,plugin}-*\" && npm i eslint@2 && npm run test:mocha -- -i -g NOT_SUPPORTED_ON_2", | ||
"codecov": "nyc report -r lcovonly && codecov" | ||
"pretest": "npm run -s lint", | ||
"preversion": "npm t && npm run build", | ||
"test": "nyc npm run -s test:_mocha", | ||
"test:_mocha": "_mocha tests/lib/**/*.js --reporter progress", | ||
"watch": "npm run test:_mocha -- --watch --growl" | ||
}, | ||
"engines": { | ||
"node": ">=0.10" | ||
"node": ">=4" | ||
}, | ||
"peerDependencies": { | ||
"eslint": ">=2.0.0" | ||
"eslint": ">=3.1.0" | ||
}, | ||
@@ -38,8 +38,10 @@ "dependencies": { | ||
"devDependencies": { | ||
"@types/minimatch": "^2.0.29", | ||
"@types/node": "^4.2.1", | ||
"@types/resolve": "0.0.4", | ||
"@types/semver": "^5.3.30", | ||
"codecov": "^1.0.1", | ||
"eslint": "^3.9.0", | ||
"eslint-config-mysticatea": "^7.0.0", | ||
"if-node-version": "^1.0.0", | ||
"mocha": "^3.0.2", | ||
"npm-run-all": "^3.1.0", | ||
"nyc": "^8.3.0", | ||
@@ -46,0 +48,0 @@ "opener": "^1.4.2", |
@@ -17,4 +17,4 @@ # eslint-plugin-node | ||
- Requires Node.js `^0.10.0 || ^0.12.0 || ^4.0.0 || >=6.0.0` | ||
- Requires ESLint `>=2.0.0` | ||
- Requires Node.js `^4.0.0 || >=6.0.0` | ||
- Requires ESLint `>=3.1.0` | ||
@@ -21,0 +21,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. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
141485
4077
12