mirror of https://github.com/lukechilds/node.git
Browse Source
PR-URL: https://github.com/nodejs/node/pull/6132 Reviewed-By: Brian White <mscdex@mscdex.net> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: thefourtheye <thechargingvolcano@gmail.com>v4.x
silverwind
9 years ago
committed by
Myles Borins
2040 changed files with 40599 additions and 36892 deletions
File diff suppressed because it is too large
@ -0,0 +1,106 @@ |
|||
/** |
|||
* @fileoverview Specify the maximum number of statements allowed per line. |
|||
* @author Kenneth Williams |
|||
* @copyright 2016 Kenneth Williams. All rights reserved. |
|||
* @copyright 2016 Michael Ficarra. All rights reserved. |
|||
* See LICENSE file in root directory for full license. |
|||
*/ |
|||
"use strict"; |
|||
|
|||
//------------------------------------------------------------------------------
|
|||
// Rule Definition
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
module.exports = function(context) { |
|||
|
|||
var options = context.options[0] || {}, |
|||
lastStatementLine = 0, |
|||
numberOfStatementsOnThisLine = 0, |
|||
maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1; |
|||
|
|||
//--------------------------------------------------------------------------
|
|||
// Helpers
|
|||
//--------------------------------------------------------------------------
|
|||
|
|||
/** |
|||
* Reports a node |
|||
* @param {ASTNode} node The node to report |
|||
* @returns {void} |
|||
* @private |
|||
*/ |
|||
function report(node) { |
|||
context.report( |
|||
node, |
|||
"This line has too many statements. Maximum allowed is {{max}}.", |
|||
{ max: maxStatementsPerLine }); |
|||
} |
|||
|
|||
/** |
|||
* Enforce a maximum number of statements per line |
|||
* @param {ASTNode} nodes Array of nodes to evaluate |
|||
* @returns {void} |
|||
* @private |
|||
*/ |
|||
function enforceMaxStatementsPerLine(nodes) { |
|||
if (nodes.length < 1) { |
|||
return; |
|||
} |
|||
|
|||
for (var i = 0, l = nodes.length; i < l; ++i) { |
|||
var currentStatement = nodes[i]; |
|||
|
|||
if (currentStatement.loc.start.line === lastStatementLine) { |
|||
++numberOfStatementsOnThisLine; |
|||
} else { |
|||
numberOfStatementsOnThisLine = 1; |
|||
lastStatementLine = currentStatement.loc.end.line; |
|||
} |
|||
if (numberOfStatementsOnThisLine === maxStatementsPerLine + 1) { |
|||
report(currentStatement); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Check each line in the body of a node |
|||
* @param {ASTNode} node node to evaluate |
|||
* @returns {void} |
|||
* @private |
|||
*/ |
|||
function checkLinesInBody(node) { |
|||
enforceMaxStatementsPerLine(node.body); |
|||
} |
|||
|
|||
/** |
|||
* Check each line in the consequent of a switch case |
|||
* @param {ASTNode} node node to evaluate |
|||
* @returns {void} |
|||
* @private |
|||
*/ |
|||
function checkLinesInConsequent(node) { |
|||
enforceMaxStatementsPerLine(node.consequent); |
|||
} |
|||
|
|||
//--------------------------------------------------------------------------
|
|||
// Public API
|
|||
//--------------------------------------------------------------------------
|
|||
|
|||
return { |
|||
"Program": checkLinesInBody, |
|||
"BlockStatement": checkLinesInBody, |
|||
"SwitchCase": checkLinesInConsequent |
|||
}; |
|||
|
|||
}; |
|||
|
|||
module.exports.schema = [ |
|||
{ |
|||
"type": "object", |
|||
"properties": { |
|||
"max": { |
|||
"type": "integer" |
|||
} |
|||
}, |
|||
"additionalProperties": false |
|||
} |
|||
]; |
@ -0,0 +1,143 @@ |
|||
|
|||
/** |
|||
* @fileoverview Rule to require newlines before `return` statement |
|||
* @author Kai Cataldo |
|||
* @copyright 2016 Kai Cataldo. All rights reserved. |
|||
* See LICENSE file in root directory for full license. |
|||
*/ |
|||
"use strict"; |
|||
|
|||
//------------------------------------------------------------------------------
|
|||
// Rule Definition
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
module.exports = function(context) { |
|||
var sourceCode = context.getSourceCode(); |
|||
|
|||
//--------------------------------------------------------------------------
|
|||
// Helpers
|
|||
//--------------------------------------------------------------------------
|
|||
|
|||
/** |
|||
* Tests whether node is preceded by supplied tokens |
|||
* @param {ASTNode} node - node to check |
|||
* @param {array} testTokens - array of tokens to test against |
|||
* @returns {boolean} Whether or not the node is preceded by one of the supplied tokens |
|||
* @private |
|||
*/ |
|||
function isPrecededByTokens(node, testTokens) { |
|||
var tokenBefore = sourceCode.getTokenBefore(node); |
|||
|
|||
return testTokens.some(function(token) { |
|||
return tokenBefore.value === token; |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Checks whether node is the first node after statement or in block |
|||
* @param {ASTNode} node - node to check |
|||
* @returns {boolean} Whether or not the node is the first node after statement or in block |
|||
* @private |
|||
*/ |
|||
function isFirstNode(node) { |
|||
var parentType = node.parent.type; |
|||
|
|||
if (node.parent.body) { |
|||
return Array.isArray(node.parent.body) |
|||
? node.parent.body[0] === node |
|||
: node.parent.body === node; |
|||
} |
|||
|
|||
if (parentType === "IfStatement") { |
|||
return isPrecededByTokens(node, ["else", ")"]); |
|||
} else if (parentType === "DoWhileStatement") { |
|||
return isPrecededByTokens(node, ["do"]); |
|||
} else if (parentType === "SwitchCase") { |
|||
return isPrecededByTokens(node, [":"]); |
|||
} else { |
|||
return isPrecededByTokens(node, [")"]); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Returns the number of lines of comments that precede the node |
|||
* @param {ASTNode} node - node to check for overlapping comments |
|||
* @param {token} tokenBefore - previous token to check for overlapping comments |
|||
* @returns {number} Number of lines of comments that precede the node |
|||
* @private |
|||
*/ |
|||
function calcCommentLines(node, tokenBefore) { |
|||
var comments = sourceCode.getComments(node).leading; |
|||
var numLinesComments = 0; |
|||
|
|||
if (!comments.length) { |
|||
return numLinesComments; |
|||
} |
|||
|
|||
comments.forEach(function(comment) { |
|||
numLinesComments++; |
|||
|
|||
if (comment.type === "Block") { |
|||
numLinesComments += comment.loc.end.line - comment.loc.start.line; |
|||
} |
|||
|
|||
// avoid counting lines with inline comments twice
|
|||
if (comment.loc.start.line === tokenBefore.loc.end.line) { |
|||
numLinesComments--; |
|||
} |
|||
|
|||
if (comment.loc.end.line === node.loc.start.line) { |
|||
numLinesComments--; |
|||
} |
|||
}); |
|||
|
|||
return numLinesComments; |
|||
} |
|||
|
|||
/** |
|||
* Checks whether node is preceded by a newline |
|||
* @param {ASTNode} node - node to check |
|||
* @returns {boolean} Whether or not the node is preceded by a newline |
|||
* @private |
|||
*/ |
|||
function hasNewlineBefore(node) { |
|||
var tokenBefore = sourceCode.getTokenBefore(node); |
|||
var lineNumTokenBefore = tokenBefore.loc.end.line; |
|||
var lineNumNode = node.loc.start.line; |
|||
var commentLines = calcCommentLines(node, tokenBefore); |
|||
|
|||
return (lineNumNode - lineNumTokenBefore - commentLines) > 1; |
|||
} |
|||
|
|||
/** |
|||
* Reports expected/unexpected newline before return statement |
|||
* @param {ASTNode} node - the node to report in the event of an error |
|||
* @param {boolean} isExpected - whether the newline is expected or not |
|||
* @returns {void} |
|||
* @private |
|||
*/ |
|||
function reportError(node, isExpected) { |
|||
var expected = isExpected ? "Expected" : "Unexpected"; |
|||
|
|||
context.report({ |
|||
node: node, |
|||
message: expected + " newline before return statement." |
|||
}); |
|||
} |
|||
|
|||
//--------------------------------------------------------------------------
|
|||
// Public
|
|||
//--------------------------------------------------------------------------
|
|||
|
|||
return { |
|||
ReturnStatement: function(node) { |
|||
if (isFirstNode(node) && hasNewlineBefore(node)) { |
|||
reportError(node, false); |
|||
} else if (!isFirstNode(node) && !hasNewlineBefore(node)) { |
|||
reportError(node, true); |
|||
} |
|||
} |
|||
}; |
|||
}; |
|||
|
|||
module.exports.schema = []; |
@ -0,0 +1,126 @@ |
|||
/** |
|||
* @fileoverview Restrict usage of duplicate imports. |
|||
* @author Simen Bekkhus |
|||
* @copyright 2016 Simen Bekkhus. All rights reserved. |
|||
* See LICENSE file in root directory for full license. |
|||
*/ |
|||
"use strict"; |
|||
|
|||
//------------------------------------------------------------------------------
|
|||
// Rule Definition
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
/** |
|||
* Returns the name of the module imported or re-exported. |
|||
* |
|||
* @param {ASTNode} node - A node to get. |
|||
* @returns {string} the name of the module, or empty string if no name. |
|||
*/ |
|||
function getValue(node) { |
|||
if (node && node.source && node.source.value) { |
|||
return node.source.value.trim(); |
|||
} |
|||
|
|||
return ""; |
|||
} |
|||
|
|||
/** |
|||
* Checks if the name of the import or export exists in the given array, and reports if so. |
|||
* |
|||
* @param {RuleContext} context - The ESLint rule context object. |
|||
* @param {ASTNode} node - A node to get. |
|||
* @param {string} value - The name of the imported or exported module. |
|||
* @param {string[]} array - The array containing other imports or exports in the file. |
|||
* @param {string} message - A message to be reported after the name of the module |
|||
* |
|||
* @returns {void} No return value |
|||
*/ |
|||
function checkAndReport(context, node, value, array, message) { |
|||
if (array.indexOf(value) !== -1) { |
|||
context.report({ |
|||
node: node, |
|||
message: "'{{module}}' " + message, |
|||
data: {module: value} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @callback nodeCallback |
|||
* @param {ASTNode} node - A node to handle. |
|||
*/ |
|||
|
|||
/** |
|||
* Returns a function handling the imports of a given file |
|||
* |
|||
* @param {RuleContext} context - The ESLint rule context object. |
|||
* @param {boolean} includeExports - Whether or not to check for exports in addition to imports. |
|||
* @param {string[]} importsInFile - The array containing other imports in the file. |
|||
* @param {string[]} exportsInFile - The array containing other exports in the file. |
|||
* |
|||
* @returns {nodeCallback} A function passed to ESLint to handle the statement. |
|||
*/ |
|||
function handleImports(context, includeExports, importsInFile, exportsInFile) { |
|||
return function(node) { |
|||
var value = getValue(node); |
|||
|
|||
if (value) { |
|||
checkAndReport(context, node, value, importsInFile, "import is duplicated."); |
|||
|
|||
if (includeExports) { |
|||
checkAndReport(context, node, value, exportsInFile, "import is duplicated as export."); |
|||
} |
|||
|
|||
importsInFile.push(value); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
/** |
|||
* Returns a function handling the exports of a given file |
|||
* |
|||
* @param {RuleContext} context - The ESLint rule context object. |
|||
* @param {string[]} importsInFile - The array containing other imports in the file. |
|||
* @param {string[]} exportsInFile - The array containing other exports in the file. |
|||
* |
|||
* @returns {nodeCallback} A function passed to ESLint to handle the statement. |
|||
*/ |
|||
function handleExports(context, importsInFile, exportsInFile) { |
|||
return function(node) { |
|||
var value = getValue(node); |
|||
|
|||
if (value) { |
|||
checkAndReport(context, node, value, exportsInFile, "export is duplicated."); |
|||
checkAndReport(context, node, value, importsInFile, "export is duplicated as import."); |
|||
|
|||
exportsInFile.push(value); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
module.exports = function(context) { |
|||
var includeExports = (context.options[0] || {}).includeExports, |
|||
importsInFile = [], |
|||
exportsInFile = []; |
|||
|
|||
var handlers = { |
|||
"ImportDeclaration": handleImports(context, includeExports, importsInFile, exportsInFile) |
|||
}; |
|||
|
|||
if (includeExports) { |
|||
handlers.ExportNamedDeclaration = handleExports(context, importsInFile, exportsInFile); |
|||
handlers.ExportAllDeclaration = handleExports(context, importsInFile, exportsInFile); |
|||
} |
|||
|
|||
return handlers; |
|||
}; |
|||
|
|||
module.exports.schema = [{ |
|||
"type": "object", |
|||
"properties": { |
|||
"includeExports": { |
|||
"type": "boolean" |
|||
} |
|||
}, |
|||
"additionalProperties": false |
|||
}]; |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue