diff options
author | Rich Trott <rtrott@gmail.com> | 2016-08-06 12:11:02 -0700 |
---|---|---|
committer | Rich Trott <rtrott@gmail.com> | 2016-08-09 21:19:02 -0700 |
commit | e313c0286b1c1a7267516a7b2b4c01fa76c71ec0 (patch) | |
tree | 7358ae3f4af0979c124eca46d734314df40a6bc6 /tools/eslint/lib/rules | |
parent | 49e473a45fb3e13fdd4588c6241b71bbac4fe5ab (diff) | |
download | node-new-e313c0286b1c1a7267516a7b2b4c01fa76c71ec0.tar.gz |
tools: update to ESLint 3.2.2
PR-URL: https://github.com/nodejs/node/pull/7999
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Johan Bergström <bugs@bergstroem.nu>
Diffstat (limited to 'tools/eslint/lib/rules')
205 files changed, 2263 insertions, 1534 deletions
diff --git a/tools/eslint/lib/rules/.eslintrc.yml b/tools/eslint/lib/rules/.eslintrc.yml new file mode 100644 index 0000000000..fded5b8497 --- /dev/null +++ b/tools/eslint/lib/rules/.eslintrc.yml @@ -0,0 +1,2 @@ +rules: + internal-no-invalid-meta: "error" diff --git a/tools/eslint/lib/rules/accessor-pairs.js b/tools/eslint/lib/rules/accessor-pairs.js index 3ed9f0dc0c..b80b44dc9f 100644 --- a/tools/eslint/lib/rules/accessor-pairs.js +++ b/tools/eslint/lib/rules/accessor-pairs.js @@ -28,7 +28,7 @@ function isIdentifier(node, name) { * @returns {boolean} `true` if the node is an argument of the specified method call. */ function isArgumentOfMethodCall(node, index, object, property) { - var parent = node.parent; + let parent = node.parent; return ( parent.type === "CallExpression" && @@ -91,9 +91,9 @@ module.exports = { }] }, create: function(context) { - var config = context.options[0] || {}; - var checkGetWithoutSet = config.getWithoutSet === true; - var checkSetWithoutGet = config.setWithoutGet !== false; + let config = context.options[0] || {}; + let checkGetWithoutSet = config.getWithoutSet === true; + let checkSetWithoutGet = config.setWithoutGet !== false; /** * Checks a object expression to see if it has setter and getter both present or none. @@ -102,14 +102,14 @@ module.exports = { * @private */ function checkLonelySetGet(node) { - var isSetPresent = false; - var isGetPresent = false; - var isDescriptor = isPropertyDescriptor(node); + let isSetPresent = false; + let isGetPresent = false; + let isDescriptor = isPropertyDescriptor(node); - for (var i = 0, end = node.properties.length; i < end; i++) { - var property = node.properties[i]; + for (let i = 0, end = node.properties.length; i < end; i++) { + let property = node.properties[i]; - var propToCheck = ""; + let propToCheck = ""; if (property.kind === "init") { if (isDescriptor && !property.computed) { @@ -139,9 +139,9 @@ module.exports = { } if (checkSetWithoutGet && isSetPresent && !isGetPresent) { - context.report(node, "Getter is not present"); + context.report(node, "Getter is not present."); } else if (checkGetWithoutSet && isGetPresent && !isSetPresent) { - context.report(node, "Setter is not present"); + context.report(node, "Setter is not present."); } } diff --git a/tools/eslint/lib/rules/array-bracket-spacing.js b/tools/eslint/lib/rules/array-bracket-spacing.js index 09598031b4..6e26e0cbd5 100644 --- a/tools/eslint/lib/rules/array-bracket-spacing.js +++ b/tools/eslint/lib/rules/array-bracket-spacing.js @@ -4,7 +4,7 @@ */ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -40,7 +40,7 @@ module.exports = { ] }, create: function(context) { - var spaced = context.options[0] === "always", + let spaced = context.options[0] === "always", sourceCode = context.getSourceCode(); /** @@ -54,7 +54,7 @@ module.exports = { return context.options[1] ? context.options[1][option] === !spaced : false; } - var options = { + let options = { spaced: spaced, singleElementException: isOptionSet("singleValue"), objectsInArraysException: isOptionSet("objectsInArrays"), @@ -75,9 +75,9 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "There should be no space after '" + token.value + "'", + message: "There should be no space after '" + token.value + "'.", fix: function(fixer) { - var nextToken = sourceCode.getTokenAfter(token); + let nextToken = sourceCode.getTokenAfter(token); return fixer.removeRange([token.range[1], nextToken.range[0]]); } @@ -94,9 +94,9 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "There should be no space before '" + token.value + "'", + message: "There should be no space before '" + token.value + "'.", fix: function(fixer) { - var previousToken = sourceCode.getTokenBefore(token); + let previousToken = sourceCode.getTokenBefore(token); return fixer.removeRange([previousToken.range[1], token.range[0]]); } @@ -113,7 +113,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "A space is required after '" + token.value + "'", + message: "A space is required after '" + token.value + "'.", fix: function(fixer) { return fixer.insertTextAfter(token, " "); } @@ -130,7 +130,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "A space is required before '" + token.value + "'", + message: "A space is required before '" + token.value + "'.", fix: function(fixer) { return fixer.insertTextBefore(token, " "); } @@ -165,20 +165,20 @@ module.exports = { return; } - var first = sourceCode.getFirstToken(node), + let first = sourceCode.getFirstToken(node), second = sourceCode.getFirstToken(node, 1), penultimate = sourceCode.getLastToken(node, 1), last = sourceCode.getLastToken(node), firstElement = node.elements[0], lastElement = node.elements[node.elements.length - 1]; - var openingBracketMustBeSpaced = + let openingBracketMustBeSpaced = options.objectsInArraysException && isObjectType(firstElement) || options.arraysInArraysException && isArrayType(firstElement) || options.singleElementException && node.elements.length === 1 ? !options.spaced : options.spaced; - var closingBracketMustBeSpaced = + let closingBracketMustBeSpaced = options.objectsInArraysException && isObjectType(lastElement) || options.arraysInArraysException && isArrayType(lastElement) || options.singleElementException && node.elements.length === 1 diff --git a/tools/eslint/lib/rules/array-callback-return.js b/tools/eslint/lib/rules/array-callback-return.js index 714c189c6b..d72fd57b2e 100644 --- a/tools/eslint/lib/rules/array-callback-return.js +++ b/tools/eslint/lib/rules/array-callback-return.js @@ -9,14 +9,14 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/; -var TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/; +let TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/; +let TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/; /** * Checks a given code path segment is reachable. @@ -104,7 +104,7 @@ function isTargetMethod(node) { */ function isCallbackOfArrayMethod(node) { while (node) { - var parent = node.parent; + let parent = node.parent; switch (parent.type) { @@ -123,14 +123,15 @@ function isCallbackOfArrayMethod(node) { // // setup... // return function callback() { ... }; // })()); - case "ReturnStatement": - var func = astUtils.getUpperFunction(parent); + case "ReturnStatement": { + const func = astUtils.getUpperFunction(parent); if (func === null || !astUtils.isCallee(func)) { return false; } node = func.parent; break; + } // e.g. // Array.from([], function() {}); @@ -176,7 +177,7 @@ module.exports = { }, create: function(context) { - var funcInfo = { + let funcInfo = { upper: null, codePath: null, hasReturn: false, diff --git a/tools/eslint/lib/rules/arrow-body-style.js b/tools/eslint/lib/rules/arrow-body-style.js index 13486fa74b..16f082edae 100644 --- a/tools/eslint/lib/rules/arrow-body-style.js +++ b/tools/eslint/lib/rules/arrow-body-style.js @@ -50,11 +50,11 @@ module.exports = { }, create: function(context) { - var options = context.options; - var always = options[0] === "always"; - var asNeeded = !options[0] || options[0] === "as-needed"; - var never = options[0] === "never"; - var requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral; + let options = context.options; + let always = options[0] === "always"; + let asNeeded = !options[0] || options[0] === "as-needed"; + let never = options[0] === "never"; + let requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral; /** * Determines whether a arrow function body needs braces @@ -62,7 +62,7 @@ module.exports = { * @returns {void} */ function validate(node) { - var arrowBody = node.body; + let arrowBody = node.body; if (arrowBody.type === "BlockStatement") { if (never) { @@ -72,7 +72,7 @@ module.exports = { message: "Unexpected block statement surrounding arrow body." }); } else { - var blockBody = arrowBody.body; + let blockBody = arrowBody.body; if (blockBody.length !== 1) { return; diff --git a/tools/eslint/lib/rules/arrow-parens.js b/tools/eslint/lib/rules/arrow-parens.js index 86b972e800..fd70ee3465 100644 --- a/tools/eslint/lib/rules/arrow-parens.js +++ b/tools/eslint/lib/rules/arrow-parens.js @@ -26,11 +26,11 @@ module.exports = { }, create: function(context) { - var message = "Expected parentheses around arrow function argument."; - var asNeededMessage = "Unexpected parentheses around single function argument"; - var asNeeded = context.options[0] === "as-needed"; + let message = "Expected parentheses around arrow function argument."; + let asNeededMessage = "Unexpected parentheses around single function argument."; + let asNeeded = context.options[0] === "as-needed"; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Determines whether a arrow function argument end with `)` @@ -38,7 +38,7 @@ module.exports = { * @returns {void} */ function parens(node) { - var token = sourceCode.getFirstToken(node); + let token = sourceCode.getFirstToken(node); // as-needed: x => x if (asNeeded && node.params.length === 1 && node.params[0].type === "Identifier") { @@ -47,8 +47,8 @@ module.exports = { node: node, message: asNeededMessage, fix: function(fixer) { - var paramToken = context.getTokenAfter(token); - var closingParenToken = context.getTokenAfter(paramToken); + let paramToken = context.getTokenAfter(token); + let closingParenToken = context.getTokenAfter(paramToken); return fixer.replaceTextRange([ token.range[0], @@ -61,7 +61,7 @@ module.exports = { } if (token.type === "Identifier") { - var after = sourceCode.getTokenAfter(token); + let after = sourceCode.getTokenAfter(token); // (x) => x if (after.value !== ")") { diff --git a/tools/eslint/lib/rules/arrow-spacing.js b/tools/eslint/lib/rules/arrow-spacing.js index 3af5ae1f84..354c860c7b 100644 --- a/tools/eslint/lib/rules/arrow-spacing.js +++ b/tools/eslint/lib/rules/arrow-spacing.js @@ -37,13 +37,13 @@ module.exports = { create: function(context) { // merge rules with default - var rule = { before: true, after: true }, + let rule = { before: true, after: true }, option = context.options[0] || {}; rule.before = option.before !== false; rule.after = option.after !== false; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Get tokens of arrow(`=>`) and before/after arrow. @@ -51,14 +51,14 @@ module.exports = { * @returns {Object} Tokens of arrow and before/after arrow. */ function getTokens(node) { - var t = sourceCode.getFirstToken(node); - var before; + let t = sourceCode.getFirstToken(node); + let before; while (t.type !== "Punctuator" || t.value !== "=>") { before = t; t = sourceCode.getTokenAfter(t); } - var after = sourceCode.getTokenAfter(t); + let after = sourceCode.getTokenAfter(t); return { before: before, arrow: t, after: after }; } @@ -69,8 +69,8 @@ module.exports = { * @returns {Object} count of space before/after arrow. */ function countSpaces(tokens) { - var before = tokens.arrow.range[0] - tokens.before.range[1]; - var after = tokens.after.range[0] - tokens.arrow.range[1]; + let before = tokens.arrow.range[0] - tokens.before.range[1]; + let after = tokens.after.range[0] - tokens.arrow.range[1]; return { before: before, after: after }; } @@ -83,8 +83,8 @@ module.exports = { * @returns {void} */ function spaces(node) { - var tokens = getTokens(node); - var countSpace = countSpaces(tokens); + let tokens = getTokens(node); + let countSpace = countSpaces(tokens); if (rule.before) { @@ -92,7 +92,7 @@ module.exports = { if (countSpace.before === 0) { context.report({ node: tokens.before, - message: "Missing space before =>", + message: "Missing space before =>.", fix: function(fixer) { return fixer.insertTextBefore(tokens.arrow, " "); } @@ -104,7 +104,7 @@ module.exports = { if (countSpace.before > 0) { context.report({ node: tokens.before, - message: "Unexpected space before =>", + message: "Unexpected space before =>.", fix: function(fixer) { return fixer.removeRange([tokens.before.range[1], tokens.arrow.range[0]]); } @@ -118,7 +118,7 @@ module.exports = { if (countSpace.after === 0) { context.report({ node: tokens.after, - message: "Missing space after =>", + message: "Missing space after =>.", fix: function(fixer) { return fixer.insertTextAfter(tokens.arrow, " "); } @@ -130,7 +130,7 @@ module.exports = { if (countSpace.after > 0) { context.report({ node: tokens.after, - message: "Unexpected space after =>", + message: "Unexpected space after =>.", fix: function(fixer) { return fixer.removeRange([tokens.arrow.range[1], tokens.after.range[0]]); } diff --git a/tools/eslint/lib/rules/block-scoped-var.js b/tools/eslint/lib/rules/block-scoped-var.js index 3da07adcba..f8198ea10a 100644 --- a/tools/eslint/lib/rules/block-scoped-var.js +++ b/tools/eslint/lib/rules/block-scoped-var.js @@ -20,7 +20,7 @@ module.exports = { }, create: function(context) { - var stack = []; + let stack = []; /** * Makes a block scope. @@ -45,7 +45,7 @@ module.exports = { * @returns {void} */ function report(reference) { - var identifier = reference.identifier; + let identifier = reference.identifier; context.report( identifier, @@ -64,7 +64,7 @@ module.exports = { } // Defines a predicate to check whether or not a given reference is outside of valid scope. - var scopeRange = stack[stack.length - 1]; + let scopeRange = stack[stack.length - 1]; /** * Check if a reference is out of scope @@ -73,15 +73,15 @@ module.exports = { * @private */ function isOutsideOfScope(reference) { - var idRange = reference.identifier.range; + let idRange = reference.identifier.range; return idRange[0] < scopeRange[0] || idRange[1] > scopeRange[1]; } // Gets declared variables, and checks its references. - var variables = context.getDeclaredVariables(node); + let variables = context.getDeclaredVariables(node); - for (var i = 0; i < variables.length; ++i) { + for (let i = 0; i < variables.length; ++i) { // Reports. variables[i] diff --git a/tools/eslint/lib/rules/block-spacing.js b/tools/eslint/lib/rules/block-spacing.js index 54ae83d117..eb24cea319 100644 --- a/tools/eslint/lib/rules/block-spacing.js +++ b/tools/eslint/lib/rules/block-spacing.js @@ -5,7 +5,7 @@ "use strict"; -var util = require("../ast-utils"); +let util = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -27,7 +27,7 @@ module.exports = { }, create: function(context) { - var always = (context.options[0] !== "never"), + let always = (context.options[0] !== "never"), message = always ? "Requires a space" : "Unexpected space(s)", sourceCode = context.getSourceCode(); @@ -72,10 +72,10 @@ module.exports = { function checkSpacingInsideBraces(node) { // Gets braces and the first/last token of content. - var openBrace = getOpenBrace(node); - var closeBrace = sourceCode.getLastToken(node); - var firstToken = sourceCode.getTokenOrCommentAfter(openBrace); - var lastToken = sourceCode.getTokenOrCommentBefore(closeBrace); + let openBrace = getOpenBrace(node); + let closeBrace = sourceCode.getLastToken(node); + let firstToken = sourceCode.getTokenOrCommentAfter(openBrace); + let lastToken = sourceCode.getTokenOrCommentBefore(closeBrace); // Skip if the node is invalid or empty. if (openBrace.type !== "Punctuator" || diff --git a/tools/eslint/lib/rules/brace-style.js b/tools/eslint/lib/rules/brace-style.js index 785a71e4e7..325130a4a2 100644 --- a/tools/eslint/lib/rules/brace-style.js +++ b/tools/eslint/lib/rules/brace-style.js @@ -34,11 +34,11 @@ module.exports = { }, create: function(context) { - var style = context.options[0] || "1tbs", + let style = context.options[0] || "1tbs", params = context.options[1] || {}, sourceCode = context.getSourceCode(); - var OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.", + let OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.", OPEN_MESSAGE_ALLMAN = "Opening curly brace appears on the same line as controlling statement.", BODY_MESSAGE = "Statement inside of curly braces should be on next line.", CLOSE_MESSAGE = "Closing curly brace does not appear on the same line as the subsequent block.", @@ -61,7 +61,7 @@ module.exports = { /** * Check if the token is an punctuator with a value of curly brace - * @param {object} token - Token to check + * @param {Object} token - Token to check * @returns {boolean} true if its a curly punctuator * @private */ @@ -78,11 +78,11 @@ module.exports = { * @private */ function checkBlock() { - var blockProperties = arguments; + let blockProperties = arguments; return function(node) { Array.prototype.forEach.call(blockProperties, function(blockProp) { - var block = node[blockProp], + let block = node[blockProp], previousToken, curlyToken, curlyTokenEnd, @@ -129,7 +129,7 @@ module.exports = { * @private */ function checkIfStatement(node) { - var tokens; + let tokens; checkBlock("consequent", "alternate")(node); @@ -157,7 +157,7 @@ module.exports = { * @private */ function checkTryStatement(node) { - var tokens; + let tokens; checkBlock("block", "finalizer")(node); @@ -180,7 +180,7 @@ module.exports = { * @private */ function checkCatchClause(node) { - var previousToken = sourceCode.getTokenBefore(node), + let previousToken = sourceCode.getTokenBefore(node), firstToken = sourceCode.getFirstToken(node); checkBlock("body")(node); @@ -205,7 +205,7 @@ module.exports = { * @private */ function checkSwitchStatement(node) { - var tokens; + let tokens; if (node.cases && node.cases.length) { tokens = sourceCode.getTokensBefore(node.cases[0], 2); diff --git a/tools/eslint/lib/rules/callback-return.js b/tools/eslint/lib/rules/callback-return.js index 1d70d0c637..0b9d4a4894 100644 --- a/tools/eslint/lib/rules/callback-return.js +++ b/tools/eslint/lib/rules/callback-return.js @@ -24,7 +24,7 @@ module.exports = { create: function(context) { - var callbacks = context.options[0] || ["callback", "cb", "next"], + let callbacks = context.options[0] || ["callback", "cb", "next"], sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- @@ -50,7 +50,7 @@ module.exports = { /** * Check to see if a node contains only identifers * @param {ASTNode} node The node to check - * @returns {Boolean} Whether or not the node contains only identifers + * @returns {boolean} Whether or not the node contains only identifers */ function containsOnlyIdentifiers(node) { if (node.type === "Identifier") { @@ -71,7 +71,7 @@ module.exports = { /** * Check to see if a CallExpression is in our callback list. * @param {ASTNode} node The node to check against our callback names list. - * @returns {Boolean} Whether or not this function matches our callback name. + * @returns {boolean} Whether or not this function matches our callback name. */ function isCallback(node) { return containsOnlyIdentifiers(node.callee) && callbacks.indexOf(sourceCode.getText(node.callee)) > -1; @@ -118,7 +118,7 @@ module.exports = { } // find the closest block, return or loop - var closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {}, + let closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {}, lastItem, parentType; // if our parent is a return we know we're ok diff --git a/tools/eslint/lib/rules/camelcase.js b/tools/eslint/lib/rules/camelcase.js index 28f9e8296b..b336e595dc 100644 --- a/tools/eslint/lib/rules/camelcase.js +++ b/tools/eslint/lib/rules/camelcase.js @@ -37,11 +37,11 @@ module.exports = { //-------------------------------------------------------------------------- // contains reported nodes to avoid reporting twice on destructuring with shorthand notation - var reported = []; + let reported = []; /** * Checks if a string contains an underscore and isn't all upper-case - * @param {String} name The string to check. + * @param {string} name The string to check. * @returns {boolean} if the string is underscored * @private */ @@ -64,7 +64,7 @@ module.exports = { } } - var options = context.options[0] || {}, + let options = context.options[0] || {}, properties = options.properties || ""; if (properties !== "always" && properties !== "never") { @@ -79,7 +79,7 @@ module.exports = { * Leading and trailing underscores are commonly used to flag * private/protected identifiers, strip them */ - var name = node.name.replace(/^_+|_+$/g, ""), + let name = node.name.replace(/^_+|_+$/g, ""), effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent; // MemberExpressions get special rules diff --git a/tools/eslint/lib/rules/comma-dangle.js b/tools/eslint/lib/rules/comma-dangle.js index d2478cacfb..69a72e8fca 100644 --- a/tools/eslint/lib/rules/comma-dangle.js +++ b/tools/eslint/lib/rules/comma-dangle.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var lodash = require("lodash"); +let lodash = require("lodash"); /** * Checks whether or not a trailing comma is allowed in a given node. @@ -45,9 +45,9 @@ module.exports = { }, create: function(context) { - var mode = context.options[0]; - var UNEXPECTED_MESSAGE = "Unexpected trailing comma."; - var MISSING_MESSAGE = "Missing trailing comma."; + let mode = context.options[0]; + let UNEXPECTED_MESSAGE = "Unexpected trailing comma."; + let MISSING_MESSAGE = "Missing trailing comma."; /** * Checks whether or not a given node is multiline. @@ -58,13 +58,13 @@ module.exports = { * @returns {boolean} `true` if the node is multiline. */ function isMultiline(node) { - var lastItem = lodash.last(node.properties || node.elements || node.specifiers); + let lastItem = lodash.last(node.properties || node.elements || node.specifiers); if (!lastItem) { return false; } - var sourceCode = context.getSourceCode(), + let sourceCode = context.getSourceCode(), penultimateToken = sourceCode.getLastToken(lastItem), lastToken = sourceCode.getTokenAfter(penultimateToken); @@ -91,13 +91,13 @@ module.exports = { * @returns {void} */ function forbidTrailingComma(node) { - var lastItem = lodash.last(node.properties || node.elements || node.specifiers); + let lastItem = lodash.last(node.properties || node.elements || node.specifiers); if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { return; } - var sourceCode = context.getSourceCode(), + let sourceCode = context.getSourceCode(), trailingToken; // last item can be surrounded by parentheses for object and array literals @@ -132,7 +132,7 @@ module.exports = { * @returns {void} */ function forceTrailingComma(node) { - var lastItem = lodash.last(node.properties || node.elements || node.specifiers); + let lastItem = lodash.last(node.properties || node.elements || node.specifiers); if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { return; @@ -142,7 +142,7 @@ module.exports = { return; } - var sourceCode = context.getSourceCode(), + let sourceCode = context.getSourceCode(), penultimateToken = lastItem, trailingToken = sourceCode.getTokenAfter(lastItem); @@ -199,7 +199,7 @@ module.exports = { } // Chooses a checking function. - var checkForTrailingComma; + let checkForTrailingComma; if (mode === "always") { checkForTrailingComma = forceTrailingComma; diff --git a/tools/eslint/lib/rules/comma-spacing.js b/tools/eslint/lib/rules/comma-spacing.js index 22fb8b235f..ea516e0333 100644 --- a/tools/eslint/lib/rules/comma-spacing.js +++ b/tools/eslint/lib/rules/comma-spacing.js @@ -4,7 +4,7 @@ */ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -38,10 +38,10 @@ module.exports = { create: function(context) { - var sourceCode = context.getSourceCode(); - var tokensAndComments = sourceCode.tokensAndComments; + let sourceCode = context.getSourceCode(); + let tokensAndComments = sourceCode.tokensAndComments; - var options = { + let options = { before: context.options[0] ? !!context.options[0].before : false, after: context.options[0] ? !!context.options[0].after : true }; @@ -51,7 +51,7 @@ module.exports = { //-------------------------------------------------------------------------- // list of comma tokens to ignore for the check of leading whitespace - var commaTokensToIgnore = []; + let commaTokensToIgnore = []; /** * Determines if a given token is a comma operator. @@ -82,8 +82,8 @@ module.exports = { return fixer.insertTextAfter(node, " "); } } else { - var start, end; - var newText = ""; + let start, end; + let newText = ""; if (dir === "before") { start = otherNode.range[1]; @@ -136,10 +136,10 @@ module.exports = { * @returns {void} */ function addNullElementsToIgnoreList(node) { - var previousToken = sourceCode.getFirstToken(node); + let previousToken = sourceCode.getFirstToken(node); node.elements.forEach(function(element) { - var token; + let token; if (element === null) { token = sourceCode.getTokenAfter(previousToken); @@ -162,7 +162,7 @@ module.exports = { return { "Program:exit": function() { - var previousToken, + let previousToken, nextToken; tokensAndComments.forEach(function(token, i) { diff --git a/tools/eslint/lib/rules/comma-style.js b/tools/eslint/lib/rules/comma-style.js index 173df90c33..69b657f62d 100644 --- a/tools/eslint/lib/rules/comma-style.js +++ b/tools/eslint/lib/rules/comma-style.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -39,7 +39,7 @@ module.exports = { }, create: function(context) { - var style = context.options[0] || "last", + let style = context.options[0] || "last", exceptions = {}, sourceCode = context.getSourceCode(); @@ -108,7 +108,7 @@ module.exports = { * @returns {void} */ function validateComma(node, property) { - var items = node[property], + let items = node[property], arrayLiteral = (node.type === "ArrayExpression"), previousItemToken; @@ -118,7 +118,7 @@ module.exports = { previousItemToken = sourceCode.getFirstToken(node); items.forEach(function(item) { - var commaToken = item ? sourceCode.getTokenBefore(item) : previousItemToken, + let commaToken = item ? sourceCode.getTokenBefore(item) : previousItemToken, currentItemToken = item ? sourceCode.getFirstToken(item) : sourceCode.getTokenAfter(commaToken), reportItem = item || currentItemToken, tokenBeforeComma = sourceCode.getTokenBefore(commaToken); @@ -158,7 +158,7 @@ module.exports = { */ if (arrayLiteral) { - var lastToken = sourceCode.getLastToken(node), + let lastToken = sourceCode.getLastToken(node), nextToLastToken = sourceCode.getTokenBefore(lastToken); if (isComma(nextToLastToken)) { @@ -177,7 +177,7 @@ module.exports = { // Public //-------------------------------------------------------------------------- - var nodes = {}; + let nodes = {}; if (!exceptions.VariableDeclaration) { nodes.VariableDeclaration = function(node) { diff --git a/tools/eslint/lib/rules/complexity.js b/tools/eslint/lib/rules/complexity.js index 029b739808..394df98c44 100644 --- a/tools/eslint/lib/rules/complexity.js +++ b/tools/eslint/lib/rules/complexity.js @@ -45,7 +45,7 @@ module.exports = { }, create: function(context) { - var option = context.options[0], + let option = context.options[0], THRESHOLD = 20; if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { @@ -63,7 +63,7 @@ module.exports = { //-------------------------------------------------------------------------- // Using a stack to store complexity (handling nested functions) - var fns = []; + let fns = []; /** * When parsing a new function, store it in our function stack @@ -81,7 +81,7 @@ module.exports = { * @private */ function endFunction(node) { - var complexity = fns.pop(), + let complexity = fns.pop(), name = "anonymous"; if (node.id) { diff --git a/tools/eslint/lib/rules/computed-property-spacing.js b/tools/eslint/lib/rules/computed-property-spacing.js index 89f0cc87b1..1122c5c83c 100644 --- a/tools/eslint/lib/rules/computed-property-spacing.js +++ b/tools/eslint/lib/rules/computed-property-spacing.js @@ -4,7 +4,7 @@ */ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -28,8 +28,8 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); - var propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never" + let sourceCode = context.getSourceCode(); + let propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never" //-------------------------------------------------------------------------- // Helpers @@ -46,7 +46,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "There should be no space after '" + token.value + "'", + message: "There should be no space after '" + token.value + "'.", fix: function(fixer) { return fixer.removeRange([token.range[1], tokenAfter.range[0]]); } @@ -64,7 +64,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "There should be no space before '" + token.value + "'", + message: "There should be no space before '" + token.value + "'.", fix: function(fixer) { return fixer.removeRange([tokenBefore.range[1], token.range[0]]); } @@ -81,7 +81,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "A space is required after '" + token.value + "'", + message: "A space is required after '" + token.value + "'.", fix: function(fixer) { return fixer.insertTextAfter(token, " "); } @@ -98,7 +98,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "A space is required before '" + token.value + "'", + message: "A space is required before '" + token.value + "'.", fix: function(fixer) { return fixer.insertTextBefore(token, " "); } @@ -108,7 +108,7 @@ module.exports = { /** * Returns a function that checks the spacing of a node on the property name * that was passed in. - * @param {String} propertyName The property on the node to check for spacing + * @param {string} propertyName The property on the node to check for spacing * @returns {Function} A function that will check spacing on a node */ function checkSpacing(propertyName) { @@ -117,9 +117,9 @@ module.exports = { return; } - var property = node[propertyName]; + let property = node[propertyName]; - var before = sourceCode.getTokenBefore(property), + let before = sourceCode.getTokenBefore(property), first = sourceCode.getFirstToken(property), last = sourceCode.getLastToken(property), after = sourceCode.getTokenAfter(property); diff --git a/tools/eslint/lib/rules/consistent-return.js b/tools/eslint/lib/rules/consistent-return.js index 10f1d41cf4..ffadd31bfd 100644 --- a/tools/eslint/lib/rules/consistent-return.js +++ b/tools/eslint/lib/rules/consistent-return.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -57,9 +57,9 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; - var treatUndefinedAsUnspecified = options.treatUndefinedAsUnspecified === true; - var funcInfo = null; + let options = context.options[0] || {}; + let treatUndefinedAsUnspecified = options.treatUndefinedAsUnspecified === true; + let funcInfo = null; /** * Checks whether of not the implicit returning is consistent if the last @@ -69,7 +69,7 @@ module.exports = { * @returns {void} */ function checkLastSegment(node) { - var loc, type; + let loc, type; /* * Skip if it expected no return value or unreachable. @@ -135,8 +135,8 @@ module.exports = { // Reports a given return statement if it's inconsistent. ReturnStatement: function(node) { - var argument = node.argument; - var hasReturnValue = Boolean(argument); + let argument = node.argument; + let hasReturnValue = Boolean(argument); if (treatUndefinedAsUnspecified && hasReturnValue) { hasReturnValue = !isIdentifier(argument, "undefined") && argument.operator !== "void"; diff --git a/tools/eslint/lib/rules/consistent-this.js b/tools/eslint/lib/rules/consistent-this.js index 042e1a0aae..339c43995e 100644 --- a/tools/eslint/lib/rules/consistent-this.js +++ b/tools/eslint/lib/rules/consistent-this.js @@ -27,7 +27,7 @@ module.exports = { }, create: function(context) { - var aliases = []; + let aliases = []; if (context.options.length === 0) { aliases.push("that"); @@ -57,7 +57,7 @@ module.exports = { * @returns {void} */ function checkAssignment(node, name, value) { - var isThis = value.type === "ThisExpression"; + let isThis = value.type === "ThisExpression"; if (aliases.indexOf(name) !== -1) { if (!isThis || node.operator && node.operator !== "=") { @@ -73,12 +73,12 @@ module.exports = { * Ensures that a variable declaration of the alias in a program or function * is assigned to the correct value. * @param {string} alias alias the check the assignment of. - * @param {object} scope scope of the current code we are checking. + * @param {Object} scope scope of the current code we are checking. * @private * @returns {void} */ function checkWasAssigned(alias, scope) { - var variable = scope.set.get(alias); + let variable = scope.set.get(alias); if (!variable) { return; @@ -94,7 +94,7 @@ module.exports = { // The alias has been declared and not assigned: check it was // assigned later in the same scope. if (!variable.references.some(function(reference) { - var write = reference.writeExpr; + let write = reference.writeExpr; return ( reference.from === scope && @@ -115,7 +115,7 @@ module.exports = { * @returns {void} */ function ensureWasAssigned() { - var scope = context.getScope(); + let scope = context.getScope(); aliases.forEach(function(alias) { checkWasAssigned(alias, scope); @@ -128,8 +128,8 @@ module.exports = { "FunctionDeclaration:exit": ensureWasAssigned, VariableDeclarator: function(node) { - var id = node.id; - var isDestructuring = + let id = node.id; + let isDestructuring = id.type === "ArrayPattern" || id.type === "ObjectPattern"; if (node.init !== null && !isDestructuring) { diff --git a/tools/eslint/lib/rules/constructor-super.js b/tools/eslint/lib/rules/constructor-super.js index 4b2aacf575..7b7e8cfd3e 100644 --- a/tools/eslint/lib/rules/constructor-super.js +++ b/tools/eslint/lib/rules/constructor-super.js @@ -75,10 +75,11 @@ function isPossibleConstructor(node) { isPossibleConstructor(node.consequent) ); - case "SequenceExpression": - var lastExpression = node.expressions[node.expressions.length - 1]; + case "SequenceExpression": { + const lastExpression = node.expressions[node.expressions.length - 1]; return isPossibleConstructor(lastExpression); + } default: return false; @@ -111,7 +112,7 @@ module.exports = { * - scope: The scope of own class. * - codePath: The code path object of the constructor. */ - var funcInfo = null; + let funcInfo = null; /* * {Map<string, {calledInSomePaths: boolean, calledInEveryPaths: boolean}>} @@ -120,7 +121,7 @@ module.exports = { * - calledInEveryPaths: A flag of be called `super()` in all code paths. * - validNodes: */ - var segInfoMap = Object.create(null); + let segInfoMap = Object.create(null); /** * Gets the flag which shows `super()` is called in some paths. @@ -163,8 +164,8 @@ module.exports = { if (isConstructorFunction(node)) { // Class > ClassBody > MethodDefinition > FunctionExpression - var classNode = node.parent.parent.parent; - var superClass = classNode.superClass; + let classNode = node.parent.parent.parent; + let superClass = classNode.superClass; funcInfo = { upper: funcInfo, @@ -192,7 +193,7 @@ module.exports = { * @returns {void} */ onCodePathEnd: function(codePath, node) { - var hasExtends = funcInfo.hasExtends; + let hasExtends = funcInfo.hasExtends; // Pop. funcInfo = funcInfo.upper; @@ -202,9 +203,9 @@ module.exports = { } // Reports if `super()` lacked. - var segments = codePath.returnedSegments; - var calledInEveryPaths = segments.every(isCalledInEveryPath); - var calledInSomePaths = segments.some(isCalledInSomePath); + let segments = codePath.returnedSegments; + let calledInEveryPaths = segments.every(isCalledInEveryPath); + let calledInSomePaths = segments.some(isCalledInSomePath); if (!calledInEveryPaths) { context.report({ @@ -227,14 +228,14 @@ module.exports = { } // Initialize info. - var info = segInfoMap[segment.id] = { + let info = segInfoMap[segment.id] = { calledInSomePaths: false, calledInEveryPaths: false, validNodes: [] }; // When there are previous segments, aggregates these. - var prevSegments = segment.prevSegments; + let prevSegments = segment.prevSegments; if (prevSegments.length > 0) { info.calledInSomePaths = prevSegments.some(isCalledInSomePath); @@ -257,13 +258,13 @@ module.exports = { } // Update information inside of the loop. - var isRealLoop = toSegment.prevSegments.length >= 2; + let isRealLoop = toSegment.prevSegments.length >= 2; funcInfo.codePath.traverseSegments( {first: toSegment, last: fromSegment}, function(segment) { - var info = segInfoMap[segment.id]; - var prevSegments = segment.prevSegments; + let info = segInfoMap[segment.id]; + let prevSegments = segment.prevSegments; // Updates flags. info.calledInSomePaths = prevSegments.some(isCalledInSomePath); @@ -271,12 +272,12 @@ module.exports = { // If flags become true anew, reports the valid nodes. if (info.calledInSomePaths || isRealLoop) { - var nodes = info.validNodes; + let nodes = info.validNodes; info.validNodes = []; - for (var i = 0; i < nodes.length; ++i) { - var node = nodes[i]; + for (let i = 0; i < nodes.length; ++i) { + let node = nodes[i]; context.report({ message: "Unexpected duplicate 'super()'.", @@ -305,23 +306,22 @@ module.exports = { // Reports if needed. if (funcInfo.hasExtends) { - var segments = funcInfo.codePath.currentSegments; - var reachable = false; - var duplicate = false; + let segments = funcInfo.codePath.currentSegments; + let duplicate = false; + let info = null; - for (var i = 0; i < segments.length; ++i) { - var segment = segments[i]; + for (let i = 0; i < segments.length; ++i) { + let segment = segments[i]; if (segment.reachable) { - var info = segInfoMap[segment.id]; + info = segInfoMap[segment.id]; - reachable = true; duplicate = duplicate || info.calledInSomePaths; info.calledInSomePaths = info.calledInEveryPaths = true; } } - if (reachable) { + if (info) { if (duplicate) { context.report({ message: "Unexpected duplicate 'super()'.", @@ -360,13 +360,13 @@ module.exports = { } // Returning argument is a substitute of 'super()'. - var segments = funcInfo.codePath.currentSegments; + let segments = funcInfo.codePath.currentSegments; - for (var i = 0; i < segments.length; ++i) { - var segment = segments[i]; + for (let i = 0; i < segments.length; ++i) { + let segment = segments[i]; if (segment.reachable) { - var info = segInfoMap[segment.id]; + let info = segInfoMap[segment.id]; info.calledInSomePaths = info.calledInEveryPaths = true; } diff --git a/tools/eslint/lib/rules/curly.js b/tools/eslint/lib/rules/curly.js index 257366fabe..912f321565 100644 --- a/tools/eslint/lib/rules/curly.js +++ b/tools/eslint/lib/rules/curly.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -53,12 +53,12 @@ module.exports = { create: function(context) { - var multiOnly = (context.options[0] === "multi"); - var multiLine = (context.options[0] === "multi-line"); - var multiOrNest = (context.options[0] === "multi-or-nest"); - var consistent = (context.options[1] === "consistent"); + let multiOnly = (context.options[0] === "multi"); + let multiLine = (context.options[0] === "multi-line"); + let multiOrNest = (context.options[0] === "multi-or-nest"); + let consistent = (context.options[1] === "consistent"); - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -71,7 +71,7 @@ module.exports = { * @private */ function isCollapsedOneLiner(node) { - var before = sourceCode.getTokenBefore(node), + let before = sourceCode.getTokenBefore(node), last = sourceCode.getLastToken(node); return before.loc.start.line === last.loc.end.line; @@ -84,7 +84,7 @@ module.exports = { * @private */ function isOneLiner(node) { - var first = sourceCode.getFirstToken(node), + let first = sourceCode.getFirstToken(node), last = sourceCode.getLastToken(node); return first.loc.start.line === last.loc.end.line; @@ -96,7 +96,7 @@ module.exports = { * @returns {Token} The `else` keyword token. */ function getElseKeyword(node) { - var token = sourceCode.getTokenAfter(node.consequent); + let token = sourceCode.getTokenAfter(node.consequent); while (token.type !== "Keyword" || token.value !== "else") { token = sourceCode.getTokenAfter(token); @@ -180,7 +180,7 @@ module.exports = { * @param {ASTNode} body The body node to check for blocks. * @param {string} name The name to report if there's a problem. * @param {string} suffix Additional string to add to the end of a report. - * @returns {object} a prepared check object, with "actual", "expected", "check" properties. + * @returns {Object} a prepared check object, with "actual", "expected", "check" properties. * "actual" will be `true` or `false` whether the body is already a block statement. * "expected" will be `true` or `false` if the body should be a block statement or not, or * `null` if it doesn't matter, depending on the rule options. It can be modified to change @@ -189,8 +189,8 @@ module.exports = { * properties. */ function prepareCheck(node, body, name, suffix) { - var hasBlock = (body.type === "BlockStatement"); - var expected = null; + let hasBlock = (body.type === "BlockStatement"); + let expected = null; if (node.type === "IfStatement" && node.consequent === body && requiresBraceOfConsequent(node)) { expected = true; @@ -230,11 +230,11 @@ module.exports = { /** * Prepares to check the bodies of a "if", "else if" and "else" chain. * @param {ASTNode} node The first IfStatement node of the chain. - * @returns {object[]} prepared checks for each body of the chain. See `prepareCheck` for more + * @returns {Object[]} prepared checks for each body of the chain. See `prepareCheck` for more * information. */ function prepareIfChecks(node) { - var preparedChecks = []; + let preparedChecks = []; do { preparedChecks.push(prepareCheck(node, node.consequent, "if", "condition")); @@ -252,7 +252,7 @@ module.exports = { * all have braces. * If all nodes shouldn't have braces, make sure they don't. */ - var expected = preparedChecks.some(function(preparedCheck) { + let expected = preparedChecks.some(function(preparedCheck) { if (preparedCheck.expected !== null) { return preparedCheck.expected; } diff --git a/tools/eslint/lib/rules/default-case.js b/tools/eslint/lib/rules/default-case.js index ae70a59284..9bcb1c065b 100644 --- a/tools/eslint/lib/rules/default-case.js +++ b/tools/eslint/lib/rules/default-case.js @@ -4,7 +4,7 @@ */ "use strict"; -var DEFAULT_COMMENT_PATTERN = /^no default$/; +let DEFAULT_COMMENT_PATTERN = /^no default$/; //------------------------------------------------------------------------------ // Rule Definition @@ -30,12 +30,12 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; - var commentPattern = options.commentPattern ? + let options = context.options[0] || {}; + let commentPattern = options.commentPattern ? new RegExp(options.commentPattern) : DEFAULT_COMMENT_PATTERN; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -67,16 +67,16 @@ module.exports = { return; } - var hasDefault = node.cases.some(function(v) { + let hasDefault = node.cases.some(function(v) { return v.test === null; }); if (!hasDefault) { - var comment; - var comments; + let comment; + let comments; - var lastCase = last(node.cases); + let lastCase = last(node.cases); comments = sourceCode.getComments(lastCase).trailing; diff --git a/tools/eslint/lib/rules/dot-location.js b/tools/eslint/lib/rules/dot-location.js index 2b29e0f49b..5a5ad353bf 100644 --- a/tools/eslint/lib/rules/dot-location.js +++ b/tools/eslint/lib/rules/dot-location.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -28,12 +28,12 @@ module.exports = { create: function(context) { - var config = context.options[0]; + let config = context.options[0]; // default to onObject if no preference is passed - var onObject = config === "object" || !config; + let onObject = config === "object" || !config; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Reports if the dot between object and property is on the correct loccation. @@ -43,7 +43,7 @@ module.exports = { * @returns {void} */ function checkDotLocation(obj, prop, node) { - var dot = sourceCode.getTokenBefore(prop); + let dot = sourceCode.getTokenBefore(prop); if (dot.type === "Punctuator" && dot.value === ".") { if (onObject) { diff --git a/tools/eslint/lib/rules/dot-notation.js b/tools/eslint/lib/rules/dot-notation.js index 07e0b0a8db..e359b118cc 100644 --- a/tools/eslint/lib/rules/dot-notation.js +++ b/tools/eslint/lib/rules/dot-notation.js @@ -8,8 +8,8 @@ // Rule Definition //------------------------------------------------------------------------------ -var validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; -var keywords = require("../util/keywords"); +let validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; +let keywords = require("../util/keywords"); module.exports = { meta: { @@ -36,10 +36,10 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; - var allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords; + let options = context.options[0] || {}; + let allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords; - var allowPattern; + let allowPattern; if (options.allowPattern) { allowPattern = new RegExp(options.allowPattern); diff --git a/tools/eslint/lib/rules/eol-last.js b/tools/eslint/lib/rules/eol-last.js index 60b070f1ab..faa4521cf1 100644 --- a/tools/eslint/lib/rules/eol-last.js +++ b/tools/eslint/lib/rules/eol-last.js @@ -35,7 +35,7 @@ module.exports = { Program: function checkBadEOF(node) { - var sourceCode = context.getSourceCode(), + let sourceCode = context.getSourceCode(), src = sourceCode.getText(), location = {column: 1}, linebreakStyle = context.options[0] || "unix", diff --git a/tools/eslint/lib/rules/eqeqeq.js b/tools/eslint/lib/rules/eqeqeq.js index 441f5b751c..124c9dd61a 100644 --- a/tools/eslint/lib/rules/eqeqeq.js +++ b/tools/eslint/lib/rules/eqeqeq.js @@ -25,7 +25,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Checks if an expression is a typeof expression @@ -71,12 +71,12 @@ module.exports = { /** * Gets the location (line and column) of the binary expression's operator * @param {ASTNode} node The binary expression node to check - * @param {String} operator The operator to find + * @param {string} operator The operator to find * @returns {Object} { line, column } location of operator * @private */ function getOperatorLocation(node) { - var opToken = sourceCode.getTokenAfter(node.left); + let opToken = sourceCode.getTokenAfter(node.left); return {line: opToken.loc.start.line, column: opToken.loc.start.column}; } diff --git a/tools/eslint/lib/rules/func-names.js b/tools/eslint/lib/rules/func-names.js index 44b989b2c4..12d8d34d5d 100644 --- a/tools/eslint/lib/rules/func-names.js +++ b/tools/eslint/lib/rules/func-names.js @@ -5,6 +5,15 @@ "use strict"; +/** + * Checks whether or not a given variable is a function name. + * @param {escope.Variable} variable - A variable to check. + * @returns {boolean} `true` if the variable is a function name. + */ +function isFunctionName(variable) { + return variable && variable.defs[0].type === "FunctionName"; +} + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -25,7 +34,7 @@ module.exports = { }, create: function(context) { - var never = context.options[0] === "never"; + let never = context.options[0] === "never"; /** * Determines whether the current FunctionExpression node is a get, set, or @@ -33,7 +42,7 @@ module.exports = { * @returns {boolean} True if the node is a get, set, or shorthand method. */ function isObjectOrClassMethod() { - var parent = context.getAncestors().pop(); + let parent = context.getAncestors().pop(); return (parent.type === "MethodDefinition" || ( parent.type === "Property" && ( @@ -45,9 +54,16 @@ module.exports = { } return { - FunctionExpression: function(node) { + "FunctionExpression:exit": function(node) { + + // Skip recursive functions. + let nameVar = context.getDeclaredVariables(node)[0]; + + if (isFunctionName(nameVar) && nameVar.references.length > 0) { + return; + } - var name = node.id && node.id.name; + let name = node.id && node.id.name; if (never) { if (name) { diff --git a/tools/eslint/lib/rules/func-style.js b/tools/eslint/lib/rules/func-style.js index 9dad6c0755..e1cdc1d1bd 100644 --- a/tools/eslint/lib/rules/func-style.js +++ b/tools/eslint/lib/rules/func-style.js @@ -34,12 +34,12 @@ module.exports = { create: function(context) { - var style = context.options[0], + let style = context.options[0], allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions === true, enforceDeclarations = (style === "declaration"), stack = []; - var nodesToCheck = { + let nodesToCheck = { Program: function() { stack = []; }, @@ -79,7 +79,7 @@ module.exports = { }; nodesToCheck["ArrowFunctionExpression:exit"] = function(node) { - var hasThisExpr = stack.pop(); + let hasThisExpr = stack.pop(); if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") { context.report(node.parent, "Expected a function declaration."); diff --git a/tools/eslint/lib/rules/generator-star-spacing.js b/tools/eslint/lib/rules/generator-star-spacing.js index 0cab2be50e..e55fe9b512 100644 --- a/tools/eslint/lib/rules/generator-star-spacing.js +++ b/tools/eslint/lib/rules/generator-star-spacing.js @@ -40,7 +40,7 @@ module.exports = { create: function(context) { - var mode = (function(option) { + let mode = (function(option) { if (!option || typeof option === "string") { return { before: { before: true, after: false }, @@ -52,7 +52,7 @@ module.exports = { return option; }(context.options[0])); - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Gets `*` token from a given node. @@ -63,7 +63,7 @@ module.exports = { * @returns {Token} `*` token. */ function getStarToken(node) { - var token = sourceCode.getFirstToken(node); + let token = sourceCode.getFirstToken(node); while (token.value !== "*") { token = sourceCode.getTokenAfter(token); @@ -83,11 +83,11 @@ module.exports = { */ function checkSpacing(side, leftToken, rightToken) { if (!!(rightToken.range[0] - leftToken.range[1]) !== mode[side]) { - var after = leftToken.value === "*"; - var spaceRequired = mode[side]; - var node = after ? leftToken : rightToken; - var type = spaceRequired ? "Missing" : "Unexpected"; - var message = type + " space " + side + " *."; + let after = leftToken.value === "*"; + let spaceRequired = mode[side]; + let node = after ? leftToken : rightToken; + let type = spaceRequired ? "Missing" : "Unexpected"; + let message = type + " space " + side + " *."; context.report({ node: node, @@ -111,7 +111,7 @@ module.exports = { * @returns {void} */ function checkFunction(node) { - var prevToken, starToken, nextToken; + let prevToken, starToken, nextToken; if (!node.generator) { return; diff --git a/tools/eslint/lib/rules/global-require.js b/tools/eslint/lib/rules/global-require.js index d1298719a9..0a104bc349 100644 --- a/tools/eslint/lib/rules/global-require.js +++ b/tools/eslint/lib/rules/global-require.js @@ -5,7 +5,7 @@ "use strict"; -var ACCEPTABLE_PARENTS = [ +let ACCEPTABLE_PARENTS = [ "AssignmentExpression", "VariableDeclarator", "MemberExpression", @@ -23,7 +23,7 @@ var ACCEPTABLE_PARENTS = [ * @returns {Reference|null} Returns the found reference or null if none were found. */ function findReference(scope, node) { - var references = scope.references.filter(function(reference) { + let references = scope.references.filter(function(reference) { return reference.identifier.range[0] === node.range[0] && reference.identifier.range[1] === node.range[1]; }); @@ -43,7 +43,7 @@ function findReference(scope, node) { * @returns {boolean} Whether or not the name is shadowed. */ function isShadowed(scope, node) { - var reference = findReference(scope, node); + let reference = findReference(scope, node); return reference && reference.resolved && reference.resolved.defs.length > 0; } @@ -62,7 +62,7 @@ module.exports = { create: function(context) { return { CallExpression: function(node) { - var currentScope = context.getScope(), + let currentScope = context.getScope(), isGoodRequire; if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) { diff --git a/tools/eslint/lib/rules/guard-for-in.js b/tools/eslint/lib/rules/guard-for-in.js index b43dda39e4..7e4dfbc43e 100644 --- a/tools/eslint/lib/rules/guard-for-in.js +++ b/tools/eslint/lib/rules/guard-for-in.js @@ -30,7 +30,7 @@ module.exports = { * If the for-in statement has {}, then the real body is the body * of the BlockStatement. Otherwise, just use body as provided. */ - var body = node.body.type === "BlockStatement" ? node.body.body[0] : node.body; + let body = node.body.type === "BlockStatement" ? node.body.body[0] : node.body; if (body && body.type !== "IfStatement") { context.report(node, "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype."); diff --git a/tools/eslint/lib/rules/handle-callback-err.js b/tools/eslint/lib/rules/handle-callback-err.js index 09bf0da977..836d3a6de7 100644 --- a/tools/eslint/lib/rules/handle-callback-err.js +++ b/tools/eslint/lib/rules/handle-callback-err.js @@ -26,7 +26,7 @@ module.exports = { create: function(context) { - var errorArgument = context.options[0] || "err"; + let errorArgument = context.options[0] || "err"; /** * Checks if the given argument should be interpreted as a regexp pattern. @@ -34,7 +34,7 @@ module.exports = { * @returns {boolean} Whether or not the string should be interpreted as a pattern. */ function isPattern(stringToCheck) { - var firstChar = stringToCheck[0]; + let firstChar = stringToCheck[0]; return firstChar === "^"; } @@ -46,7 +46,7 @@ module.exports = { */ function matchesConfiguredErrorName(name) { if (isPattern(errorArgument)) { - var regexp = new RegExp(errorArgument); + let regexp = new RegExp(errorArgument); return regexp.test(name); } @@ -55,7 +55,7 @@ module.exports = { /** * Get the parameters of a given function scope. - * @param {object} scope The function scope. + * @param {Object} scope The function scope. * @returns {array} All parameters of the given scope. */ function getParameters(scope) { @@ -70,7 +70,7 @@ module.exports = { * @returns {void} */ function checkForError(node) { - var scope = context.getScope(), + let scope = context.getScope(), parameters = getParameters(scope), firstParameter = parameters[0]; diff --git a/tools/eslint/lib/rules/id-blacklist.js b/tools/eslint/lib/rules/id-blacklist.js index 142d8d21f4..d2be0d12c3 100644 --- a/tools/eslint/lib/rules/id-blacklist.js +++ b/tools/eslint/lib/rules/id-blacklist.js @@ -34,12 +34,12 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - var blacklist = context.options; + let blacklist = context.options; /** * Checks if a string matches the provided pattern - * @param {String} name The string to check. + * @param {string} name The string to check. * @returns {boolean} if the string is a match * @private */ @@ -51,7 +51,7 @@ module.exports = { * Verifies if we should report an error or not based on the effective * parent node and the identifier name. * @param {ASTNode} effectiveParent The effective parent node of the node to be reported - * @param {String} name The identifier name of the identifier node + * @param {string} name The identifier name of the identifier node * @returns {boolean} whether an error should be reported or not */ function shouldReport(effectiveParent, name) { @@ -67,7 +67,7 @@ module.exports = { * @private */ function report(node) { - context.report(node, "Identifier '{{name}}' is blacklisted", { + context.report(node, "Identifier '{{name}}' is blacklisted.", { name: node.name }); } @@ -75,7 +75,7 @@ module.exports = { return { Identifier: function(node) { - var name = node.name, + let name = node.name, effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent; // MemberExpressions get special rules diff --git a/tools/eslint/lib/rules/id-length.js b/tools/eslint/lib/rules/id-length.js index 43437513ac..d337cdacce 100644 --- a/tools/eslint/lib/rules/id-length.js +++ b/tools/eslint/lib/rules/id-length.js @@ -45,18 +45,18 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; - var minLength = typeof options.min !== "undefined" ? options.min : 2; - var maxLength = typeof options.max !== "undefined" ? options.max : Infinity; - var properties = options.properties !== "never"; - var exceptions = (options.exceptions ? options.exceptions : []) + let options = context.options[0] || {}; + let minLength = typeof options.min !== "undefined" ? options.min : 2; + let maxLength = typeof options.max !== "undefined" ? options.max : Infinity; + let properties = options.properties !== "never"; + let exceptions = (options.exceptions ? options.exceptions : []) .reduce(function(obj, item) { obj[item] = true; return obj; }, {}); - var SUPPORTED_EXPRESSIONS = { + let SUPPORTED_EXPRESSIONS = { MemberExpression: properties && function(parent) { return !parent.computed && ( @@ -87,24 +87,24 @@ module.exports = { return { Identifier: function(node) { - var name = node.name; - var parent = node.parent; + let name = node.name; + let parent = node.parent; - var isShort = name.length < minLength; - var isLong = name.length > maxLength; + let isShort = name.length < minLength; + let isLong = name.length > maxLength; if (!(isShort || isLong) || exceptions[name]) { return; // Nothing to report } - var isValidExpression = SUPPORTED_EXPRESSIONS[parent.type]; + let isValidExpression = SUPPORTED_EXPRESSIONS[parent.type]; if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) { context.report( node, isShort ? - "Identifier name '{{name}}' is too short. (< {{min}})" : - "Identifier name '{{name}}' is too long. (> {{max}})", + "Identifier name '{{name}}' is too short (< {{min}})." : + "Identifier name '{{name}}' is too long (> {{max}}).", { name: name, min: minLength, max: maxLength } ); } diff --git a/tools/eslint/lib/rules/id-match.js b/tools/eslint/lib/rules/id-match.js index 4c9f435108..4128cbf3d1 100644 --- a/tools/eslint/lib/rules/id-match.js +++ b/tools/eslint/lib/rules/id-match.js @@ -38,16 +38,16 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - var pattern = context.options[0] || "^.+$", + let pattern = context.options[0] || "^.+$", regexp = new RegExp(pattern); - var options = context.options[1] || {}, + let options = context.options[1] || {}, properties = !!options.properties, onlyDeclarations = !!options.onlyDeclarations; /** * Checks if a string matches the provided pattern - * @param {String} name The string to check. + * @param {string} name The string to check. * @returns {boolean} if the string is a match * @private */ @@ -59,7 +59,7 @@ module.exports = { * Verifies if we should report an error or not based on the effective * parent node and the identifier name. * @param {ASTNode} effectiveParent The effective parent node of the node to be reported - * @param {String} name The identifier name of the identifier node + * @param {string} name The identifier name of the identifier node * @returns {boolean} whether an error should be reported or not */ function shouldReport(effectiveParent, name) { @@ -84,7 +84,7 @@ module.exports = { return { Identifier: function(node) { - var name = node.name, + let name = node.name, parent = node.parent, effectiveParent = (parent.type === "MemberExpression") ? parent.parent : parent; @@ -122,7 +122,7 @@ module.exports = { } } else { - var isDeclaration = effectiveParent.type === "FunctionDeclaration" || effectiveParent.type === "VariableDeclarator"; + let isDeclaration = effectiveParent.type === "FunctionDeclaration" || effectiveParent.type === "VariableDeclarator"; if (onlyDeclarations && !isDeclaration) { return; diff --git a/tools/eslint/lib/rules/indent.js b/tools/eslint/lib/rules/indent.js index 3c0c9827d8..b24f942d1a 100644 --- a/tools/eslint/lib/rules/indent.js +++ b/tools/eslint/lib/rules/indent.js @@ -11,8 +11,8 @@ //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -var util = require("util"); -var lodash = require("lodash"); +let util = require("util"); +let lodash = require("lodash"); module.exports = { meta: { @@ -71,6 +71,10 @@ module.exports = { outerIIFEBody: { type: "integer", minimum: 0 + }, + MemberExpression: { + type: "integer", + minimum: 0 } }, additionalProperties: false @@ -80,12 +84,12 @@ module.exports = { create: function(context) { - var MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}."; - var DEFAULT_VARIABLE_INDENT = 1; + let MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}."; + let DEFAULT_VARIABLE_INDENT = 1; - var indentType = "space"; - var indentSize = 4; - var options = { + let indentType = "space"; + let indentSize = 4; + let options = { SwitchCase: 0, VariableDeclarator: { var: DEFAULT_VARIABLE_INDENT, @@ -95,7 +99,7 @@ module.exports = { outerIIFEBody: null }; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); if (context.options.length) { if (context.options[0] === "tab") { @@ -107,10 +111,10 @@ module.exports = { } if (context.options[1]) { - var opts = context.options[1]; + let opts = context.options[1]; options.SwitchCase = opts.SwitchCase || 0; - var variableDeclaratorRules = opts.VariableDeclarator; + let variableDeclaratorRules = opts.VariableDeclarator; if (typeof variableDeclaratorRules === "number") { options.VariableDeclarator = { @@ -125,15 +129,19 @@ module.exports = { if (typeof opts.outerIIFEBody === "number") { options.outerIIFEBody = opts.outerIIFEBody; } + + if (typeof opts.MemberExpression === "number") { + options.MemberExpression = opts.MemberExpression; + } } } - var indentPattern = { + let indentPattern = { normal: indentType === "space" ? /^ +/ : /^\t+/, excludeCommas: indentType === "space" ? /^[ ,]+/ : /^[\t,]+/ }; - var caseIndentStore = {}; + let caseIndentStore = {}; /** * Reports a given indent violation and properly pluralizes the message @@ -145,13 +153,13 @@ module.exports = { * @returns {void} */ function report(node, needed, gotten, loc, isLastNodeCheck) { - var msgContext = { + let msgContext = { needed: needed, type: indentType, characters: needed === 1 ? "character" : "characters", gotten: gotten }; - var indentChar = indentType === "space" ? " " : "\t"; + let indentChar = indentType === "space" ? " " : "\t"; /** * Responsible for fixing the indentation issue fix @@ -159,10 +167,10 @@ module.exports = { * @private */ function getFixerFunction() { - var rangeToFix = []; + let rangeToFix = []; if (needed > gotten) { - var spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future + let spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future if (isLastNodeCheck === true) { rangeToFix = [ @@ -224,10 +232,10 @@ module.exports = { * @returns {int} Indent */ function getNodeIndent(node, byLastLine, excludeCommas) { - var token = byLastLine ? sourceCode.getLastToken(node) : sourceCode.getFirstToken(node); - var src = sourceCode.getText(token, token.loc.start.column); - var regExp = excludeCommas ? indentPattern.excludeCommas : indentPattern.normal; - var indent = regExp.exec(src); + let token = byLastLine ? sourceCode.getLastToken(node) : sourceCode.getFirstToken(node); + let src = sourceCode.getText(token, token.loc.start.column); + let regExp = excludeCommas ? indentPattern.excludeCommas : indentPattern.normal; + let indent = regExp.exec(src); return indent ? indent[0].length : 0; } @@ -239,7 +247,7 @@ module.exports = { * @returns {boolean} true if its the first in the its start line */ function isNodeFirstInLine(node, byEndLocation) { - var firstToken = byEndLocation === true ? sourceCode.getLastToken(node, 1) : sourceCode.getTokenBefore(node), + let firstToken = byEndLocation === true ? sourceCode.getLastToken(node, 1) : sourceCode.getTokenBefore(node), startLine = byEndLocation === true ? node.loc.end.line : node.loc.start.line, endLine = firstToken ? firstToken.loc.end.line : -1; @@ -254,7 +262,7 @@ module.exports = { * @returns {void} */ function checkNodeIndent(node, indent, excludeCommas) { - var nodeIndent = getNodeIndent(node, false, excludeCommas); + let nodeIndent = getNodeIndent(node, false, excludeCommas); if ( node.type !== "ArrayExpression" && node.type !== "ObjectExpression" && @@ -274,7 +282,7 @@ module.exports = { function checkNodesIndent(nodes, indent, excludeCommas) { nodes.forEach(function(node) { if (node.type === "IfStatement" && node.alternate) { - var elseToken = sourceCode.getTokenBefore(node.alternate); + let elseToken = sourceCode.getTokenBefore(node.alternate); checkNodeIndent(elseToken, indent, excludeCommas); } @@ -289,8 +297,8 @@ module.exports = { * @returns {void} */ function checkLastNodeLineIndent(node, lastLineIndent) { - var lastToken = sourceCode.getLastToken(node); - var endIndent = getNodeIndent(lastToken, true); + let lastToken = sourceCode.getLastToken(node); + let endIndent = getNodeIndent(lastToken, true); if (endIndent !== lastLineIndent && isNodeFirstInLine(node, true)) { report( @@ -310,7 +318,7 @@ module.exports = { * @returns {void} */ function checkFirstNodeLineIndent(node, firstLineIndent) { - var startIndent = getNodeIndent(node, false); + let startIndent = getNodeIndent(node, false); if (startIndent !== firstLineIndent && isNodeFirstInLine(node)) { report( @@ -323,19 +331,40 @@ module.exports = { } /** - * Returns the VariableDeclarator based on the current node + * Returns a parent node of given node based on a specified type * if not present then return null * @param {ASTNode} node node to examine + * @param {string} type type that is being looked for * @returns {ASTNode|void} if found then node otherwise null */ - function getVariableDeclaratorNode(node) { - var parent = node.parent; + function getParentNodeByType(node, type) { + let parent = node.parent; - while (parent.type !== "VariableDeclarator" && parent.type !== "Program") { + while (parent.type !== type && parent.type !== "Program") { parent = parent.parent; } - return parent.type === "VariableDeclarator" ? parent : null; + return parent.type === type ? parent : null; + } + + /** + * Returns the VariableDeclarator based on the current node + * if not present then return null + * @param {ASTNode} node node to examine + * @returns {ASTNode|void} if found then node otherwise null + */ + function getVariableDeclaratorNode(node) { + return getParentNodeByType(node, "VariableDeclarator"); + } + + /** + * Returns the ExpressionStatement based on the current node + * if not present then return null + * @param {ASTNode} node node to examine + * @returns {ASTNode|void} if found then node otherwise null + */ + function getAssignmentExpressionNode(node) { + return getParentNodeByType(node, "AssignmentExpression"); } /** @@ -358,7 +387,7 @@ module.exports = { * @returns {boolean} True if arguments are multi-line */ function isArgBeforeCalleeNodeMultiline(node) { - var parent = node.parent; + let parent = node.parent; if (parent.arguments.length >= 2 && parent.arguments[1] === node) { return parent.arguments[0].loc.end.line > parent.arguments[0].loc.start.line; @@ -367,19 +396,46 @@ module.exports = { return false; } - /** + /** * Check to see if the node is a file level IIFE * @param {ASTNode} node The function node to check. * @returns {boolean} True if the node is the outer IIFE */ function isOuterIIFE(node) { - var parent = node.parent; + let parent = node.parent; + let stmt = parent.parent; - return ( - parent.type === "CallExpression" && - parent.callee === node && - parent.parent.type === "ExpressionStatement" && - parent.parent.parent && parent.parent.parent.type === "Program" + /* + * Verify that the node is an IIEF + */ + if ( + parent.type !== "CallExpression" || + parent.callee !== node) { + + return false; + } + + /* + * Navigate legal ancestors to determine whether this IIEF is outer + */ + while ( + stmt.type === "UnaryExpression" && ( + stmt.operator === "!" || + stmt.operator === "~" || + stmt.operator === "+" || + stmt.operator === "-") || + stmt.type === "AssignmentExpression" || + stmt.type === "LogicalExpression" || + stmt.type === "SequenceExpression" || + stmt.type === "VariableDeclarator") { + + stmt = stmt.parent; + } + + return (( + stmt.type === "ExpressionStatement" || + stmt.type === "VariableDeclaration") && + stmt.parent && stmt.parent.type === "Program" ); } @@ -403,8 +459,8 @@ module.exports = { * * Looks for 'Models' */ - var calleeNode = node.parent; // FunctionExpression - var indent; + let calleeNode = node.parent; // FunctionExpression + let indent; if (calleeNode.parent && (calleeNode.parent.type === "Property" || @@ -419,7 +475,7 @@ module.exports = { } if (calleeNode.parent.type === "CallExpression") { - var calleeParent = calleeNode.parent; + let calleeParent = calleeNode.parent; if (calleeNode.type !== "FunctionExpression" && calleeNode.type !== "ArrowFunctionExpression") { if (calleeParent && calleeParent.loc.start.line < node.loc.start.line) { @@ -436,7 +492,7 @@ module.exports = { // function body indent should be indent + indent size, unless this // is the outer IIFE and that option is enabled. - var functionOffset = indentSize; + let functionOffset = indentSize; if (options.outerIIFEBody !== null && isOuterIIFE(calleeNode)) { functionOffset = options.outerIIFEBody * indentSize; @@ -444,7 +500,7 @@ module.exports = { indent += functionOffset; // check if the node is inside a variable - var parentVarNode = getVariableDeclaratorNode(node); + let parentVarNode = getVariableDeclaratorNode(node); if (parentVarNode && isNodeInVarOnTop(node, parentVarNode)) { indent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind]; @@ -464,7 +520,7 @@ module.exports = { * @returns {boolean} Whether or not the block starts and ends on the same line. */ function isSingleLineNode(node) { - var lastToken = sourceCode.getLastToken(node), + let lastToken = sourceCode.getLastToken(node), startLine = node.loc.start.line, endLine = lastToken.loc.end.line; @@ -497,7 +553,7 @@ module.exports = { return; } - var elements = (node.type === "ArrayExpression") ? node.elements : node.properties; + let elements = (node.type === "ArrayExpression") ? node.elements : node.properties; // filter out empty elements example would be [ , 2] so remove first element as espree considers it as null elements = elements.filter(function(elem) { @@ -509,14 +565,14 @@ module.exports = { return; } - var nodeIndent; - var elementsIndent; - var parentVarNode = getVariableDeclaratorNode(node); + let nodeIndent; + let elementsIndent; + let parentVarNode = getVariableDeclaratorNode(node); // TODO - come up with a better strategy in future if (isNodeFirstInLine(node)) { - var parent = node.parent; - var effectiveParent = parent; + let parent = node.parent; + let effectiveParent = parent; if (parent.type === "MemberExpression") { if (isNodeFirstInLine(parent)) { @@ -605,14 +661,14 @@ module.exports = { return; } - var indent; - var nodesToCheck = []; + let indent; + let nodesToCheck = []; /* * For this statements we should check indent from statement beginning, * not from the beginning of the block. */ - var statementsWithProperties = [ + let statementsWithProperties = [ "IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration" ]; @@ -647,7 +703,7 @@ module.exports = { */ function filterOutSameLineVars(node) { return node.declarations.reduce(function(finalCollection, elem) { - var lastElem = finalCollection[finalCollection.length - 1]; + let lastElem = finalCollection[finalCollection.length - 1]; if ((elem.loc.start.line !== node.loc.start.line && !lastElem) || (lastElem && lastElem.loc.start.line !== elem.loc.start.line)) { @@ -664,11 +720,11 @@ module.exports = { * @returns {void} */ function checkIndentInVariableDeclarations(node) { - var elements = filterOutSameLineVars(node); - var nodeIndent = getNodeIndent(node); - var lastElement = elements[elements.length - 1]; + let elements = filterOutSameLineVars(node); + let nodeIndent = getNodeIndent(node); + let lastElement = elements[elements.length - 1]; - var elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind]; + let elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind]; // Comma can be placed before declaration checkNodesIndent(elements, elementsIndent, true); @@ -678,7 +734,7 @@ module.exports = { return; } - var tokenBeforeLastElement = sourceCode.getTokenBefore(lastElement); + let tokenBeforeLastElement = sourceCode.getTokenBefore(lastElement); if (tokenBeforeLastElement.value === ",") { @@ -708,8 +764,8 @@ module.exports = { * @returns {int} indent size */ function expectedCaseIndent(node, switchIndent) { - var switchNode = (node.type === "SwitchStatement") ? node : node.parent; - var caseIndent; + let switchNode = (node.type === "SwitchStatement") ? node : node.parent; + let caseIndent; if (caseIndentStore[switchNode.loc.start.line]) { return caseIndentStore[switchNode.loc.start.line]; @@ -772,11 +828,45 @@ module.exports = { checkIndentInArrayOrObjectBlock(node); }, + MemberExpression: function(node) { + if (typeof options.MemberExpression === "undefined") { + return; + } + + if (isSingleLineNode(node)) { + return; + } + + // The typical layout of variable declarations and assignments + // alter the expectation of correct indentation. Skip them. + // TODO: Add appropriate configuration options for variable + // declarations and assignments. + if (getVariableDeclaratorNode(node)) { + return; + } + + if (getAssignmentExpressionNode(node)) { + return; + } + + let propertyIndent = getNodeIndent(node) + indentSize * options.MemberExpression; + + let checkNodes = [node.property]; + + let dot = context.getTokenBefore(node.property); + + if (dot.type === "Punctuator" && dot.value === ".") { + checkNodes.push(dot); + } + + checkNodesIndent(checkNodes, propertyIndent); + }, + SwitchStatement: function(node) { // Switch is not a 'BlockStatement' - var switchIndent = getNodeIndent(node); - var caseIndent = expectedCaseIndent(node, switchIndent); + let switchIndent = getNodeIndent(node); + let caseIndent = expectedCaseIndent(node, switchIndent); checkNodesIndent(node.cases, caseIndent); @@ -790,7 +880,7 @@ module.exports = { if (isSingleLineNode(node)) { return; } - var caseIndent = expectedCaseIndent(node); + let caseIndent = expectedCaseIndent(node); checkNodesIndent(node.consequent, caseIndent + indentSize); } diff --git a/tools/eslint/lib/rules/init-declarations.js b/tools/eslint/lib/rules/init-declarations.js index 66b0a0aea4..e51596f7af 100644 --- a/tools/eslint/lib/rules/init-declarations.js +++ b/tools/eslint/lib/rules/init-declarations.js @@ -26,8 +26,8 @@ function isForLoop(block) { * @returns {boolean} `true` when the node has its initializer. */ function isInitialized(node) { - var declaration = node.parent; - var block = declaration.parent; + let declaration = node.parent; + let block = declaration.parent; if (isForLoop(block)) { if (block.type === "ForStatement") { @@ -87,11 +87,11 @@ module.exports = { create: function(context) { - var MODE_ALWAYS = "always", + let MODE_ALWAYS = "always", MODE_NEVER = "never"; - var mode = context.options[0] || MODE_ALWAYS; - var params = context.options[1] || {}; + let mode = context.options[0] || MODE_ALWAYS; + let params = context.options[1] || {}; //-------------------------------------------------------------------------- // Public API @@ -100,11 +100,11 @@ module.exports = { return { "VariableDeclaration:exit": function(node) { - var kind = node.kind, + let kind = node.kind, declarations = node.declarations; - for (var i = 0; i < declarations.length; ++i) { - var declaration = declarations[i], + for (let i = 0; i < declarations.length; ++i) { + let declaration = declarations[i], id = declaration.id, initialized = isInitialized(declaration), isIgnoredForLoop = params.ignoreForLoopInit && isForLoop(node.parent); diff --git a/tools/eslint/lib/rules/jsx-quotes.js b/tools/eslint/lib/rules/jsx-quotes.js index 6b3a2efef7..c3d87623cd 100644 --- a/tools/eslint/lib/rules/jsx-quotes.js +++ b/tools/eslint/lib/rules/jsx-quotes.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ -var QUOTE_SETTINGS = { +let QUOTE_SETTINGS = { "prefer-double": { quote: "\"", description: "singlequote", @@ -54,7 +54,7 @@ module.exports = { }, create: function(context) { - var quoteOption = context.options[0] || "prefer-double", + let quoteOption = context.options[0] || "prefer-double", setting = QUOTE_SETTINGS[quoteOption]; /** @@ -69,7 +69,7 @@ module.exports = { return { JSXAttribute: function(node) { - var attributeValue = node.value; + let attributeValue = node.value; if (attributeValue && astUtils.isStringLiteral(attributeValue) && !usesExpectedQuotes(attributeValue)) { context.report({ diff --git a/tools/eslint/lib/rules/key-spacing.js b/tools/eslint/lib/rules/key-spacing.js index 1cf677865d..25aba47ba0 100644 --- a/tools/eslint/lib/rules/key-spacing.js +++ b/tools/eslint/lib/rules/key-spacing.js @@ -34,7 +34,7 @@ function last(arr) { * @returns {boolean} True if the candidate property is part of the group. */ function continuesPropertyGroup(lastMember, candidate) { - var groupEndLine = lastMember.loc.start.line, + let groupEndLine = lastMember.loc.start.line, candidateStartLine = candidate.loc.start.line, comments, i; @@ -71,19 +71,15 @@ function isSingleLine(node) { return (node.loc.end.line === node.loc.start.line); } -/** Sets option values from the configured options with defaults +/** + * Initializes a single option property from the configuration with defaults for undefined values * @param {Object} toOptions Object to be initialized * @param {Object} fromOptions Object to be initialized from * @returns {Object} The object with correctly initialized options and values */ -function initOptions(toOptions, fromOptions) { +function initOptionProperty(toOptions, fromOptions) { toOptions.mode = fromOptions.mode || "strict"; - // Set align if exists - multiLine case - if (typeof fromOptions.align !== "undefined") { - toOptions.align = fromOptions.align; - } - // Set value of beforeColon if (typeof fromOptions.beforeColon !== "undefined") { toOptions.beforeColon = +fromOptions.beforeColon; @@ -98,6 +94,55 @@ function initOptions(toOptions, fromOptions) { toOptions.afterColon = 1; } + // Set align if exists + if (typeof fromOptions.align !== "undefined") { + if (typeof fromOptions.align === "object") { + toOptions.align = fromOptions.align; + } else { // "string" + toOptions.align = { + on: fromOptions.align, + mode: toOptions.mode, + beforeColon: toOptions.beforeColon, + afterColon: toOptions.afterColon + }; + } + } + + return toOptions; +} + +/** + * Initializes all the option values (singleLine, multiLine and align) from the configuration with defaults for undefined values + * @param {Object} toOptions Object to be initialized + * @param {Object} fromOptions Object to be initialized from + * @returns {Object} The object with correctly initialized options and values + */ +function initOptions(toOptions, fromOptions) { + if (typeof fromOptions.align === "object") { + + // Initialize the alignment configuration + toOptions.align = initOptionProperty({}, fromOptions.align); + toOptions.align.on = fromOptions.align.on || "colon"; + toOptions.align.mode = fromOptions.align.mode || "strict"; + + toOptions.multiLine = initOptionProperty({}, (fromOptions.multiLine || fromOptions)); + toOptions.singleLine = initOptionProperty({}, (fromOptions.singleLine || fromOptions)); + + } else { // string or undefined + toOptions.multiLine = initOptionProperty({}, (fromOptions.multiLine || fromOptions)); + toOptions.singleLine = initOptionProperty({}, (fromOptions.singleLine || fromOptions)); + + // If alignment options are defined in multiLine, pull them out into the general align configuration + if (toOptions.multiLine.align) { + toOptions.align = { + on: toOptions.multiLine.align.on, + mode: toOptions.multiLine.mode, + beforeColon: toOptions.multiLine.align.beforeColon, + afterColon: toOptions.multiLine.align.afterColon + }; + } + } + return toOptions; } @@ -105,7 +150,7 @@ function initOptions(toOptions, fromOptions) { // Rule Definition //------------------------------------------------------------------------------ -var messages = { +let messages = { key: "{{error}} space after {{computed}}key '{{key}}'.", value: "{{error}} space before value for {{computed}}key '{{key}}'." }; @@ -126,7 +171,29 @@ module.exports = { type: "object", properties: { align: { - enum: ["colon", "value"] + anyOf: [ + { + enum: ["colon", "value"] + }, + { + type: "object", + properties: { + mode: { + enum: ["strict", "minimum"] + }, + on: { + enum: ["colon", "value"] + }, + beforeColon: { + type: "boolean" + }, + afterColon: { + type: "boolean" + } + }, + additionalProperties: false + } + ] }, mode: { enum: ["strict", "minimum"] @@ -162,7 +229,29 @@ module.exports = { type: "object", properties: { align: { - enum: ["colon", "value"] + anyOf: [ + { + enum: ["colon", "value"] + }, + { + type: "object", + properties: { + mode: { + enum: ["strict", "minimum"] + }, + on: { + enum: ["colon", "value"] + }, + beforeColon: { + type: "boolean" + }, + afterColon: { + type: "boolean" + } + }, + additionalProperties: false + } + ] }, mode: { enum: ["strict", "minimum"] @@ -178,6 +267,57 @@ module.exports = { } }, additionalProperties: false + }, + { + type: "object", + properties: { + singleLine: { + type: "object", + properties: { + mode: { + enum: ["strict", "minimum"] + }, + beforeColon: { + type: "boolean" + }, + afterColon: { + type: "boolean" + } + }, + additionalProperties: false + }, + multiLine: { + type: "object", + properties: { + beforeColon: { + type: "boolean" + }, + afterColon: { + type: "boolean" + } + }, + additionalProperties: false + }, + align: { + type: "object", + properties: { + mode: { + enum: ["strict", "minimum"] + }, + on: { + enum: ["colon", "value"] + }, + beforeColon: { + type: "boolean" + }, + afterColon: { + type: "boolean" + } + }, + additionalProperties: false + } + }, + additionalProperties: false } ] }] @@ -193,17 +333,18 @@ module.exports = { * align: "colon" // Optional, or "value" * } */ + let options = context.options[0] || {}, + ruleOptions = initOptions({}, options), + multiLineOptions = ruleOptions.multiLine, + singleLineOptions = ruleOptions.singleLine, + alignmentOptions = ruleOptions.align || null; - var options = context.options[0] || {}, - multiLineOptions = initOptions({}, (options.multiLine || options)), - singleLineOptions = initOptions({}, (options.singleLine || options)); - - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Determines if the given property is key-value property. * @param {ASTNode} property Property node to check. - * @returns {Boolean} Whether the property is a key-value property. + * @returns {boolean} Whether the property is a key-value property. */ function isKeyValueProperty(property) { return !( @@ -220,7 +361,7 @@ module.exports = { * @returns {ASTNode} The last token before a colon punctuator. */ function getLastTokenBeforeColon(node) { - var prevNode; + let prevNode; while (node && (node.type !== "Punctuator" || node.value !== ":")) { prevNode = node; @@ -251,7 +392,7 @@ module.exports = { * @returns {string} The property's key. */ function getKey(property) { - var key = property.key; + let key = property.key; if (property.computed) { return sourceCode.getText().slice(key.range[0], key.range[1]); @@ -271,7 +412,7 @@ module.exports = { * @returns {void} */ function report(property, side, whitespace, expected, mode) { - var diff = whitespace.length - expected, + let diff = whitespace.length - expected, nextColon = getNextColon(property.key), tokenBeforeColon = sourceCode.getTokenBefore(nextColon), tokenAfterColon = sourceCode.getTokenAfter(nextColon), @@ -335,7 +476,7 @@ module.exports = { * @returns {int} Width of the key. */ function getKeyWidth(property) { - var startToken, endToken; + let startToken, endToken; startToken = sourceCode.getFirstToken(property); endToken = getLastTokenBeforeColon(property.key); @@ -349,7 +490,7 @@ module.exports = { * @returns {Object} Whitespace before and after the property's colon. */ function getPropertyWhitespace(property) { - var whitespace = /(\s*):(\s*)/.exec(sourceCode.getText().slice( + let whitespace = /(\s*):(\s*)/.exec(sourceCode.getText().slice( property.key.range[1], property.value.range[0] )); @@ -373,7 +514,7 @@ module.exports = { } return node.properties.reduce(function(groups, property) { - var currentGroup = last(groups), + let currentGroup = last(groups), prev = last(currentGroup); if (!prev || continuesPropertyGroup(prev, property)) { @@ -394,14 +535,22 @@ module.exports = { * @returns {void} */ function verifyGroupAlignment(properties) { - var length = properties.length, + let length = properties.length, widths = properties.map(getKeyWidth), // Width of keys, including quotes targetWidth = Math.max.apply(null, widths), + align = alignmentOptions.on, // "value" or "colon" i, property, whitespace, width, - align = multiLineOptions.align, - beforeColon = multiLineOptions.beforeColon, - afterColon = multiLineOptions.afterColon, - mode = multiLineOptions.mode; + beforeColon, afterColon, mode; + + if (alignmentOptions && length > 1) { // When aligning values within a group, use the alignment configuration. + beforeColon = alignmentOptions.beforeColon; + afterColon = alignmentOptions.afterColon; + mode = alignmentOptions.mode; + } else { + beforeColon = multiLineOptions.beforeColon; + afterColon = multiLineOptions.afterColon; + mode = alignmentOptions.mode; + } // Conditionally include one space before or after colon targetWidth += (align === "colon" ? beforeColon : afterColon); @@ -441,7 +590,7 @@ module.exports = { * @returns {void} */ function verifySpacing(node, lineOptions) { - var actual = getPropertyWhitespace(node); + let actual = getPropertyWhitespace(node); if (actual) { // Object literal getters/setters lack colons report(node, "key", actual.beforeColon, lineOptions.beforeColon, lineOptions.mode); @@ -455,9 +604,9 @@ module.exports = { * @returns {void} */ function verifyListSpacing(properties) { - var length = properties.length; + let length = properties.length; - for (var i = 0; i < length; i++) { + for (let i = 0; i < length; i++) { verifySpacing(properties[i], singleLineOptions); } } @@ -466,7 +615,7 @@ module.exports = { // Public API //-------------------------------------------------------------------------- - if (multiLineOptions.align) { // Verify vertical alignment + if (alignmentOptions) { // Verify vertical alignment return { ObjectExpression: function(node) { diff --git a/tools/eslint/lib/rules/keyword-spacing.js b/tools/eslint/lib/rules/keyword-spacing.js index f771029a58..3c8d171ce8 100644 --- a/tools/eslint/lib/rules/keyword-spacing.js +++ b/tools/eslint/lib/rules/keyword-spacing.js @@ -9,26 +9,26 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"), +let astUtils = require("../ast-utils"), keywords = require("../util/keywords"); //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ -var PREV_TOKEN = /^[\)\]\}>]$/; -var NEXT_TOKEN = /^(?:[\(\[\{<~!]|\+\+?|--?)$/; -var PREV_TOKEN_M = /^[\)\]\}>*]$/; -var NEXT_TOKEN_M = /^[\{*]$/; -var TEMPLATE_OPEN_PAREN = /\$\{$/; -var TEMPLATE_CLOSE_PAREN = /^\}/; -var CHECK_TYPE = /^(?:JSXElement|RegularExpression|String|Template)$/; -var KEYS = keywords.concat(["as", "await", "from", "get", "let", "of", "set", "yield"]); +let PREV_TOKEN = /^[\)\]\}>]$/; +let NEXT_TOKEN = /^(?:[\(\[\{<~!]|\+\+?|--?)$/; +let PREV_TOKEN_M = /^[\)\]\}>*]$/; +let NEXT_TOKEN_M = /^[\{*]$/; +let TEMPLATE_OPEN_PAREN = /\$\{$/; +let TEMPLATE_CLOSE_PAREN = /^\}/; +let CHECK_TYPE = /^(?:JSXElement|RegularExpression|String|Template)$/; +let KEYS = keywords.concat(["as", "await", "from", "get", "let", "of", "set", "yield"]); // check duplications. (function() { KEYS.sort(); - for (var i = 1; i < KEYS.length; ++i) { + for (let i = 1; i < KEYS.length; ++i) { if (KEYS[i] === KEYS[i - 1]) { throw new Error("Duplication was found in the keyword list: " + KEYS[i]); } @@ -101,7 +101,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Reports a given token if there are not space(s) before the token. @@ -114,7 +114,7 @@ module.exports = { function expectSpaceBefore(token, pattern) { pattern = pattern || PREV_TOKEN; - var prevToken = sourceCode.getTokenBefore(token); + let prevToken = sourceCode.getTokenBefore(token); if (prevToken && (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && @@ -144,7 +144,7 @@ module.exports = { function unexpectSpaceBefore(token, pattern) { pattern = pattern || PREV_TOKEN; - var prevToken = sourceCode.getTokenBefore(token); + let prevToken = sourceCode.getTokenBefore(token); if (prevToken && (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && @@ -174,7 +174,7 @@ module.exports = { function expectSpaceAfter(token, pattern) { pattern = pattern || NEXT_TOKEN; - var nextToken = sourceCode.getTokenAfter(token); + let nextToken = sourceCode.getTokenAfter(token); if (nextToken && (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && @@ -204,7 +204,7 @@ module.exports = { function unexpectSpaceAfter(token, pattern) { pattern = pattern || NEXT_TOKEN; - var nextToken = sourceCode.getTokenAfter(token); + let nextToken = sourceCode.getTokenAfter(token); if (nextToken && (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && @@ -226,28 +226,28 @@ module.exports = { /** * Parses the option object and determines check methods for each keyword. * - * @param {object|undefined} options - The option object to parse. - * @returns {object} - Normalized option object. + * @param {Object|undefined} options - The option object to parse. + * @returns {Object} - Normalized option object. * Keys are keywords (there are for every keyword). * Values are instances of `{"before": function, "after": function}`. */ function parseOptions(options) { - var before = !options || options.before !== false; - var after = !options || options.after !== false; - var defaultValue = { + let before = !options || options.before !== false; + let after = !options || options.after !== false; + let defaultValue = { before: before ? expectSpaceBefore : unexpectSpaceBefore, after: after ? expectSpaceAfter : unexpectSpaceAfter }; - var overrides = (options && options.overrides) || {}; - var retv = Object.create(null); + let overrides = (options && options.overrides) || {}; + let retv = Object.create(null); - for (var i = 0; i < KEYS.length; ++i) { - var key = KEYS[i]; - var override = overrides[key]; + for (let i = 0; i < KEYS.length; ++i) { + let key = KEYS[i]; + let override = overrides[key]; if (override) { - var thisBefore = ("before" in override) ? override.before : before; - var thisAfter = ("after" in override) ? override.after : after; + let thisBefore = ("before" in override) ? override.before : before; + let thisAfter = ("after" in override) ? override.after : after; retv[key] = { before: thisBefore ? expectSpaceBefore : unexpectSpaceBefore, @@ -261,7 +261,7 @@ module.exports = { return retv; } - var checkMethodMap = parseOptions(context.options[0]); + let checkMethodMap = parseOptions(context.options[0]); /** * Reports a given token if usage of spacing followed by the token is @@ -308,7 +308,7 @@ module.exports = { * @returns {void} */ function checkSpacingAroundFirstToken(node) { - var firstToken = node && sourceCode.getFirstToken(node); + let firstToken = node && sourceCode.getFirstToken(node); if (firstToken && firstToken.type === "Keyword") { checkSpacingAround(firstToken); @@ -326,7 +326,7 @@ module.exports = { * @returns {void} */ function checkSpacingBeforeFirstToken(node) { - var firstToken = node && sourceCode.getFirstToken(node); + let firstToken = node && sourceCode.getFirstToken(node); if (firstToken && firstToken.type === "Keyword") { checkSpacingBefore(firstToken); @@ -342,7 +342,7 @@ module.exports = { */ function checkSpacingAroundTokenBefore(node) { if (node) { - var token = sourceCode.getTokenBefore(node); + let token = sourceCode.getTokenBefore(node); while (token.type !== "Keyword") { token = sourceCode.getTokenBefore(token); @@ -424,7 +424,7 @@ module.exports = { checkSpacingAroundFirstToken(node); // `of` is not a keyword token. - var token = sourceCode.getTokenBefore(node.right); + let token = sourceCode.getTokenBefore(node.right); while (token.value !== "of") { token = sourceCode.getTokenBefore(token); @@ -445,13 +445,13 @@ module.exports = { * @returns {void} */ function checkSpacingForModuleDeclaration(node) { - var firstToken = sourceCode.getFirstToken(node); + let firstToken = sourceCode.getFirstToken(node); checkSpacingBefore(firstToken, PREV_TOKEN_M); checkSpacingAfter(firstToken, NEXT_TOKEN_M); if (node.source) { - var fromToken = sourceCode.getTokenBefore(node.source); + let fromToken = sourceCode.getTokenBefore(node.source); checkSpacingBefore(fromToken, PREV_TOKEN_M); checkSpacingAfter(fromToken, NEXT_TOKEN_M); @@ -466,7 +466,7 @@ module.exports = { * @returns {void} */ function checkSpacingForImportNamespaceSpecifier(node) { - var asToken = sourceCode.getFirstToken(node, 1); + let asToken = sourceCode.getFirstToken(node, 1); checkSpacingBefore(asToken, PREV_TOKEN_M); } @@ -483,7 +483,7 @@ module.exports = { checkSpacingAroundFirstToken(node); } if (node.kind === "get" || node.kind === "set") { - var token = sourceCode.getFirstToken( + let token = sourceCode.getFirstToken( node, node.static ? 1 : 0 ); diff --git a/tools/eslint/lib/rules/linebreak-style.js b/tools/eslint/lib/rules/linebreak-style.js index 5e6b819f3f..a8a5e4ed88 100644 --- a/tools/eslint/lib/rules/linebreak-style.js +++ b/tools/eslint/lib/rules/linebreak-style.js @@ -28,10 +28,10 @@ module.exports = { create: function(context) { - var EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.", + let EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.", EXPECTED_CRLF_MSG = "Expected linebreaks to be 'CRLF' but found 'LF'."; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -41,7 +41,7 @@ module.exports = { * Builds a fix function that replaces text at the specified range in the source text. * @param {int[]} range The range to replace * @param {string} text The text to insert. - * @returns {function} Fixer function + * @returns {Function} Fixer function * @private */ function createFix(range, text) { @@ -56,7 +56,7 @@ module.exports = { return { Program: function checkForlinebreakStyle(node) { - var linebreakStyle = context.options[0] || "unix", + let linebreakStyle = context.options[0] || "unix", expectedLF = linebreakStyle === "unix", expectedLFChars = expectedLF ? "\n" : "\r\n", source = sourceCode.getText(), @@ -65,7 +65,7 @@ module.exports = { index, range; - var i = 0; + let i = 0; while ((match = pattern.exec(source)) !== null) { i++; diff --git a/tools/eslint/lib/rules/lines-around-comment.js b/tools/eslint/lib/rules/lines-around-comment.js index a227fe4184..70775b4213 100644 --- a/tools/eslint/lib/rules/lines-around-comment.js +++ b/tools/eslint/lib/rules/lines-around-comment.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -var lodash = require("lodash"), +let lodash = require("lodash"), astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ @@ -21,7 +21,7 @@ var lodash = require("lodash"), * @returns {Array} An array of line numbers. */ function getEmptyLineNums(lines) { - var emptyLines = lines.map(function(line, i) { + let emptyLines = lines.map(function(line, i) { return { code: line.trim(), num: i + 1 @@ -41,11 +41,11 @@ function getEmptyLineNums(lines) { * @returns {Array} An array of line numbers. */ function getCommentLineNums(comments) { - var lines = []; + let lines = []; comments.forEach(function(token) { - var start = token.loc.start.line; - var end = token.loc.end.line; + let start = token.loc.start.line; + let end = token.loc.end.line; lines.push(start, end); }); @@ -108,7 +108,7 @@ module.exports = { create: function(context) { - var options = context.options[0] ? lodash.assign({}, context.options[0]) : {}; + let options = context.options[0] ? lodash.assign({}, context.options[0]) : {}; options.beforeLineComment = options.beforeLineComment || false; options.afterLineComment = options.afterLineComment || false; @@ -117,9 +117,9 @@ module.exports = { options.allowBlockStart = options.allowBlockStart || false; options.allowBlockEnd = options.allowBlockEnd || false; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); - var lines = sourceCode.lines, + let lines = sourceCode.lines, numLines = lines.length + 1, comments = sourceCode.getAllComments(), commentLines = getCommentLineNums(comments), @@ -141,7 +141,7 @@ module.exports = { * @returns {boolean} True if the comment is not alone. */ function codeAroundComment(node) { - var token; + let token; token = node; do { @@ -184,8 +184,8 @@ module.exports = { * @returns {boolean} True if the comment is at parent start. */ function isCommentAtParentStart(node, nodeType) { - var ancestors = context.getAncestors(); - var parent; + let ancestors = context.getAncestors(); + let parent; if (ancestors.length) { parent = ancestors.pop(); @@ -202,8 +202,8 @@ module.exports = { * @returns {boolean} True if the comment is at parent end. */ function isCommentAtParentEnd(node, nodeType) { - var ancestors = context.getAncestors(); - var parent; + let ancestors = context.getAncestors(); + let parent; if (ancestors.length) { parent = ancestors.pop(); @@ -271,27 +271,27 @@ module.exports = { * Checks if a comment node has lines around it (ignores inline comments) * @param {ASTNode} node The Comment node. * @param {Object} opts Options to determine the newline. - * @param {Boolean} opts.after Should have a newline after this line. - * @param {Boolean} opts.before Should have a newline before this line. + * @param {boolean} opts.after Should have a newline after this line. + * @param {boolean} opts.before Should have a newline before this line. * @returns {void} */ function checkForEmptyLine(node, opts) { - var after = opts.after, + let after = opts.after, before = opts.before; - var prevLineNum = node.loc.start.line - 1, + let prevLineNum = node.loc.start.line - 1, nextLineNum = node.loc.end.line + 1, commentIsNotAlone = codeAroundComment(node); - var blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(node), + let blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(node), blockEndAllowed = options.allowBlockEnd && isCommentAtBlockEnd(node), objectStartAllowed = options.allowObjectStart && isCommentAtObjectStart(node), objectEndAllowed = options.allowObjectEnd && isCommentAtObjectEnd(node), arrayStartAllowed = options.allowArrayStart && isCommentAtArrayStart(node), arrayEndAllowed = options.allowArrayEnd && isCommentAtArrayEnd(node); - var exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed; - var exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed; + let exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed; + let exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed; // ignore top of the file and bottom of the file if (prevLineNum < 1) { @@ -306,14 +306,14 @@ module.exports = { return; } - var previousTokenOrComment = sourceCode.getTokenOrCommentBefore(node); - var nextTokenOrComment = sourceCode.getTokenOrCommentAfter(node); + let previousTokenOrComment = sourceCode.getTokenOrCommentBefore(node); + let nextTokenOrComment = sourceCode.getTokenOrCommentAfter(node); // check for newline before if (!exceptionStartAllowed && before && !lodash.includes(commentAndEmptyLines, prevLineNum) && !(isCommentNodeType(previousTokenOrComment) && astUtils.isTokenOnSameLine(previousTokenOrComment, node))) { - var lineStart = node.range[0] - node.loc.start.column; - var range = [lineStart, lineStart]; + let lineStart = node.range[0] - node.loc.start.column; + let range = [lineStart, lineStart]; context.report({ node: node, diff --git a/tools/eslint/lib/rules/max-depth.js b/tools/eslint/lib/rules/max-depth.js index 317f06c68f..dbc1f6d48c 100644 --- a/tools/eslint/lib/rules/max-depth.js +++ b/tools/eslint/lib/rules/max-depth.js @@ -49,7 +49,7 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - var functionStack = [], + let functionStack = [], option = context.options[0], maxDepth = 4; @@ -88,7 +88,7 @@ module.exports = { * @private */ function pushBlock(node) { - var len = ++functionStack[functionStack.length - 1]; + let len = ++functionStack[functionStack.length - 1]; if (len > maxDepth) { context.report(node, "Blocks are nested too deeply ({{depth}}).", diff --git a/tools/eslint/lib/rules/max-len.js b/tools/eslint/lib/rules/max-len.js index b5813bbfaa..1bb63990d8 100644 --- a/tools/eslint/lib/rules/max-len.js +++ b/tools/eslint/lib/rules/max-len.js @@ -9,7 +9,7 @@ // Constants //------------------------------------------------------------------------------ -var OPTIONS_SCHEMA = { +let OPTIONS_SCHEMA = { type: "object", properties: { code: { @@ -40,7 +40,7 @@ var OPTIONS_SCHEMA = { additionalProperties: false }; -var OPTIONS_OR_INTEGER_SCHEMA = { +let OPTIONS_OR_INTEGER_SCHEMA = { anyOf: [ OPTIONS_SCHEMA, { @@ -79,9 +79,9 @@ module.exports = { * too many false positives * - We don't care about matching the entire URL, any small segment is fine */ - var URL_REGEXP = /[^:/?#]:\/\/[^?#]/; + let URL_REGEXP = /[^:/?#]:\/\/[^?#]/; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Computes the length of a line that may contain tabs. The width of each @@ -92,10 +92,10 @@ module.exports = { * @private */ function computeLineLength(line, tabWidth) { - var extraCharacterCount = 0; + let extraCharacterCount = 0; line.replace(/\t/g, function(match, offset) { - var totalOffset = offset + extraCharacterCount, + let totalOffset = offset + extraCharacterCount, previousTabStopOffset = tabWidth ? totalOffset % tabWidth : 0, spaceCount = tabWidth - previousTabStopOffset; @@ -105,8 +105,8 @@ module.exports = { } // The options object must be the last option specified… - var lastOption = context.options[context.options.length - 1]; - var options = typeof lastOption === "object" ? Object.create(lastOption) : {}; + let lastOption = context.options[context.options.length - 1]; + let options = typeof lastOption === "object" ? Object.create(lastOption) : {}; // …but max code length… if (typeof context.options[0] === "number") { @@ -118,7 +118,7 @@ module.exports = { options.tabWidth = context.options[1]; } - var maxLength = options.code || 80, + let maxLength = options.code || 80, tabWidth = options.tabWidth || 4, ignorePattern = options.ignorePattern || null, ignoreComments = options.ignoreComments || false, @@ -156,7 +156,7 @@ module.exports = { * @returns {boolean} If the comment covers the entire line */ function isFullLineComment(line, lineNumber, comment) { - var start = comment.loc.start, + let start = comment.loc.start, end = comment.loc.end, isFirstTokenOnLine = !line.slice(0, comment.loc.start.column).trim(); @@ -188,7 +188,7 @@ module.exports = { function checkProgramForMaxLength(node) { // split (honors line-ending) - var lines = sourceCode.lines, + let lines = sourceCode.lines, // list of comments to ignore comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? sourceCode.getAllComments() : [], @@ -199,23 +199,24 @@ module.exports = { lines.forEach(function(line, i) { // i is zero-indexed, line numbers are one-indexed - var lineNumber = i + 1; + let lineNumber = i + 1; /* * if we're checking comment length; we need to know whether this * line is a comment */ - var lineIsComment = false; + let lineIsComment = false; /* * We can short-circuit the comment checks if we're already out of * comments to check. */ if (commentsIndex < comments.length) { + let comment = null; // iterate over comments until we find one past the current line do { - var comment = comments[++commentsIndex]; + comment = comments[++commentsIndex]; } while (comment && comment.loc.start.line <= lineNumber); // and step back by one @@ -234,7 +235,7 @@ module.exports = { return; } - var lineLength = computeLineLength(line, tabWidth); + let lineLength = computeLineLength(line, tabWidth); if (lineIsComment && ignoreComments) { return; diff --git a/tools/eslint/lib/rules/max-lines.js b/tools/eslint/lib/rules/max-lines.js index 751310e81d..1e311eaffb 100644 --- a/tools/eslint/lib/rules/max-lines.js +++ b/tools/eslint/lib/rules/max-lines.js @@ -8,8 +8,8 @@ // Requirements //------------------------------------------------------------------------------ -var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +let lodash = require("lodash"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -52,7 +52,7 @@ module.exports = { }, create: function(context) { - var option = context.options[0], + let option = context.options[0], max = 300; if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { @@ -63,10 +63,10 @@ module.exports = { max = option; } - var skipComments = option && option.skipComments; - var skipBlankLines = option && option.skipBlankLines; + let skipComments = option && option.skipComments; + let skipBlankLines = option && option.skipBlankLines; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Returns whether or not a token is a comment node type @@ -83,10 +83,10 @@ module.exports = { * @returns {int[]} The line numbers */ function getLinesWithoutCode(comment) { - var start = comment.loc.start.line; - var end = comment.loc.end.line; + let start = comment.loc.start.line; + let end = comment.loc.end.line; - var token; + let token; token = comment; do { @@ -114,7 +114,7 @@ module.exports = { return { "Program:exit": function() { - var lines = sourceCode.lines.map(function(text, i) { + let lines = sourceCode.lines.map(function(text, i) { return { lineNumber: i + 1, text: text }; }); @@ -125,9 +125,9 @@ module.exports = { } if (skipComments) { - var comments = sourceCode.getAllComments(); + let comments = sourceCode.getAllComments(); - var commentLines = lodash.flatten(comments.map(function(comment) { + let commentLines = lodash.flatten(comments.map(function(comment) { return getLinesWithoutCode(comment); })); @@ -139,7 +139,7 @@ module.exports = { if (lines.length > max) { context.report({ loc: { line: 1, column: 0 }, - message: "File must be at most " + max + " lines long" + message: "File must be at most " + max + " lines long." }); } } diff --git a/tools/eslint/lib/rules/max-nested-callbacks.js b/tools/eslint/lib/rules/max-nested-callbacks.js index 06554127c6..a1145c1f1a 100644 --- a/tools/eslint/lib/rules/max-nested-callbacks.js +++ b/tools/eslint/lib/rules/max-nested-callbacks.js @@ -48,7 +48,7 @@ module.exports = { //-------------------------------------------------------------------------- // Constants //-------------------------------------------------------------------------- - var option = context.options[0], + let option = context.options[0], THRESHOLD = 10; if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { @@ -65,7 +65,7 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - var callbackStack = []; + let callbackStack = []; /** * Checks a given function node for too many callbacks. @@ -74,14 +74,14 @@ module.exports = { * @private */ function checkFunction(node) { - var parent = node.parent; + let parent = node.parent; if (parent.type === "CallExpression") { callbackStack.push(node); } if (callbackStack.length > THRESHOLD) { - var opts = {num: callbackStack.length, max: THRESHOLD}; + let opts = {num: callbackStack.length, max: THRESHOLD}; context.report(node, "Too many nested callbacks ({{num}}). Maximum allowed is {{max}}.", opts); } diff --git a/tools/eslint/lib/rules/max-params.js b/tools/eslint/lib/rules/max-params.js index 5d9d64fac1..9fb922392b 100644 --- a/tools/eslint/lib/rules/max-params.js +++ b/tools/eslint/lib/rules/max-params.js @@ -45,7 +45,7 @@ module.exports = { create: function(context) { - var option = context.options[0], + let option = context.options[0], numParams = 3; if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { diff --git a/tools/eslint/lib/rules/max-statements-per-line.js b/tools/eslint/lib/rules/max-statements-per-line.js index 55f09746c3..165c6dd137 100644 --- a/tools/eslint/lib/rules/max-statements-per-line.js +++ b/tools/eslint/lib/rules/max-statements-per-line.js @@ -32,7 +32,7 @@ module.exports = { create: function(context) { - var sourceCode = context.getSourceCode(), + let sourceCode = context.getSourceCode(), options = context.options[0] || {}, lastStatementLine = 0, numberOfStatementsOnThisLine = 0, @@ -43,7 +43,7 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - var SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/; + let SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/; /** * Gets the actual last token of a given node. @@ -52,7 +52,7 @@ module.exports = { * @returns {Token} The actual last token. */ function getActualLastToken(node) { - var lastToken = sourceCode.getLastToken(node); + let lastToken = sourceCode.getLastToken(node); if (lastToken.value === ";") { lastToken = sourceCode.getTokenBefore(lastToken); @@ -68,7 +68,7 @@ module.exports = { * @returns {void} */ function enterStatement(node) { - var line = node.loc.start.line; + let line = node.loc.start.line; // Skip to allow non-block statements if this is direct child of control statements. // `if (a) foo();` is counted as 1. @@ -100,7 +100,7 @@ module.exports = { * @returns {void} */ function leaveStatement(node) { - var line = getActualLastToken(node).loc.end.line; + let line = getActualLastToken(node).loc.end.line; // Update state. if (line !== lastStatementLine) { diff --git a/tools/eslint/lib/rules/max-statements.js b/tools/eslint/lib/rules/max-statements.js index 72904c64ba..6708be3a12 100644 --- a/tools/eslint/lib/rules/max-statements.js +++ b/tools/eslint/lib/rules/max-statements.js @@ -58,7 +58,7 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - var functionStack = [], + let functionStack = [], option = context.options[0], maxStatements = 10, ignoreTopLevelFunctions = context.options[1] && context.options[1].ignoreTopLevelFunctions || false, @@ -107,7 +107,7 @@ module.exports = { * @private */ function endFunction(node) { - var count = functionStack.pop(); + let count = functionStack.pop(); if (ignoreTopLevelFunctions && functionStack.length === 0) { topLevelFunctions.push({ node: node, count: count}); @@ -147,8 +147,8 @@ module.exports = { } topLevelFunctions.forEach(function(element) { - var count = element.count; - var node = element.node; + let count = element.count; + let node = element.node; reportIfTooManyStatements(node, count, maxStatements); }); diff --git a/tools/eslint/lib/rules/multiline-ternary.js b/tools/eslint/lib/rules/multiline-ternary.js new file mode 100644 index 0000000000..469eb134de --- /dev/null +++ b/tools/eslint/lib/rules/multiline-ternary.js @@ -0,0 +1,66 @@ +/** + * @fileoverview Enforce newlines between operands of ternary expressions + * @author Kai Cataldo + */ + +"use strict"; + +let astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "enforce newlines between operands of ternary expressions", + category: "Stylistic Issues", + recommended: false + }, + schema: [] + }, + + create: function(context) { + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Tests whether node is preceded by supplied tokens + * @param {ASTNode} node - node to check + * @param {ASTNode} parentNode - parent of node to report + * @returns {void} + * @private + */ + function reportError(node, parentNode) { + context.report({ + node: node, + message: "Expected newline between {{typeOfError}} of ternary expression.", + data: { + typeOfError: node === parentNode.test ? "test and consequent" : "consequent and alternate" + } + }); + } + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + ConditionalExpression: function(node) { + let areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(node.test, node.consequent); + let areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(node.consequent, node.alternate); + + if (areTestAndConsequentOnSameLine) { + reportError(node.test, node); + } + + if (areConsequentAndAlternateOnSameLine) { + reportError(node.consequent, node); + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/new-cap.js b/tools/eslint/lib/rules/new-cap.js index 2dabb30a65..5e1baa540c 100644 --- a/tools/eslint/lib/rules/new-cap.js +++ b/tools/eslint/lib/rules/new-cap.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -var lodash = require("lodash"); +let lodash = require("lodash"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var CAPS_ALLOWED = [ +let CAPS_ALLOWED = [ "Array", "Boolean", "Date", @@ -61,7 +61,7 @@ function invert(map, key) { * @returns {Object} Object with cap is new exceptions. */ function calculateCapIsNewExceptions(config) { - var capIsNewExceptions = checkArray(config, "capIsNewExceptions", CAPS_ALLOWED); + let capIsNewExceptions = checkArray(config, "capIsNewExceptions", CAPS_ALLOWED); if (capIsNewExceptions !== CAPS_ALLOWED) { capIsNewExceptions = capIsNewExceptions.concat(CAPS_ALLOWED); @@ -115,19 +115,19 @@ module.exports = { create: function(context) { - var config = context.options[0] ? lodash.assign({}, context.options[0]) : {}; + let config = context.options[0] ? lodash.assign({}, context.options[0]) : {}; config.newIsCap = config.newIsCap !== false; config.capIsNew = config.capIsNew !== false; - var skipProperties = config.properties === false; + let skipProperties = config.properties === false; - var newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {}); + let newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {}); - var capIsNewExceptions = calculateCapIsNewExceptions(config); + let capIsNewExceptions = calculateCapIsNewExceptions(config); - var listeners = {}; + let listeners = {}; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -140,7 +140,7 @@ module.exports = { */ function extractNameFromExpression(node) { - var name = "", + let name = "", property; if (node.callee.type === "MemberExpression") { @@ -164,10 +164,10 @@ module.exports = { * @returns {string} capitalization state: "non-alpha", "lower", or "upper" */ function getCap(str) { - var firstChar = str.charAt(0); + let firstChar = str.charAt(0); - var firstCharLower = firstChar.toLowerCase(); - var firstCharUpper = firstChar.toUpperCase(); + let firstCharLower = firstChar.toLowerCase(); + let firstCharUpper = firstChar.toUpperCase(); if (firstCharLower === firstCharUpper) { @@ -185,7 +185,7 @@ module.exports = { * @param {Object} allowedMap Object mapping calleeName to a Boolean * @param {ASTNode} node CallExpression node * @param {string} calleeName Capitalized callee name from a CallExpression - * @returns {Boolean} Returns true if the callee may be capitalized + * @returns {boolean} Returns true if the callee may be capitalized */ function isCapAllowed(allowedMap, node, calleeName) { if (allowedMap[calleeName] || allowedMap[sourceCode.getText(node.callee)]) { @@ -209,7 +209,7 @@ module.exports = { * @returns {void} */ function report(node, message) { - var callee = node.callee; + let callee = node.callee; if (callee.type === "MemberExpression") { callee = callee.property; @@ -225,11 +225,11 @@ module.exports = { if (config.newIsCap) { listeners.NewExpression = function(node) { - var constructorName = extractNameFromExpression(node); + let constructorName = extractNameFromExpression(node); if (constructorName) { - var capitalization = getCap(constructorName); - var isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName); + let capitalization = getCap(constructorName); + let isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName); if (!isAllowed) { report(node, "A constructor name should not start with a lowercase letter."); @@ -241,11 +241,11 @@ module.exports = { if (config.capIsNew) { listeners.CallExpression = function(node) { - var calleeName = extractNameFromExpression(node); + let calleeName = extractNameFromExpression(node); if (calleeName) { - var capitalization = getCap(calleeName); - var isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName); + let capitalization = getCap(calleeName); + let isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName); if (!isAllowed) { report(node, "A function with a name starting with an uppercase letter should only be used as a constructor."); diff --git a/tools/eslint/lib/rules/new-parens.js b/tools/eslint/lib/rules/new-parens.js index ec6106647a..7ebd144b7e 100644 --- a/tools/eslint/lib/rules/new-parens.js +++ b/tools/eslint/lib/rules/new-parens.js @@ -21,18 +21,18 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { NewExpression: function(node) { - var tokens = sourceCode.getTokens(node); - var prenticesTokens = tokens.filter(function(token) { + let tokens = sourceCode.getTokens(node); + let prenticesTokens = tokens.filter(function(token) { return token.value === "(" || token.value === ")"; }); if (prenticesTokens.length < 2) { - context.report(node, "Missing '()' invoking a constructor"); + context.report(node, "Missing '()' invoking a constructor."); } } }; diff --git a/tools/eslint/lib/rules/newline-after-var.js b/tools/eslint/lib/rules/newline-after-var.js index 8801407c0b..cb06c6f261 100644 --- a/tools/eslint/lib/rules/newline-after-var.js +++ b/tools/eslint/lib/rules/newline-after-var.js @@ -26,16 +26,16 @@ module.exports = { create: function(context) { - var ALWAYS_MESSAGE = "Expected blank line after variable declarations.", + let ALWAYS_MESSAGE = "Expected blank line after variable declarations.", NEVER_MESSAGE = "Unexpected blank line after variable declarations."; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); // Default `mode` to "always". - var mode = context.options[0] === "never" ? "never" : "always"; + let mode = context.options[0] === "never" ? "never" : "always"; // Cache starting and ending line numbers of comments for faster lookup - var commentEndLine = sourceCode.getAllComments().reduce(function(result, token) { + let commentEndLine = sourceCode.getAllComments().reduce(function(result, token) { result[token.loc.start.line] = token.loc.end.line; return result; }, {}); @@ -83,7 +83,7 @@ module.exports = { * @returns {boolean} True if `node` is last of their parent block. */ function isLastNode(node) { - var token = sourceCode.getTokenAfter(node); + let token = sourceCode.getTokenAfter(node); return !token || (token.type === "Punctuator" && token.value === "}"); } @@ -95,7 +95,7 @@ module.exports = { * @returns {boolean} True if `token` does not start immediately after a comment */ function hasBlankLineAfterComment(token, commentStartLine) { - var commentEnd = commentEndLine[commentStartLine]; + let commentEnd = commentEndLine[commentStartLine]; // If there's another comment, repeat check for blank line if (commentEndLine[commentEnd + 1]) { @@ -114,7 +114,7 @@ module.exports = { * @returns {void} */ function checkForBlankLine(node) { - var lastToken = sourceCode.getLastToken(node), + let lastToken = sourceCode.getLastToken(node), nextToken = sourceCode.getTokenAfter(node), nextLineNum = lastToken.loc.end.line + 1, noNextLineToken, diff --git a/tools/eslint/lib/rules/newline-before-return.js b/tools/eslint/lib/rules/newline-before-return.js index 5c8a139358..966ddb9193 100644 --- a/tools/eslint/lib/rules/newline-before-return.js +++ b/tools/eslint/lib/rules/newline-before-return.js @@ -20,7 +20,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -34,7 +34,7 @@ module.exports = { * @private */ function isPrecededByTokens(node, testTokens) { - var tokenBefore = sourceCode.getTokenBefore(node); + let tokenBefore = sourceCode.getTokenBefore(node); return testTokens.some(function(token) { return tokenBefore.value === token; @@ -48,7 +48,7 @@ module.exports = { * @private */ function isFirstNode(node) { - var parentType = node.parent.type; + let parentType = node.parent.type; if (node.parent.body) { return Array.isArray(node.parent.body) @@ -75,7 +75,7 @@ module.exports = { * @private */ function calcCommentLines(node, lineNumTokenBefore) { - var comments = sourceCode.getComments(node).leading, + let comments = sourceCode.getComments(node).leading, numLinesComments = 0; if (!comments.length) { @@ -109,7 +109,7 @@ module.exports = { * @private */ function hasNewlineBefore(node) { - var tokenBefore = sourceCode.getTokenBefore(node), + let tokenBefore = sourceCode.getTokenBefore(node), lineNumNode = node.loc.start.line, lineNumTokenBefore, commentLines; diff --git a/tools/eslint/lib/rules/newline-per-chained-call.js b/tools/eslint/lib/rules/newline-per-chained-call.js index c412d53e99..068e7b97ae 100644 --- a/tools/eslint/lib/rules/newline-per-chained-call.js +++ b/tools/eslint/lib/rules/newline-per-chained-call.js @@ -33,10 +33,10 @@ module.exports = { create: function(context) { - var options = context.options[0] || {}, + let options = context.options[0] || {}, ignoreChainWithDepth = options.ignoreChainWithDepth || 2; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Gets the property text of a given MemberExpression node. @@ -46,9 +46,9 @@ module.exports = { * @returns {string} The property text of the node. */ function getPropertyText(node) { - var prefix = node.computed ? "[" : "."; - var lines = sourceCode.getText(node.property).split(/\r\n|\r|\n/g); - var suffix = node.computed && lines.length === 1 ? "]" : ""; + let prefix = node.computed ? "[" : "."; + let lines = sourceCode.getText(node.property).split(/\r\n|\r|\n/g); + let suffix = node.computed && lines.length === 1 ? "]" : ""; return prefix + lines[0] + suffix; } @@ -59,9 +59,9 @@ module.exports = { return; } - var callee = node.callee; - var parent = callee.object; - var depth = 1; + let callee = node.callee; + let parent = callee.object; + let depth = 1; while (parent && parent.callee) { depth += 1; diff --git a/tools/eslint/lib/rules/no-alert.js b/tools/eslint/lib/rules/no-alert.js index e491dfefc5..1ff04a3b68 100644 --- a/tools/eslint/lib/rules/no-alert.js +++ b/tools/eslint/lib/rules/no-alert.js @@ -51,7 +51,7 @@ function getPropertyName(memberExpressionNode) { * @returns {Reference|null} Returns the found reference or null if none were found. */ function findReference(scope, node) { - var references = scope.references.filter(function(reference) { + let references = scope.references.filter(function(reference) { return reference.identifier.range[0] === node.range[0] && reference.identifier.range[1] === node.range[1]; }); @@ -70,7 +70,7 @@ function findReference(scope, node) { * @returns {boolean} Whether or not the name is shadowed. */ function isShadowed(scope, globalScope, node) { - var reference = findReference(scope, node); + let reference = findReference(scope, node); return reference && reference.resolved && reference.resolved.defs.length > 0; } @@ -108,7 +108,7 @@ module.exports = { }, create: function(context) { - var globalScope; + let globalScope; return { @@ -117,7 +117,7 @@ module.exports = { }, CallExpression: function(node) { - var callee = node.callee, + let callee = node.callee, identifierName, currentScope = context.getScope(); diff --git a/tools/eslint/lib/rules/no-bitwise.js b/tools/eslint/lib/rules/no-bitwise.js index 0294998ecc..bfb6c180da 100644 --- a/tools/eslint/lib/rules/no-bitwise.js +++ b/tools/eslint/lib/rules/no-bitwise.js @@ -8,7 +8,7 @@ // // Set of bitwise operators. // -var BITWISE_OPERATORS = [ +let BITWISE_OPERATORS = [ "^", "|", "&", "<<", ">>", ">>>", "^=", "|=", "&=", "<<=", ">>=", ">>>=", "~" @@ -47,9 +47,9 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; - var allowed = options.allow || []; - var int32Hint = options.int32Hint === true; + let options = context.options[0] || {}; + let allowed = options.allow || []; + let int32Hint = options.int32Hint === true; /** * Reports an unexpected use of a bitwise operator. diff --git a/tools/eslint/lib/rules/no-caller.js b/tools/eslint/lib/rules/no-caller.js index 0405fdaeb9..75cfb63f65 100644 --- a/tools/eslint/lib/rules/no-caller.js +++ b/tools/eslint/lib/rules/no-caller.js @@ -25,7 +25,7 @@ module.exports = { return { MemberExpression: function(node) { - var objectName = node.object.name, + let objectName = node.object.name, propertyName = node.property.name; if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/)) { diff --git a/tools/eslint/lib/rules/no-case-declarations.js b/tools/eslint/lib/rules/no-case-declarations.js index 8ef202538e..6538674d41 100644 --- a/tools/eslint/lib/rules/no-case-declarations.js +++ b/tools/eslint/lib/rules/no-case-declarations.js @@ -40,8 +40,8 @@ module.exports = { return { SwitchCase: function(node) { - for (var i = 0; i < node.consequent.length; i++) { - var statement = node.consequent[i]; + for (let i = 0; i < node.consequent.length; i++) { + let statement = node.consequent[i]; if (isLexicalDeclaration(statement)) { context.report({ diff --git a/tools/eslint/lib/rules/no-catch-shadow.js b/tools/eslint/lib/rules/no-catch-shadow.js index 4a206833c0..919ad3bc37 100644 --- a/tools/eslint/lib/rules/no-catch-shadow.js +++ b/tools/eslint/lib/rules/no-catch-shadow.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -34,7 +34,7 @@ module.exports = { /** * Check if the parameters are been shadowed - * @param {object} scope current scope + * @param {Object} scope current scope * @param {string} name parameter name * @returns {boolean} True is its been shadowed */ @@ -49,7 +49,7 @@ module.exports = { return { CatchClause: function(node) { - var scope = context.getScope(); + let scope = context.getScope(); // When blockBindings is enabled, CatchClause creates its own scope // so start from one upper scope to exclude the current node diff --git a/tools/eslint/lib/rules/no-class-assign.js b/tools/eslint/lib/rules/no-class-assign.js index 1e4d3243d8..e12d3a065a 100644 --- a/tools/eslint/lib/rules/no-class-assign.js +++ b/tools/eslint/lib/rules/no-class-assign.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-cond-assign.js b/tools/eslint/lib/rules/no-cond-assign.js index e0979ddaf2..5cba25e8c7 100644 --- a/tools/eslint/lib/rules/no-cond-assign.js +++ b/tools/eslint/lib/rules/no-cond-assign.js @@ -4,7 +4,7 @@ */ "use strict"; -var NODE_DESCRIPTIONS = { +let NODE_DESCRIPTIONS = { DoWhileStatement: "a 'do...while' statement", ForStatement: "a 'for' statement", IfStatement: "an 'if' statement", @@ -32,9 +32,9 @@ module.exports = { create: function(context) { - var prohibitAssign = (context.options[0] || "except-parens"); + let prohibitAssign = (context.options[0] || "except-parens"); - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Check whether an AST node is the test expression for a conditional statement. @@ -53,7 +53,7 @@ module.exports = { * @returns {?Object} The closest ancestor node that represents a conditional statement. */ function findConditionalAncestor(node) { - var currentAncestor = node; + let currentAncestor = node; do { if (isConditionalTestExpression(currentAncestor)) { @@ -70,7 +70,7 @@ module.exports = { * @returns {boolean} `true` if the code is enclosed in parentheses; otherwise, `false`. */ function isParenthesised(node) { - var previousToken = sourceCode.getTokenBefore(node), + let previousToken = sourceCode.getTokenBefore(node), nextToken = sourceCode.getTokenAfter(node); return previousToken.value === "(" && previousToken.range[1] <= node.range[0] && @@ -83,7 +83,7 @@ module.exports = { * @returns {boolean} `true` if the code is enclosed in two sets of parentheses; otherwise, `false`. */ function isParenthesisedTwice(node) { - var previousToken = sourceCode.getTokenBefore(node, 1), + let previousToken = sourceCode.getTokenBefore(node, 1), nextToken = sourceCode.getTokenAfter(node, 1); return isParenthesised(node) && @@ -120,7 +120,7 @@ module.exports = { * @returns {void} */ function testForConditionalAncestor(node) { - var ancestor = findConditionalAncestor(node); + let ancestor = findConditionalAncestor(node); if (ancestor) { context.report(ancestor, "Unexpected assignment within {{type}}.", { diff --git a/tools/eslint/lib/rules/no-confusing-arrow.js b/tools/eslint/lib/rules/no-confusing-arrow.js index 1f18aa3567..42d1f865e2 100644 --- a/tools/eslint/lib/rules/no-confusing-arrow.js +++ b/tools/eslint/lib/rules/no-confusing-arrow.js @@ -6,7 +6,7 @@ "use strict"; -var astUtils = require("../ast-utils.js"); +let astUtils = require("../ast-utils.js"); //------------------------------------------------------------------------------ // Helpers @@ -43,8 +43,8 @@ module.exports = { }, create: function(context) { - var config = context.options[0] || {}; - var sourceCode = context.getSourceCode(); + let config = context.options[0] || {}; + let sourceCode = context.getSourceCode(); /** * Reports if an arrow function contains an ambiguous conditional. @@ -52,7 +52,7 @@ module.exports = { * @returns {void} */ function checkArrowFunc(node) { - var body = node.body; + let body = node.body; if (isConditional(body) && !(config.allowParens && astUtils.isParenthesised(sourceCode, body))) { context.report(node, "Arrow function used ambiguously with a conditional expression."); diff --git a/tools/eslint/lib/rules/no-console.js b/tools/eslint/lib/rules/no-console.js index 18a897409f..553fc72460 100644 --- a/tools/eslint/lib/rules/no-console.js +++ b/tools/eslint/lib/rules/no-console.js @@ -42,12 +42,12 @@ module.exports = { MemberExpression: function(node) { if (node.object.name === "console") { - var blockConsole = true; + let blockConsole = true; if (context.options.length > 0) { - var allowedProperties = context.options[0].allow; - var passedProperty = node.property.name; - var propertyIsAllowed = (allowedProperties.indexOf(passedProperty) > -1); + let allowedProperties = context.options[0].allow; + let passedProperty = node.property.name; + let propertyIsAllowed = (allowedProperties.indexOf(passedProperty) > -1); if (propertyIsAllowed) { blockConsole = false; diff --git a/tools/eslint/lib/rules/no-const-assign.js b/tools/eslint/lib/rules/no-const-assign.js index 344e05a644..8015225dbd 100644 --- a/tools/eslint/lib/rules/no-const-assign.js +++ b/tools/eslint/lib/rules/no-const-assign.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-constant-condition.js b/tools/eslint/lib/rules/no-constant-condition.js index 7c4ede7f78..b2d3b64738 100644 --- a/tools/eslint/lib/rules/no-constant-condition.js +++ b/tools/eslint/lib/rules/no-constant-condition.js @@ -32,7 +32,7 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}, + let options = context.options[0] || {}, checkLoops = options.checkLoops !== false; //-------------------------------------------------------------------------- @@ -85,13 +85,16 @@ module.exports = { return isConstant(node.left, false) && isConstant(node.right, false) && node.operator !== "in"; - case "LogicalExpression": - var isLeftConstant = isConstant(node.left, inBooleanPosition); - var isRightConstant = isConstant(node.right, inBooleanPosition); - var isLeftShortCircuit = (isLeftConstant && isLogicalIdentity(node.left, node.operator)); - var isRightShortCircuit = (isRightConstant && isLogicalIdentity(node.right, node.operator)); + + case "LogicalExpression": { + const isLeftConstant = isConstant(node.left, inBooleanPosition); + const isRightConstant = isConstant(node.right, inBooleanPosition); + const isLeftShortCircuit = (isLeftConstant && isLogicalIdentity(node.left, node.operator)); + const isRightShortCircuit = (isRightConstant && isLogicalIdentity(node.right, node.operator)); return (isLeftConstant && isRightConstant) || isLeftShortCircuit || isRightShortCircuit; + } + case "AssignmentExpression": return (node.operator === "=") && isConstant(node.right, inBooleanPosition); diff --git a/tools/eslint/lib/rules/no-continue.js b/tools/eslint/lib/rules/no-continue.js index 246df89ebe..5e8c059b0e 100644 --- a/tools/eslint/lib/rules/no-continue.js +++ b/tools/eslint/lib/rules/no-continue.js @@ -24,7 +24,7 @@ module.exports = { return { ContinueStatement: function(node) { - context.report(node, "Unexpected use of continue statement"); + context.report(node, "Unexpected use of continue statement."); } }; diff --git a/tools/eslint/lib/rules/no-control-regex.js b/tools/eslint/lib/rules/no-control-regex.js index 74e03f03c5..4032fb2af7 100644 --- a/tools/eslint/lib/rules/no-control-regex.js +++ b/tools/eslint/lib/rules/no-control-regex.js @@ -33,7 +33,7 @@ module.exports = { return node.value; } else if (typeof node.value === "string") { - var parent = context.getAncestors().pop(); + let parent = context.getAncestors().pop(); if ((parent.type === "NewExpression" || parent.type === "CallExpression") && parent.callee.type === "Identifier" && parent.callee.name === "RegExp" @@ -53,22 +53,22 @@ module.exports = { /** * Check if given regex string has control characters in it - * @param {String} regexStr regex as string to check - * @returns {Boolean} returns true if finds control characters on given string + * @param {string} regexStr regex as string to check + * @returns {boolean} returns true if finds control characters on given string * @private */ function hasControlCharacters(regexStr) { // check control characters, if RegExp object used - var hasControlChars = /[\x00-\x1f]/.test(regexStr); // eslint-disable-line no-control-regex + let hasControlChars = /[\x00-\x1f]/.test(regexStr); // eslint-disable-line no-control-regex // check substr, if regex literal used - var subStrIndex = regexStr.search(/\\x[01][0-9a-f]/i); + let subStrIndex = regexStr.search(/\\x[01][0-9a-f]/i); if (!hasControlChars && subStrIndex > -1) { // is it escaped, check backslash count - var possibleEscapeCharacters = regexStr.substr(0, subStrIndex).match(/\\+$/gi); + let possibleEscapeCharacters = regexStr.substr(0, subStrIndex).match(/\\+$/gi); hasControlChars = possibleEscapeCharacters === null || !(possibleEscapeCharacters[0].length % 2); } @@ -78,7 +78,7 @@ module.exports = { return { Literal: function(node) { - var computedValue, + let computedValue, regex = getRegExp(node); if (regex) { diff --git a/tools/eslint/lib/rules/no-div-regex.js b/tools/eslint/lib/rules/no-div-regex.js index 75a6085595..f54a534b22 100644 --- a/tools/eslint/lib/rules/no-div-regex.js +++ b/tools/eslint/lib/rules/no-div-regex.js @@ -21,12 +21,12 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { Literal: function(node) { - var token = sourceCode.getFirstToken(node); + let token = sourceCode.getFirstToken(node); if (token.type === "RegularExpression" && token.value[1] === "=") { context.report(node, "A regular expression literal can be confused with '/='."); diff --git a/tools/eslint/lib/rules/no-dupe-args.js b/tools/eslint/lib/rules/no-dupe-args.js index e927ce2b3a..f63fab5bb2 100644 --- a/tools/eslint/lib/rules/no-dupe-args.js +++ b/tools/eslint/lib/rules/no-dupe-args.js @@ -42,13 +42,13 @@ module.exports = { * @private */ function checkParams(node) { - var variables = context.getDeclaredVariables(node); + let variables = context.getDeclaredVariables(node); - for (var i = 0; i < variables.length; ++i) { - var variable = variables[i]; + for (let i = 0; i < variables.length; ++i) { + let variable = variables[i]; // Checks and reports duplications. - var defs = variable.defs.filter(isParameter); + let defs = variable.defs.filter(isParameter); if (defs.length >= 2) { context.report({ diff --git a/tools/eslint/lib/rules/no-dupe-class-members.js b/tools/eslint/lib/rules/no-dupe-class-members.js index 883020bdfe..102072b8bb 100644 --- a/tools/eslint/lib/rules/no-dupe-class-members.js +++ b/tools/eslint/lib/rules/no-dupe-class-members.js @@ -21,20 +21,20 @@ module.exports = { }, create: function(context) { - var stack = []; + let stack = []; /** * Gets state of a given member name. * @param {string} name - A name of a member. * @param {boolean} isStatic - A flag which specifies that is a static member. - * @returns {object} A state of a given member name. + * @returns {Object} A state of a given member name. * - retv.init {boolean} A flag which shows the name is declared as normal member. * - retv.get {boolean} A flag which shows the name is declared as getter. * - retv.set {boolean} A flag which shows the name is declared as setter. */ function getState(name, isStatic) { - var stateMap = stack[stack.length - 1]; - var key = "$" + name; // to avoid "__proto__". + let stateMap = stack[stack.length - 1]; + let key = "$" + name; // to avoid "__proto__". if (!stateMap[key]) { stateMap[key] = { @@ -85,9 +85,9 @@ module.exports = { return; } - var name = getName(node.key); - var state = getState(name, node.static); - var isDuplicate = false; + let name = getName(node.key); + let state = getState(name, node.static); + let isDuplicate = false; if (node.kind === "get") { isDuplicate = (state.init || state.get); diff --git a/tools/eslint/lib/rules/no-dupe-keys.js b/tools/eslint/lib/rules/no-dupe-keys.js index 26f009b3bf..d2a3fc6773 100644 --- a/tools/eslint/lib/rules/no-dupe-keys.js +++ b/tools/eslint/lib/rules/no-dupe-keys.js @@ -28,7 +28,7 @@ module.exports = { // Object that will be a map of properties--safe because we will // prefix all of the keys. - var nodeProps = Object.create(null); + let nodeProps = Object.create(null); node.properties.forEach(function(property) { @@ -36,7 +36,7 @@ module.exports = { return; } - var keyName = property.key.name || property.key.value, + let keyName = property.key.name || property.key.value, key = property.kind + "-" + keyName, checkProperty = (!property.computed || property.key.type === "Literal"); diff --git a/tools/eslint/lib/rules/no-duplicate-case.js b/tools/eslint/lib/rules/no-duplicate-case.js index 8c877ed4e8..9e9b8b5cd8 100644 --- a/tools/eslint/lib/rules/no-duplicate-case.js +++ b/tools/eslint/lib/rules/no-duplicate-case.js @@ -22,14 +22,14 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { SwitchStatement: function(node) { - var mapping = {}; + let mapping = {}; node.cases.forEach(function(switchCase) { - var key = sourceCode.getText(switchCase.test); + let key = sourceCode.getText(switchCase.test); if (mapping[key]) { context.report(switchCase, "Duplicate case label."); diff --git a/tools/eslint/lib/rules/no-duplicate-imports.js b/tools/eslint/lib/rules/no-duplicate-imports.js index 44432f4863..8594541b14 100644 --- a/tools/eslint/lib/rules/no-duplicate-imports.js +++ b/tools/eslint/lib/rules/no-duplicate-imports.js @@ -60,7 +60,7 @@ function checkAndReport(context, node, value, array, message) { */ function handleImports(context, includeExports, importsInFile, exportsInFile) { return function(node) { - var value = getValue(node); + let value = getValue(node); if (value) { checkAndReport(context, node, value, importsInFile, "import is duplicated."); @@ -85,7 +85,7 @@ function handleImports(context, includeExports, importsInFile, exportsInFile) { */ function handleExports(context, importsInFile, exportsInFile) { return function(node) { - var value = getValue(node); + let value = getValue(node); if (value) { checkAndReport(context, node, value, exportsInFile, "export is duplicated."); @@ -116,11 +116,11 @@ module.exports = { }, create: function(context) { - var includeExports = (context.options[0] || {}).includeExports, + let includeExports = (context.options[0] || {}).includeExports, importsInFile = [], exportsInFile = []; - var handlers = { + let handlers = { ImportDeclaration: handleImports(context, includeExports, importsInFile, exportsInFile) }; diff --git a/tools/eslint/lib/rules/no-else-return.js b/tools/eslint/lib/rules/no-else-return.js index 528d4ca566..05ead21586 100644 --- a/tools/eslint/lib/rules/no-else-return.js +++ b/tools/eslint/lib/rules/no-else-return.js @@ -56,7 +56,7 @@ module.exports = { */ function naiveHasReturn(node) { if (node.type === "BlockStatement") { - var body = node.body, + let body = node.body, lastChildNode = body[body.length - 1]; return lastChildNode && checkForReturn(lastChildNode); @@ -128,7 +128,7 @@ module.exports = { return { IfStatement: function(node) { - var parent = context.getAncestors().pop(), + let parent = context.getAncestors().pop(), consequents, alternate; diff --git a/tools/eslint/lib/rules/no-empty-character-class.js b/tools/eslint/lib/rules/no-empty-character-class.js index 34ef78a396..4a1ae8f92f 100644 --- a/tools/eslint/lib/rules/no-empty-character-class.js +++ b/tools/eslint/lib/rules/no-empty-character-class.js @@ -21,7 +21,7 @@ plain-English description of the following regexp: 4. `[gimuy]*`: optional regexp flags 5. `$`: fix the match at the end of the string */ -var regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+\])*\/[gimuy]*$/; +let regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+\])*\/[gimuy]*$/; //------------------------------------------------------------------------------ // Rule Definition @@ -39,12 +39,12 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { Literal: function(node) { - var token = sourceCode.getFirstToken(node); + let token = sourceCode.getFirstToken(node); if (token.type === "RegularExpression" && !regex.test(token.value)) { context.report(node, "Empty class."); diff --git a/tools/eslint/lib/rules/no-empty-function.js b/tools/eslint/lib/rules/no-empty-function.js index 0102acff51..d7d8c2e886 100644 --- a/tools/eslint/lib/rules/no-empty-function.js +++ b/tools/eslint/lib/rules/no-empty-function.js @@ -9,7 +9,7 @@ // Helpers //------------------------------------------------------------------------------ -var ALLOW_OPTIONS = Object.freeze([ +let ALLOW_OPTIONS = Object.freeze([ "functions", "arrowFunctions", "generatorFunctions", @@ -19,7 +19,7 @@ var ALLOW_OPTIONS = Object.freeze([ "setters", "constructors" ]); -var SHOW_KIND = Object.freeze({ +let SHOW_KIND = Object.freeze({ functions: "function", arrowFunctions: "arrow function", generatorFunctions: "generator function", @@ -44,8 +44,8 @@ var SHOW_KIND = Object.freeze({ * "constructors". */ function getKind(node) { - var parent = node.parent; - var kind = ""; + let parent = node.parent; + let kind = ""; if (node.type === "ArrowFunctionExpression") { return "arrowFunctions"; @@ -78,7 +78,7 @@ function getKind(node) { } // Detects prefix. - var prefix = ""; + let prefix = ""; if (node.generator) { prefix = "generator"; @@ -118,10 +118,10 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; - var allowed = options.allow || []; + let options = context.options[0] || {}; + let allowed = options.allow || []; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Reports a given function node if the node matches the following patterns. @@ -136,7 +136,7 @@ module.exports = { * @returns {void} */ function reportIfEmpty(node) { - var kind = getKind(node); + let kind = getKind(node); if (allowed.indexOf(kind) === -1 && node.body.type === "BlockStatement" && diff --git a/tools/eslint/lib/rules/no-empty.js b/tools/eslint/lib/rules/no-empty.js index 1302a90753..8897cce02b 100644 --- a/tools/eslint/lib/rules/no-empty.js +++ b/tools/eslint/lib/rules/no-empty.js @@ -5,10 +5,14 @@ "use strict"; //------------------------------------------------------------------------------ -// Rule Definition +// Requirements //------------------------------------------------------------------------------ -var FUNCTION_TYPE = /^(?:ArrowFunctionExpression|Function(?:Declaration|Expression))$/; +let astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ module.exports = { meta: { @@ -32,10 +36,10 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}, + let options = context.options[0] || {}, allowEmptyCatch = options.allowEmptyCatch || false; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { BlockStatement: function(node) { @@ -46,7 +50,7 @@ module.exports = { } // a function is generally allowed to be empty - if (FUNCTION_TYPE.test(node.parent.type)) { + if (astUtils.isFunction(node.parent)) { return; } diff --git a/tools/eslint/lib/rules/no-eq-null.js b/tools/eslint/lib/rules/no-eq-null.js index da039bb9d7..743f290803 100644 --- a/tools/eslint/lib/rules/no-eq-null.js +++ b/tools/eslint/lib/rules/no-eq-null.js @@ -26,7 +26,7 @@ module.exports = { return { BinaryExpression: function(node) { - var badOperator = node.operator === "==" || node.operator === "!="; + let badOperator = node.operator === "==" || node.operator === "!="; if (node.right.type === "Literal" && node.right.raw === "null" && badOperator || node.left.type === "Literal" && node.left.raw === "null" && badOperator) { diff --git a/tools/eslint/lib/rules/no-eval.js b/tools/eslint/lib/rules/no-eval.js index 04db4b96b4..67ac1017cf 100644 --- a/tools/eslint/lib/rules/no-eval.js +++ b/tools/eslint/lib/rules/no-eval.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var candidatesOfGlobalObject = Object.freeze([ +let candidatesOfGlobalObject = Object.freeze([ "global", "window" ]); @@ -94,12 +94,12 @@ module.exports = { }, create: function(context) { - var allowIndirect = Boolean( + let allowIndirect = Boolean( context.options[0] && context.options[0].allowIndirect ); - var sourceCode = context.getSourceCode(); - var funcInfo = null; + let sourceCode = context.getSourceCode(); + let funcInfo = null; /** * Pushs a variable scope (Program or Function) information to the stack. @@ -112,7 +112,7 @@ module.exports = { * @returns {void} */ function enterVarScope(node) { - var strict = context.getScope().isStrict; + let strict = context.getScope().isStrict; funcInfo = { upper: funcInfo, @@ -146,8 +146,8 @@ module.exports = { * @returns {void} */ function report(node) { - var locationNode = node; - var parent = node.parent; + let locationNode = node; + let parent = node.parent; if (node.type === "MemberExpression") { locationNode = node.property; @@ -170,19 +170,19 @@ module.exports = { * @returns {void} */ function reportAccessingEvalViaGlobalObject(globalScope) { - for (var i = 0; i < candidatesOfGlobalObject.length; ++i) { - var name = candidatesOfGlobalObject[i]; - var variable = astUtils.getVariableByName(globalScope, name); + for (let i = 0; i < candidatesOfGlobalObject.length; ++i) { + let name = candidatesOfGlobalObject[i]; + let variable = astUtils.getVariableByName(globalScope, name); if (!variable) { continue; } - var references = variable.references; + let references = variable.references; - for (var j = 0; j < references.length; ++j) { - var identifier = references[j].identifier; - var node = identifier.parent; + for (let j = 0; j < references.length; ++j) { + let identifier = references[j].identifier; + let node = identifier.parent; // To detect code like `window.window.eval`. while (isMember(node, name)) { @@ -204,17 +204,17 @@ module.exports = { * @returns {void} */ function reportAccessingEval(globalScope) { - var variable = astUtils.getVariableByName(globalScope, "eval"); + let variable = astUtils.getVariableByName(globalScope, "eval"); if (!variable) { return; } - var references = variable.references; + let references = variable.references; - for (var i = 0; i < references.length; ++i) { - var reference = references[i]; - var id = reference.identifier; + for (let i = 0; i < references.length; ++i) { + let reference = references[i]; + let id = reference.identifier; if (id.name === "eval" && !astUtils.isCallee(id)) { @@ -229,7 +229,7 @@ module.exports = { // Checks only direct calls to eval. It's simple! return { "CallExpression:exit": function(node) { - var callee = node.callee; + let callee = node.callee; if (isIdentifier(callee, "eval")) { report(callee); @@ -240,7 +240,7 @@ module.exports = { return { "CallExpression:exit": function(node) { - var callee = node.callee; + let callee = node.callee; if (isIdentifier(callee, "eval")) { report(callee); @@ -248,7 +248,7 @@ module.exports = { }, Program: function(node) { - var scope = context.getScope(), + let scope = context.getScope(), features = context.parserOptions.ecmaFeatures || {}, strict = scope.isStrict || @@ -265,7 +265,7 @@ module.exports = { }, "Program:exit": function() { - var globalScope = context.getScope(); + let globalScope = context.getScope(); exitVarScope(); reportAccessingEval(globalScope); diff --git a/tools/eslint/lib/rules/no-ex-assign.js b/tools/eslint/lib/rules/no-ex-assign.js index bf3afc6cd3..42aea52723 100644 --- a/tools/eslint/lib/rules/no-ex-assign.js +++ b/tools/eslint/lib/rules/no-ex-assign.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-extend-native.js b/tools/eslint/lib/rules/no-extend-native.js index 69d4931ab6..c58e5c3554 100644 --- a/tools/eslint/lib/rules/no-extend-native.js +++ b/tools/eslint/lib/rules/no-extend-native.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var globals = require("globals"); +let globals = require("globals"); //------------------------------------------------------------------------------ // Rule Definition @@ -42,9 +42,9 @@ module.exports = { create: function(context) { - var config = context.options[0] || {}; - var exceptions = config.exceptions || []; - var modifiedBuiltins = Object.keys(globals.builtin).filter(function(builtin) { + let config = context.options[0] || {}; + let exceptions = config.exceptions || []; + let modifiedBuiltins = Object.keys(globals.builtin).filter(function(builtin) { return builtin[0].toUpperCase() === builtin[0]; }); @@ -58,7 +58,7 @@ module.exports = { // handle the Array.prototype.extra style case AssignmentExpression: function(node) { - var lhs = node.left, + let lhs = node.left, affectsProto; if (lhs.type !== "MemberExpression" || lhs.object.type !== "MemberExpression") { @@ -83,7 +83,7 @@ module.exports = { // handle the Object.definePropert[y|ies](Array.prototype) case CallExpression: function(node) { - var callee = node.callee, + let callee = node.callee, subject, object; diff --git a/tools/eslint/lib/rules/no-extra-bind.js b/tools/eslint/lib/rules/no-extra-bind.js index f75e2fcc25..bdafaf040f 100644 --- a/tools/eslint/lib/rules/no-extra-bind.js +++ b/tools/eslint/lib/rules/no-extra-bind.js @@ -20,7 +20,7 @@ module.exports = { }, create: function(context) { - var scopeInfo = null; + let scopeInfo = null; /** * Reports a given function node. @@ -73,8 +73,8 @@ module.exports = { * @returns {boolean} `true` if the node is the callee of `.bind()` method. */ function isCalleeOfBindMethod(node) { - var parent = node.parent; - var grandparent = parent.parent; + let parent = node.parent; + let grandparent = parent.parent; return ( grandparent && diff --git a/tools/eslint/lib/rules/no-extra-boolean-cast.js b/tools/eslint/lib/rules/no-extra-boolean-cast.js index f14da0821d..890f7cb605 100644 --- a/tools/eslint/lib/rules/no-extra-boolean-cast.js +++ b/tools/eslint/lib/rules/no-extra-boolean-cast.js @@ -23,7 +23,7 @@ module.exports = { create: function(context) { // Node types which have a test which will coerce values to booleans. - var BOOLEAN_NODE_TYPES = [ + let BOOLEAN_NODE_TYPES = [ "IfStatement", "DoWhileStatement", "WhileStatement", @@ -36,7 +36,7 @@ module.exports = { * * @param {Object} node The node * @param {Object} parent Its parent - * @returns {Boolean} If it is in a boolean context + * @returns {boolean} If it is in a boolean context */ function isInBooleanContext(node, parent) { return ( @@ -52,7 +52,7 @@ module.exports = { return { UnaryExpression: function(node) { - var ancestors = context.getAncestors(), + let ancestors = context.getAncestors(), parent = ancestors.pop(), grandparent = ancestors.pop(); @@ -74,7 +74,7 @@ module.exports = { } }, CallExpression: function(node) { - var parent = node.parent; + let parent = node.parent; if (node.callee.type !== "Identifier" || node.callee.name !== "Boolean") { return; diff --git a/tools/eslint/lib/rules/no-extra-label.js b/tools/eslint/lib/rules/no-extra-label.js index f1a48e3688..5b72209bf2 100644 --- a/tools/eslint/lib/rules/no-extra-label.js +++ b/tools/eslint/lib/rules/no-extra-label.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -27,7 +27,7 @@ module.exports = { }, create: function(context) { - var scopeInfo = null; + let scopeInfo = null; /** * Creates a new scope with a breakable statement. @@ -98,9 +98,9 @@ module.exports = { return; } - var labelNode = node.label; - var label = labelNode.name; - var info = scopeInfo; + let labelNode = node.label; + let label = labelNode.name; + let info = scopeInfo; while (info) { if (info.breakable || info.label === label) { diff --git a/tools/eslint/lib/rules/no-extra-parens.js b/tools/eslint/lib/rules/no-extra-parens.js index c33a64920f..86ef6ddc0f 100644 --- a/tools/eslint/lib/rules/no-extra-parens.js +++ b/tools/eslint/lib/rules/no-extra-parens.js @@ -8,7 +8,7 @@ // Rule Definition //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils.js"); +let astUtils = require("../ast-utils.js"); module.exports = { meta: { @@ -54,14 +54,14 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); - var isParenthesised = astUtils.isParenthesised.bind(astUtils, sourceCode); - var precedence = astUtils.getPrecedence; - var ALL_NODES = context.options[0] !== "functions"; - var EXCEPT_COND_ASSIGN = ALL_NODES && context.options[1] && context.options[1].conditionalAssign === false; - var NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false; - var EXCEPT_RETURN_ASSIGN = ALL_NODES && context.options[1] && context.options[1].returnAssign === false; + let isParenthesised = astUtils.isParenthesised.bind(astUtils, sourceCode); + let precedence = astUtils.getPrecedence; + let ALL_NODES = context.options[0] !== "functions"; + let EXCEPT_COND_ASSIGN = ALL_NODES && context.options[1] && context.options[1].conditionalAssign === false; + let NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false; + let EXCEPT_RETURN_ASSIGN = ALL_NODES && context.options[1] && context.options[1].returnAssign === false; /** * Determines if this rule should be enforced for a node given the current configuration. @@ -80,7 +80,7 @@ module.exports = { * @private */ function isParenthesisedTwice(node) { - var previousToken = sourceCode.getTokenBefore(node, 1), + let previousToken = sourceCode.getTokenBefore(node, 1), nextToken = sourceCode.getTokenAfter(node, 1); return isParenthesised(node) && previousToken && nextToken && @@ -199,7 +199,7 @@ module.exports = { * @returns {boolean} `true` if the node is located at the head of ExpressionStatement. */ function isHeadOfExpressionStatement(node) { - var parent = node.parent; + let parent = node.parent; while (parent) { switch (parent.type) { @@ -263,7 +263,7 @@ module.exports = { * @private */ function report(node) { - var previousToken = sourceCode.getTokenBefore(node); + let previousToken = sourceCode.getTokenBefore(node); context.report(node, previousToken.loc.start, "Gratuitous parentheses around expression."); } @@ -317,7 +317,7 @@ module.exports = { */ function dryBinaryLogical(node) { if (!NESTED_BINARY) { - var prec = precedence(node); + let prec = precedence(node); if (hasExcessParens(node.left) && precedence(node.left) >= prec) { report(node.left); @@ -394,7 +394,7 @@ module.exports = { }, ExpressionStatement: function(node) { - var firstToken, secondToken, firstTokens; + let firstToken, secondToken, firstTokens; if (hasExcessParens(node.expression)) { firstTokens = sourceCode.getFirstTokens(node.expression, 2); @@ -484,7 +484,7 @@ module.exports = { ObjectExpression: function(node) { [].forEach.call(node.properties, function(e) { - var v = e.value; + let v = e.value; if (v && hasExcessParens(v) && precedence(v) >= precedence({type: "AssignmentExpression"})) { report(v); @@ -493,7 +493,7 @@ module.exports = { }, ReturnStatement: function(node) { - var returnToken = sourceCode.getFirstToken(node); + let returnToken = sourceCode.getFirstToken(node); if (isReturnAssignException(node)) { return; @@ -529,7 +529,7 @@ module.exports = { }, ThrowStatement: function(node) { - var throwToken = sourceCode.getFirstToken(node); + let throwToken = sourceCode.getFirstToken(node); if (hasExcessParensNoLineTerminator(throwToken, node.argument)) { report(node.argument); @@ -562,7 +562,7 @@ module.exports = { }, YieldExpression: function(node) { - var yieldToken; + let yieldToken; if (node.argument) { yieldToken = sourceCode.getFirstToken(node); diff --git a/tools/eslint/lib/rules/no-extra-semi.js b/tools/eslint/lib/rules/no-extra-semi.js index 679a16641b..37f2253c26 100644 --- a/tools/eslint/lib/rules/no-extra-semi.js +++ b/tools/eslint/lib/rules/no-extra-semi.js @@ -22,7 +22,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Reports an unnecessary semicolon error. @@ -47,7 +47,7 @@ module.exports = { * @returns {void} */ function checkForPartOfClassBody(firstToken) { - for (var token = firstToken; + for (let token = firstToken; token.type === "Punctuator" && token.value !== "}"; token = sourceCode.getTokenAfter(token) ) { @@ -65,7 +65,7 @@ module.exports = { * @returns {void} */ EmptyStatement: function(node) { - var parent = node.parent, + let parent = node.parent, allowedParentTypes = [ "ForStatement", "ForInStatement", diff --git a/tools/eslint/lib/rules/no-fallthrough.js b/tools/eslint/lib/rules/no-fallthrough.js index 2edb4972ba..24f3642fa1 100644 --- a/tools/eslint/lib/rules/no-fallthrough.js +++ b/tools/eslint/lib/rules/no-fallthrough.js @@ -8,13 +8,13 @@ // Requirements //------------------------------------------------------------------------------ -var lodash = require("lodash"); +let lodash = require("lodash"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/i; +let DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/i; /** * Checks whether or not a given node has a fallthrough comment. @@ -24,8 +24,8 @@ var DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/i; * @returns {boolean} `true` if the node has a valid fallthrough comment. */ function hasFallthroughComment(node, context, fallthroughCommentPattern) { - var sourceCode = context.getSourceCode(); - var comment = lodash.last(sourceCode.getComments(node).leading); + let sourceCode = context.getSourceCode(); + let comment = lodash.last(sourceCode.getComments(node).leading); return Boolean(comment && fallthroughCommentPattern.test(comment.value)); } @@ -75,16 +75,16 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; - var currentCodePath = null; - var sourceCode = context.getSourceCode(); + let options = context.options[0] || {}; + let currentCodePath = null; + let sourceCode = context.getSourceCode(); /* * We need to use leading comments of the next SwitchCase node because * trailing comments is wrong if semicolons are omitted. */ - var fallthroughCase = null; - var fallthroughCommentPattern = null; + let fallthroughCase = null; + let fallthroughCommentPattern = null; if (options.commentPattern) { fallthroughCommentPattern = new RegExp(options.commentPattern); @@ -117,7 +117,7 @@ module.exports = { }, "SwitchCase:exit": function(node) { - var nextToken = sourceCode.getTokenAfter(node); + let nextToken = sourceCode.getTokenAfter(node); /* * `reachable` meant fall through because statements preceded by diff --git a/tools/eslint/lib/rules/no-func-assign.js b/tools/eslint/lib/rules/no-func-assign.js index ac3afe55c0..2266a044fc 100644 --- a/tools/eslint/lib/rules/no-func-assign.js +++ b/tools/eslint/lib/rules/no-func-assign.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-implicit-coercion.js b/tools/eslint/lib/rules/no-implicit-coercion.js index 113c205855..ee11bd0087 100644 --- a/tools/eslint/lib/rules/no-implicit-coercion.js +++ b/tools/eslint/lib/rules/no-implicit-coercion.js @@ -9,13 +9,13 @@ // Helpers //------------------------------------------------------------------------------ -var INDEX_OF_PATTERN = /^(?:i|lastI)ndexOf$/; -var ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"]; +let INDEX_OF_PATTERN = /^(?:i|lastI)ndexOf$/; +let ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"]; /** * Parses and normalizes an option object. - * @param {object} options - An option object to parse. - * @returns {object} The parsed and normalized option object. + * @param {Object} options - An option object to parse. + * @returns {Object} The parsed and normalized option object. */ function parseOptions(options) { options = options || {}; @@ -91,7 +91,7 @@ function isNumeric(node) { * @returns {ASTNode|null} The first non-numeric item in the BinaryExpression tree or null */ function getNonNumericOperand(node) { - var left = node.left, + let left = node.left, right = node.right; if (right.type !== "BinaryExpression" && !isNumeric(right)) { @@ -176,10 +176,10 @@ module.exports = { }, create: function(context) { - var options = parseOptions(context.options[0]), + let options = parseOptions(context.options[0]), operatorAllowed = false; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { UnaryExpression: function(node) { @@ -220,7 +220,7 @@ module.exports = { // 1 * foo operatorAllowed = options.allow.indexOf("*") >= 0; - var nonNumericOperand = !operatorAllowed && options.number && isMultiplyByOne(node) && getNonNumericOperand(node); + let nonNumericOperand = !operatorAllowed && options.number && isMultiplyByOne(node) && getNonNumericOperand(node); if (nonNumericOperand) { context.report( diff --git a/tools/eslint/lib/rules/no-implicit-globals.js b/tools/eslint/lib/rules/no-implicit-globals.js index c2768ea1a0..9f8180394f 100644 --- a/tools/eslint/lib/rules/no-implicit-globals.js +++ b/tools/eslint/lib/rules/no-implicit-globals.js @@ -23,7 +23,7 @@ module.exports = { create: function(context) { return { Program: function() { - var scope = context.getScope(); + let scope = context.getScope(); scope.variables.forEach(function(variable) { if (variable.writeable) { @@ -38,7 +38,7 @@ module.exports = { }); scope.implicit.variables.forEach(function(variable) { - var scopeVariable = scope.set.get(variable.name); + let scopeVariable = scope.set.get(variable.name); if (scopeVariable && scopeVariable.writeable) { return; diff --git a/tools/eslint/lib/rules/no-implied-eval.js b/tools/eslint/lib/rules/no-implied-eval.js index 7c1ed2fb6e..ec660fa08f 100644 --- a/tools/eslint/lib/rules/no-implied-eval.js +++ b/tools/eslint/lib/rules/no-implied-eval.js @@ -21,13 +21,13 @@ module.exports = { }, create: function(context) { - var CALLEE_RE = /set(?:Timeout|Interval)|execScript/; + let CALLEE_RE = /set(?:Timeout|Interval)|execScript/; /* * Figures out if we should inspect a given binary expression. Is a stack * of stacks, where the first element in each substack is a CallExpression. */ - var impliedEvalAncestorsStack = []; + let impliedEvalAncestorsStack = []; //-------------------------------------------------------------------------- // Helpers @@ -50,7 +50,7 @@ module.exports = { * @private */ function isImpliedEvalMemberExpression(node) { - var object = node.object, + let object = node.object, property = node.property, hasImpliedEvalName = CALLEE_RE.test(property.name) || CALLEE_RE.test(property.value); @@ -67,7 +67,7 @@ module.exports = { * @private */ function isImpliedEvalCallExpression(node) { - var isMemberExpression = (node.callee.type === "MemberExpression"), + let isMemberExpression = (node.callee.type === "MemberExpression"), isIdentifier = (node.callee.type === "Identifier"), isImpliedEvalCallee = (isIdentifier && CALLEE_RE.test(node.callee.name)) || @@ -103,7 +103,7 @@ module.exports = { if (hasImpliedEvalParent(node)) { // remove the entire substack, to avoid duplicate reports - var substack = impliedEvalAncestorsStack.pop(); + let substack = impliedEvalAncestorsStack.pop(); context.report(substack[0], "Implied eval. Consider passing a function instead of a string."); } diff --git a/tools/eslint/lib/rules/no-inline-comments.js b/tools/eslint/lib/rules/no-inline-comments.js index e313eac06f..87039d4697 100644 --- a/tools/eslint/lib/rules/no-inline-comments.js +++ b/tools/eslint/lib/rules/no-inline-comments.js @@ -4,7 +4,7 @@ */ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -22,7 +22,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Will check that comments are not on lines starting with or ending with code @@ -33,16 +33,16 @@ module.exports = { function testCodeAroundComment(node) { // Get the whole line and cut it off at the start of the comment - var startLine = String(sourceCode.lines[node.loc.start.line - 1]); - var endLine = String(sourceCode.lines[node.loc.end.line - 1]); + let startLine = String(sourceCode.lines[node.loc.start.line - 1]); + let endLine = String(sourceCode.lines[node.loc.end.line - 1]); - var preamble = startLine.slice(0, node.loc.start.column).trim(); + let preamble = startLine.slice(0, node.loc.start.column).trim(); // Also check after the comment - var postamble = endLine.slice(node.loc.end.column).trim(); + let postamble = endLine.slice(node.loc.end.column).trim(); // Check that this comment isn't an ESLint directive - var isDirective = astUtils.isDirectiveComment(node); + let isDirective = astUtils.isDirectiveComment(node); // Should be empty if there was only whitespace around the comment if (!isDirective && (preamble || postamble)) { diff --git a/tools/eslint/lib/rules/no-inner-declarations.js b/tools/eslint/lib/rules/no-inner-declarations.js index 3471ce8cc7..3e21385a59 100644 --- a/tools/eslint/lib/rules/no-inner-declarations.js +++ b/tools/eslint/lib/rules/no-inner-declarations.js @@ -31,7 +31,7 @@ module.exports = { * @returns {Object} Ancestor's type and distance from node. */ function nearestBody() { - var ancestors = context.getAncestors(), + let ancestors = context.getAncestors(), ancestor = ancestors.pop(), generation = 1; @@ -58,7 +58,7 @@ module.exports = { * @returns {void} */ function check(node) { - var body = nearestBody(node), + let body = nearestBody(node), valid = ((body.type === "Program" && body.distance === 1) || body.distance === 2); diff --git a/tools/eslint/lib/rules/no-invalid-regexp.js b/tools/eslint/lib/rules/no-invalid-regexp.js index 6f8b867378..eb693c55c6 100644 --- a/tools/eslint/lib/rules/no-invalid-regexp.js +++ b/tools/eslint/lib/rules/no-invalid-regexp.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -var espree = require("espree"); +let espree = require("espree"); //------------------------------------------------------------------------------ // Rule Definition @@ -38,7 +38,7 @@ module.exports = { create: function(context) { - var options = context.options[0], + let options = context.options[0], allowedFlags = ""; if (options && options.allowConstructorFlags) { @@ -63,7 +63,7 @@ module.exports = { */ function check(node) { if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0])) { - var flags = isString(node.arguments[1]) ? node.arguments[1].value : ""; + let flags = isString(node.arguments[1]) ? node.arguments[1].value : ""; if (allowedFlags) { flags = flags.replace(new RegExp("[" + allowedFlags + "]", "gi"), ""); @@ -72,7 +72,7 @@ module.exports = { try { void new RegExp(node.arguments[0].value); } catch (e) { - context.report(node, e.message); + context.report(node, e.message + "."); } if (flags) { @@ -80,7 +80,7 @@ module.exports = { try { espree.parse("/./" + flags, context.parserOptions); } catch (ex) { - context.report(node, "Invalid flags supplied to RegExp constructor '" + flags + "'"); + context.report(node, "Invalid flags supplied to RegExp constructor '" + flags + "'."); } } diff --git a/tools/eslint/lib/rules/no-invalid-this.js b/tools/eslint/lib/rules/no-invalid-this.js index 198bfd706a..e41c474699 100644 --- a/tools/eslint/lib/rules/no-invalid-this.js +++ b/tools/eslint/lib/rules/no-invalid-this.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -27,7 +27,7 @@ module.exports = { }, create: function(context) { - var stack = [], + let stack = [], sourceCode = context.getSourceCode(); /** @@ -40,7 +40,7 @@ module.exports = { * an object which has a flag that whether or not `this` keyword is valid. */ stack.getCurrent = function() { - var current = this[this.length - 1]; + let current = this[this.length - 1]; if (!current.init) { current.init = true; @@ -86,7 +86,7 @@ module.exports = { * Modules is always strict mode. */ Program: function(node) { - var scope = context.getScope(), + let scope = context.getScope(), features = context.parserOptions.ecmaFeatures || {}; stack.push({ @@ -111,7 +111,7 @@ module.exports = { // Reports if `this` of the current context is invalid. ThisExpression: function(node) { - var current = stack.getCurrent(); + let current = stack.getCurrent(); if (current && !current.valid) { context.report(node, "Unexpected 'this'."); diff --git a/tools/eslint/lib/rules/no-irregular-whitespace.js b/tools/eslint/lib/rules/no-irregular-whitespace.js index 032dd96c11..0049de3dde 100644 --- a/tools/eslint/lib/rules/no-irregular-whitespace.js +++ b/tools/eslint/lib/rules/no-irregular-whitespace.js @@ -10,10 +10,10 @@ // Constants //------------------------------------------------------------------------------ -var ALL_IRREGULARS = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/; -var IRREGULAR_WHITESPACE = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg; -var IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mg; -var LINE_BREAK = /\r\n|\r|\n|\u2028|\u2029/g; +let ALL_IRREGULARS = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/; +let IRREGULAR_WHITESPACE = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg; +let IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mg; +let LINE_BREAK = /\r\n|\r|\n|\u2028|\u2029/g; //------------------------------------------------------------------------------ // Rule Definition @@ -52,19 +52,19 @@ module.exports = { create: function(context) { // Module store of errors that we have found - var errors = []; + let errors = []; // Comment nodes. We accumulate these as we go, so we can be sure to trigger them after the whole `Program` entity is parsed, even for top-of-file comments. - var commentNodes = []; + let commentNodes = []; // Lookup the `skipComments` option, which defaults to `false`. - var options = context.options[0] || {}; - var skipComments = !!options.skipComments; - var skipStrings = options.skipStrings !== false; - var skipRegExps = !!options.skipRegExps; - var skipTemplates = !!options.skipTemplates; + let options = context.options[0] || {}; + let skipComments = !!options.skipComments; + let skipStrings = options.skipStrings !== false; + let skipRegExps = !!options.skipRegExps; + let skipTemplates = !!options.skipTemplates; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Removes errors that occur inside a string node @@ -73,11 +73,11 @@ module.exports = { * @private */ function removeWhitespaceError(node) { - var locStart = node.loc.start; - var locEnd = node.loc.end; + let locStart = node.loc.start; + let locEnd = node.loc.end; errors = errors.filter(function(error) { - var errorLoc = error[1]; + let errorLoc = error[1]; if (errorLoc.line >= locStart.line && errorLoc.line <= locEnd.line) { if (errorLoc.column >= locStart.column && (errorLoc.column <= locEnd.column || errorLoc.line < locEnd.line)) { @@ -95,8 +95,8 @@ module.exports = { * @private */ function removeInvalidNodeErrorsInIdentifierOrLiteral(node) { - var shouldCheckStrings = skipStrings && (typeof node.value === "string"); - var shouldCheckRegExps = skipRegExps && (node.value instanceof RegExp); + let shouldCheckStrings = skipStrings && (typeof node.value === "string"); + let shouldCheckRegExps = skipRegExps && (node.value instanceof RegExp); if (shouldCheckStrings || shouldCheckRegExps) { @@ -140,10 +140,10 @@ module.exports = { * @private */ function checkForIrregularWhitespace(node) { - var sourceLines = sourceCode.lines; + let sourceLines = sourceCode.lines; sourceLines.forEach(function(sourceLine, lineIndex) { - var lineNumber = lineIndex + 1, + let lineNumber = lineIndex + 1, location, match; @@ -153,7 +153,7 @@ module.exports = { column: match.index }; - errors.push([node, location, "Irregular whitespace not allowed"]); + errors.push([node, location, "Irregular whitespace not allowed."]); } }); } @@ -165,7 +165,7 @@ module.exports = { * @private */ function checkForIrregularLineTerminators(node) { - var source = sourceCode.getText(), + let source = sourceCode.getText(), sourceLines = sourceCode.lines, linebreaks = source.match(LINE_BREAK), lastLineIndex = -1, @@ -181,7 +181,7 @@ module.exports = { column: sourceLines[lineIndex].length }; - errors.push([node, location, "Irregular whitespace not allowed"]); + errors.push([node, location, "Irregular whitespace not allowed."]); lastLineIndex = lineIndex; } } @@ -203,7 +203,7 @@ module.exports = { */ function noop() {} - var nodes = {}; + let nodes = {}; if (ALL_IRREGULARS.test(sourceCode.getText())) { nodes.Program = function(node) { diff --git a/tools/eslint/lib/rules/no-label-var.js b/tools/eslint/lib/rules/no-label-var.js index 7c6d56f355..a203324f14 100644 --- a/tools/eslint/lib/rules/no-label-var.js +++ b/tools/eslint/lib/rules/no-label-var.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -34,7 +34,7 @@ module.exports = { /** * Check if the identifier is present inside current scope - * @param {object} scope current scope + * @param {Object} scope current scope * @param {string} name To evaluate * @returns {boolean} True if its present * @private @@ -52,7 +52,7 @@ module.exports = { LabeledStatement: function(node) { // Fetch the innermost scope. - var scope = context.getScope(); + let scope = context.getScope(); // Recursively find the identifier walking up the scope, starting // with the innermost scope. diff --git a/tools/eslint/lib/rules/no-labels.js b/tools/eslint/lib/rules/no-labels.js index da0cd8e742..adc5bc0f81 100644 --- a/tools/eslint/lib/rules/no-labels.js +++ b/tools/eslint/lib/rules/no-labels.js @@ -5,10 +5,10 @@ "use strict"; //------------------------------------------------------------------------------ -// Constants +// Requirements //------------------------------------------------------------------------------ -var LOOP_TYPES = /^(?:While|DoWhile|For|ForIn|ForOf)Statement$/; +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -39,10 +39,10 @@ module.exports = { }, create: function(context) { - var options = context.options[0]; - var allowLoop = Boolean(options && options.allowLoop); - var allowSwitch = Boolean(options && options.allowSwitch); - var scopeInfo = null; + let options = context.options[0]; + let allowLoop = Boolean(options && options.allowLoop); + let allowSwitch = Boolean(options && options.allowSwitch); + let scopeInfo = null; /** * Gets the kind of a given node. @@ -51,12 +51,10 @@ module.exports = { * @returns {string} The kind of the node. */ function getBodyKind(node) { - var type = node.type; - - if (LOOP_TYPES.test(type)) { + if (astUtils.isLoop(node)) { return "loop"; } - if (type === "SwitchStatement") { + if (node.type === "SwitchStatement") { return "switch"; } return "other"; @@ -83,7 +81,7 @@ module.exports = { * @returns {boolean} `true` if the name is a label of a loop. */ function getKind(label) { - var info = scopeInfo; + let info = scopeInfo; while (info) { if (info.label === label) { diff --git a/tools/eslint/lib/rules/no-lone-blocks.js b/tools/eslint/lib/rules/no-lone-blocks.js index 113cd89b93..e93f1d0809 100644 --- a/tools/eslint/lib/rules/no-lone-blocks.js +++ b/tools/eslint/lib/rules/no-lone-blocks.js @@ -23,7 +23,7 @@ module.exports = { create: function(context) { // A stack of lone blocks to be checked for block-level bindings - var loneBlocks = [], + let loneBlocks = [], ruleDef; /** @@ -32,7 +32,7 @@ module.exports = { * @returns {void} */ function report(node) { - var parent = context.getAncestors().pop(); + let parent = context.getAncestors().pop(); context.report(node, parent.type === "Program" ? "Block is redundant." : @@ -45,7 +45,7 @@ module.exports = { * @returns {boolean} True if the current node is a lone block. */ function isLoneBlock() { - var parent = context.getAncestors().pop(); + let parent = context.getAncestors().pop(); return parent.type === "BlockStatement" || parent.type === "Program"; } @@ -60,7 +60,7 @@ module.exports = { return; } - var block = context.getAncestors().pop(); + let block = context.getAncestors().pop(); if (loneBlocks[loneBlocks.length - 1] === block) { loneBlocks.pop(); diff --git a/tools/eslint/lib/rules/no-lonely-if.js b/tools/eslint/lib/rules/no-lonely-if.js index 1efd1acc01..4c99bca838 100644 --- a/tools/eslint/lib/rules/no-lonely-if.js +++ b/tools/eslint/lib/rules/no-lonely-if.js @@ -23,7 +23,7 @@ module.exports = { return { IfStatement: function(node) { - var ancestors = context.getAncestors(), + let ancestors = context.getAncestors(), parent = ancestors.pop(), grandparent = ancestors.pop(); diff --git a/tools/eslint/lib/rules/no-loop-func.js b/tools/eslint/lib/rules/no-loop-func.js index 247dc52cd4..e940933896 100644 --- a/tools/eslint/lib/rules/no-loop-func.js +++ b/tools/eslint/lib/rules/no-loop-func.js @@ -20,7 +20,7 @@ * `null`. */ function getContainingLoopNode(node) { - var parent = node.parent; + let parent = node.parent; while (parent) { switch (parent.type) { @@ -73,8 +73,8 @@ function getContainingLoopNode(node) { * @returns {ASTNode} The most outer loop node. */ function getTopLoopNode(node, excludedNode) { - var retv = node; - var border = excludedNode ? excludedNode.range[1] : 0; + let retv = node; + let border = excludedNode ? excludedNode.range[1] : 0; while (node && node.range[0] >= border) { retv = node; @@ -94,10 +94,10 @@ function getTopLoopNode(node, excludedNode) { * @returns {boolean} `true` if the reference is safe or not. */ function isSafe(funcNode, loopNode, reference) { - var variable = reference.resolved; - var definition = variable && variable.defs[0]; - var declaration = definition && definition.parent; - var kind = (declaration && declaration.type === "VariableDeclaration") + let variable = reference.resolved; + let definition = variable && variable.defs[0]; + let declaration = definition && definition.parent; + let kind = (declaration && declaration.type === "VariableDeclaration") ? declaration.kind : ""; @@ -117,7 +117,7 @@ function isSafe(funcNode, loopNode, reference) { // WriteReferences which exist after this border are unsafe because those // can modify the variable. - var border = getTopLoopNode( + let border = getTopLoopNode( loopNode, (kind === "let") ? declaration : null ).range[0]; @@ -135,7 +135,7 @@ function isSafe(funcNode, loopNode, reference) { * @returns {boolean} `true` if the reference is safe. */ function isSafeReference(upperRef) { - var id = upperRef.identifier; + let id = upperRef.identifier; return ( !upperRef.isWrite() || @@ -174,18 +174,18 @@ module.exports = { * @returns {boolean} Whether or not the node is within a loop. */ function checkForLoops(node) { - var loopNode = getContainingLoopNode(node); + let loopNode = getContainingLoopNode(node); if (!loopNode) { return; } - var references = context.getScope().through; + let references = context.getScope().through; if (references.length > 0 && !references.every(isSafe.bind(null, node, loopNode)) ) { - context.report(node, "Don't make functions within a loop"); + context.report(node, "Don't make functions within a loop."); } } diff --git a/tools/eslint/lib/rules/no-magic-numbers.js b/tools/eslint/lib/rules/no-magic-numbers.js index 2e7434c1a5..76d71c1e6c 100644 --- a/tools/eslint/lib/rules/no-magic-numbers.js +++ b/tools/eslint/lib/rules/no-magic-numbers.js @@ -42,7 +42,7 @@ module.exports = { }, create: function(context) { - var config = context.options[0] || {}, + let config = context.options[0] || {}, detectObjects = !!config.detectObjects, enforceConst = !!config.enforceConst, ignore = config.ignore || [], @@ -100,7 +100,7 @@ module.exports = { return { Literal: function(node) { - var parent = node.parent, + let parent = node.parent, value = node.value, raw = node.raw, okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"]; @@ -128,14 +128,14 @@ module.exports = { if (enforceConst && parent.parent.kind !== "const") { context.report({ node: node, - message: "Number constants declarations must use 'const'" + message: "Number constants declarations must use 'const'." }); } } else if (okTypes.indexOf(parent.type) === -1 || (parent.type === "AssignmentExpression" && parent.operator !== "=")) { context.report({ node: node, - message: "No magic number: " + raw + message: "No magic number: " + raw + "." }); } } diff --git a/tools/eslint/lib/rules/no-mixed-operators.js b/tools/eslint/lib/rules/no-mixed-operators.js index 9a8b1c3925..f6e686521d 100644 --- a/tools/eslint/lib/rules/no-mixed-operators.js +++ b/tools/eslint/lib/rules/no-mixed-operators.js @@ -9,43 +9,43 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils.js"); +let astUtils = require("../ast-utils.js"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var ARITHMETIC_OPERATORS = ["+", "-", "*", "/", "%", "**"]; -var BITWISE_OPERATORS = ["&", "|", "^", "~", "<<", ">>", ">>>"]; -var COMPARISON_OPERATORS = ["==", "!=", "===", "!==", ">", ">=", "<", "<="]; -var LOGICAL_OPERATORS = ["&&", "||"]; -var RELATIONAL_OPERATORS = ["in", "instanceof"]; -var ALL_OPERATORS = [].concat( +let ARITHMETIC_OPERATORS = ["+", "-", "*", "/", "%", "**"]; +let BITWISE_OPERATORS = ["&", "|", "^", "~", "<<", ">>", ">>>"]; +let COMPARISON_OPERATORS = ["==", "!=", "===", "!==", ">", ">=", "<", "<="]; +let LOGICAL_OPERATORS = ["&&", "||"]; +let RELATIONAL_OPERATORS = ["in", "instanceof"]; +let ALL_OPERATORS = [].concat( ARITHMETIC_OPERATORS, BITWISE_OPERATORS, COMPARISON_OPERATORS, LOGICAL_OPERATORS, RELATIONAL_OPERATORS ); -var DEFAULT_GROUPS = [ +let DEFAULT_GROUPS = [ ARITHMETIC_OPERATORS, BITWISE_OPERATORS, COMPARISON_OPERATORS, LOGICAL_OPERATORS, RELATIONAL_OPERATORS ]; -var TARGET_NODE_TYPE = /^(?:Binary|Logical)Expression$/; +let TARGET_NODE_TYPE = /^(?:Binary|Logical)Expression$/; /** * Normalizes options. * - * @param {object|undefined} options - A options object to normalize. - * @returns {object} Normalized option object. + * @param {Object|undefined} options - A options object to normalize. + * @returns {Object} Normalized option object. */ function normalizeOptions(options) { - var hasGroups = (options && options.groups && options.groups.length > 0); - var groups = hasGroups ? options.groups : DEFAULT_GROUPS; - var allowSamePrecedence = (options && options.allowSamePrecedence) !== false; + let hasGroups = (options && options.groups && options.groups.length > 0); + let groups = hasGroups ? options.groups : DEFAULT_GROUPS; + let allowSamePrecedence = (options && options.allowSamePrecedence) !== false; return { groups: groups, @@ -102,8 +102,8 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); - var options = normalizeOptions(context.options[0]); + let sourceCode = context.getSourceCode(); + let options = normalizeOptions(context.options[0]); /** * Checks whether a given node should be ignored by options or not. @@ -114,8 +114,8 @@ module.exports = { * @returns {boolean} `true` if the node should be ignored. */ function shouldIgnore(node) { - var a = node; - var b = node.parent; + let a = node; + let b = node.parent; return ( !includesBothInAGroup(options.groups, a.operator, b.operator) || @@ -150,7 +150,7 @@ module.exports = { * @returns {Token} The operator token of the node. */ function getOperatorToken(node) { - var token = sourceCode.getTokenAfter(node.left); + let token = sourceCode.getTokenAfter(node.left); while (token.value === ")") { token = sourceCode.getTokenAfter(token); @@ -169,10 +169,10 @@ module.exports = { * @returns {void} */ function reportBothOperators(node) { - var parent = node.parent; - var left = (parent.left === node) ? node : parent; - var right = (parent.left !== node) ? node : parent; - var message = + let parent = node.parent; + let left = (parent.left === node) ? node : parent; + let right = (parent.left !== node) ? node : parent; + let message = "Unexpected mix of '" + left.operator + "' and '" + right.operator + "'."; diff --git a/tools/eslint/lib/rules/no-mixed-requires.js b/tools/eslint/lib/rules/no-mixed-requires.js index b6d365a9db..68ce51f56f 100644 --- a/tools/eslint/lib/rules/no-mixed-requires.js +++ b/tools/eslint/lib/rules/no-mixed-requires.js @@ -42,7 +42,7 @@ module.exports = { create: function(context) { - var grouping = false, + let grouping = false, allowCall = false, options = context.options[0]; @@ -74,13 +74,13 @@ module.exports = { ]; } - var BUILTIN_MODULES = getBuiltinModules(); + let BUILTIN_MODULES = getBuiltinModules(); - var DECL_REQUIRE = "require", + let DECL_REQUIRE = "require", DECL_UNINITIALIZED = "uninitialized", DECL_OTHER = "other"; - var REQ_CORE = "core", + let REQ_CORE = "core", REQ_FILE = "file", REQ_MODULE = "module", REQ_COMPUTED = "computed"; @@ -137,7 +137,7 @@ module.exports = { return REQ_COMPUTED; } - var arg = initExpression.arguments[0]; + let arg = initExpression.arguments[0]; if (arg.type !== "Literal" || typeof arg.value !== "string") { @@ -167,10 +167,10 @@ module.exports = { * @returns {boolean} True if the declarations are mixed, false if not. */ function isMixed(declarations) { - var contains = {}; + let contains = {}; declarations.forEach(function(declaration) { - var type = getDeclarationType(declaration.init); + let type = getDeclarationType(declaration.init); contains[type] = true; }); @@ -188,7 +188,7 @@ module.exports = { * @returns {boolean} True if the declarations are grouped, false if not. */ function isGrouped(declarations) { - var found = {}; + let found = {}; declarations.forEach(function(declaration) { if (getDeclarationType(declaration.init) === DECL_REQUIRE) { diff --git a/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js b/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js index 74553f6511..19734b1b5d 100644 --- a/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js +++ b/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js @@ -24,9 +24,9 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); - var smartTabs, + let smartTabs, ignoredLocs = []; switch (context.options[0]) { @@ -85,7 +85,7 @@ module.exports = { * or the reverse before non-tab/-space * characters begin. */ - var regex = /^(?=[\t ]*(\t | \t))/, + let regex = /^(?=[\t ]*(\t | \t))/, match, lines = sourceCode.lines, comments = sourceCode.getAllComments(); @@ -119,10 +119,10 @@ module.exports = { match = regex.exec(line); if (match) { - var lineNumber = i + 1, + let lineNumber = i + 1, column = match.index + 1; - for (var j = 0; j < ignoredLocs.length; j++) { + for (let j = 0; j < ignoredLocs.length; j++) { if (beforeLoc(ignoredLocs[j], lineNumber, column)) { continue; } diff --git a/tools/eslint/lib/rules/no-multi-spaces.js b/tools/eslint/lib/rules/no-multi-spaces.js index 2fd89ef4dc..78d600c884 100644 --- a/tools/eslint/lib/rules/no-multi-spaces.js +++ b/tools/eslint/lib/rules/no-multi-spaces.js @@ -41,7 +41,7 @@ module.exports = { create: function(context) { // the index of the last comment that was checked - var exceptions = { Property: true }, + let exceptions = { Property: true }, hasExceptions = true, options = context.options[0], lastCommentIndex = 0; @@ -69,7 +69,7 @@ module.exports = { */ function isIndexInComment(index, comments) { - var comment; + let comment; while (lastCommentIndex < comments.length) { @@ -95,7 +95,7 @@ module.exports = { return { Program: function() { - var sourceCode = context.getSourceCode(), + let sourceCode = context.getSourceCode(), source = sourceCode.getText(), allComments = sourceCode.getAllComments(), pattern = /[^\n\r\u2028\u2029\t ].? {2,}/g, // note: repeating space @@ -108,7 +108,7 @@ module.exports = { * Creates a fix function that removes the multiple spaces between the two tokens * @param {RuleFixer} leftToken left token * @param {RuleFixer} rightToken right token - * @returns {function} fix function + * @returns {Function} fix function * @private */ function createFix(leftToken, rightToken) { diff --git a/tools/eslint/lib/rules/no-multi-str.js b/tools/eslint/lib/rules/no-multi-str.js index fe7fee4a60..1d88010459 100644 --- a/tools/eslint/lib/rules/no-multi-str.js +++ b/tools/eslint/lib/rules/no-multi-str.js @@ -39,7 +39,7 @@ module.exports = { return { Literal: function(node) { - var lineBreak = /\n/; + let lineBreak = /\n/; if (lineBreak.test(node.raw) && !isJSXElement(node.parent)) { context.report(node, "Multiline support is limited to browsers supporting ES5 only."); diff --git a/tools/eslint/lib/rules/no-multiple-empty-lines.js b/tools/eslint/lib/rules/no-multiple-empty-lines.js index 7508164d38..cede2d5e78 100644 --- a/tools/eslint/lib/rules/no-multiple-empty-lines.js +++ b/tools/eslint/lib/rules/no-multiple-empty-lines.js @@ -45,12 +45,12 @@ module.exports = { create: function(context) { // Use options.max or 2 as default - var max = 2, + let max = 2, maxEOF, maxBOF; // store lines that appear empty but really aren't - var notEmpty = []; + let notEmpty = []; if (context.options.length) { max = context.options[0].max; @@ -58,7 +58,7 @@ module.exports = { maxBOF = typeof context.options[0].maxBOF !== "undefined" ? context.options[0].maxBOF : max; } - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Public @@ -67,8 +67,8 @@ module.exports = { return { TemplateLiteral: function(node) { - var start = node.loc.start.line; - var end = node.loc.end.line; + let start = node.loc.start.line; + let end = node.loc.end.line; while (start <= end) { notEmpty.push(start); @@ -77,7 +77,7 @@ module.exports = { }, "Program:exit": function checkBlankLines(node) { - var lines = sourceCode.lines, + let lines = sourceCode.lines, fullLines = sourceCode.text.match(/.*(\r\n|\r|\n|\u2028|\u2029)/g) || [], firstNonBlankLine = -1, trimmedLines = [], @@ -98,7 +98,7 @@ module.exports = { linesRangeStart.push(0); lines.forEach(function(str, i) { - var length = i < fullLines.length ? fullLines[i].length : 0, + let length = i < fullLines.length ? fullLines[i].length : 0, trimmed = str.trim(); if ((firstNonBlankLine === -1) && (trimmed !== "")) { diff --git a/tools/eslint/lib/rules/no-native-reassign.js b/tools/eslint/lib/rules/no-native-reassign.js index 8b75f022a0..aa8314dda6 100644 --- a/tools/eslint/lib/rules/no-native-reassign.js +++ b/tools/eslint/lib/rules/no-native-reassign.js @@ -33,8 +33,8 @@ module.exports = { }, create: function(context) { - var config = context.options[0]; - var exceptions = (config && config.exceptions) || []; + let config = context.options[0]; + let exceptions = (config && config.exceptions) || []; /** * Reports write references. @@ -44,7 +44,7 @@ module.exports = { * @returns {void} */ function checkReference(reference, index, references) { - var identifier = reference.identifier; + let identifier = reference.identifier; if (reference.init === false && reference.isWrite() && @@ -74,7 +74,7 @@ module.exports = { return { Program: function() { - var globalScope = context.getScope(); + let globalScope = context.getScope(); globalScope.variables.forEach(checkVariable); } diff --git a/tools/eslint/lib/rules/no-negated-in-lhs.js b/tools/eslint/lib/rules/no-negated-in-lhs.js index 891b75dd2f..46f6c1cad4 100644 --- a/tools/eslint/lib/rules/no-negated-in-lhs.js +++ b/tools/eslint/lib/rules/no-negated-in-lhs.js @@ -26,7 +26,7 @@ module.exports = { BinaryExpression: function(node) { if (node.operator === "in" && node.left.type === "UnaryExpression" && node.left.operator === "!") { - context.report(node, "The 'in' expression's left operand is negated"); + context.report(node, "The 'in' expression's left operand is negated."); } } }; diff --git a/tools/eslint/lib/rules/no-nested-ternary.js b/tools/eslint/lib/rules/no-nested-ternary.js index 34f9eaaa8d..d28ee693cf 100644 --- a/tools/eslint/lib/rules/no-nested-ternary.js +++ b/tools/eslint/lib/rules/no-nested-ternary.js @@ -26,7 +26,7 @@ module.exports = { ConditionalExpression: function(node) { if (node.alternate.type === "ConditionalExpression" || node.consequent.type === "ConditionalExpression") { - context.report(node, "Do not nest ternary expressions"); + context.report(node, "Do not nest ternary expressions."); } } }; diff --git a/tools/eslint/lib/rules/no-new-symbol.js b/tools/eslint/lib/rules/no-new-symbol.js index c7c524641e..d4c4e67b17 100644 --- a/tools/eslint/lib/rules/no-new-symbol.js +++ b/tools/eslint/lib/rules/no-new-symbol.js @@ -24,12 +24,12 @@ module.exports = { return { "Program:exit": function() { - var globalScope = context.getScope(); - var variable = globalScope.set.get("Symbol"); + let globalScope = context.getScope(); + let variable = globalScope.set.get("Symbol"); if (variable && variable.defs.length === 0) { variable.references.forEach(function(ref) { - var node = ref.identifier; + let node = ref.identifier; if (node.parent && node.parent.type === "NewExpression") { context.report(node, "`Symbol` cannot be called as a constructor."); diff --git a/tools/eslint/lib/rules/no-new-wrappers.js b/tools/eslint/lib/rules/no-new-wrappers.js index eec774fdca..756ee80076 100644 --- a/tools/eslint/lib/rules/no-new-wrappers.js +++ b/tools/eslint/lib/rules/no-new-wrappers.js @@ -25,7 +25,7 @@ module.exports = { return { NewExpression: function(node) { - var wrapperObjects = ["String", "Number", "Boolean", "Math", "JSON"]; + let wrapperObjects = ["String", "Number", "Boolean", "Math", "JSON"]; if (wrapperObjects.indexOf(node.callee.name) > -1) { context.report(node, "Do not use {{fn}} as a constructor.", { fn: node.callee.name }); diff --git a/tools/eslint/lib/rules/no-obj-calls.js b/tools/eslint/lib/rules/no-obj-calls.js index 0f58ab93db..ba1c45a31f 100644 --- a/tools/eslint/lib/rules/no-obj-calls.js +++ b/tools/eslint/lib/rules/no-obj-calls.js @@ -26,7 +26,7 @@ module.exports = { CallExpression: function(node) { if (node.callee.type === "Identifier") { - var name = node.callee.name; + let name = node.callee.name; if (name === "Math" || name === "JSON") { context.report(node, "'{{name}}' is not a function.", { name: name }); diff --git a/tools/eslint/lib/rules/no-octal-escape.js b/tools/eslint/lib/rules/no-octal-escape.js index 3ca01324b5..cf5953a986 100644 --- a/tools/eslint/lib/rules/no-octal-escape.js +++ b/tools/eslint/lib/rules/no-octal-escape.js @@ -29,7 +29,7 @@ module.exports = { return; } - var match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/), + let match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/), octalDigit; if (match) { diff --git a/tools/eslint/lib/rules/no-param-reassign.js b/tools/eslint/lib/rules/no-param-reassign.js index fad61fc0c1..3a59106a2d 100644 --- a/tools/eslint/lib/rules/no-param-reassign.js +++ b/tools/eslint/lib/rules/no-param-reassign.js @@ -8,7 +8,7 @@ // Rule Definition //------------------------------------------------------------------------------ -var stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program)$/; +let stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program)$/; module.exports = { meta: { @@ -30,7 +30,7 @@ module.exports = { }, create: function(context) { - var props = context.options[0] && Boolean(context.options[0].props); + let props = context.options[0] && Boolean(context.options[0].props); /** * Checks whether or not the reference modifies properties of its variable. @@ -38,8 +38,8 @@ module.exports = { * @returns {boolean} Whether or not the reference modifies properties of its variable. */ function isModifyingProp(reference) { - var node = reference.identifier; - var parent = node.parent; + let node = reference.identifier; + let parent = node.parent; while (parent && !stopNodePattern.test(parent.type)) { switch (parent.type) { @@ -92,7 +92,7 @@ module.exports = { * @returns {void} */ function checkReference(reference, index, references) { - var identifier = reference.identifier; + let identifier = reference.identifier; if (identifier && !reference.init && diff --git a/tools/eslint/lib/rules/no-path-concat.js b/tools/eslint/lib/rules/no-path-concat.js index 1412c6c32e..f13d942674 100644 --- a/tools/eslint/lib/rules/no-path-concat.js +++ b/tools/eslint/lib/rules/no-path-concat.js @@ -21,7 +21,7 @@ module.exports = { create: function(context) { - var MATCHER = /^__(?:dir|file)name$/; + let MATCHER = /^__(?:dir|file)name$/; //-------------------------------------------------------------------------- // Public @@ -31,7 +31,7 @@ module.exports = { BinaryExpression: function(node) { - var left = node.left, + let left = node.left, right = node.right; if (node.operator === "+" && diff --git a/tools/eslint/lib/rules/no-plusplus.js b/tools/eslint/lib/rules/no-plusplus.js index 159a42be2c..34e54001ae 100644 --- a/tools/eslint/lib/rules/no-plusplus.js +++ b/tools/eslint/lib/rules/no-plusplus.js @@ -33,7 +33,7 @@ module.exports = { create: function(context) { - var config = context.options[0], + let config = context.options[0], allowInForAfterthought = false; if (typeof config === "object") { diff --git a/tools/eslint/lib/rules/no-process-env.js b/tools/eslint/lib/rules/no-process-env.js index af48c78029..d1bf15a245 100644 --- a/tools/eslint/lib/rules/no-process-env.js +++ b/tools/eslint/lib/rules/no-process-env.js @@ -24,7 +24,7 @@ module.exports = { return { MemberExpression: function(node) { - var objectName = node.object.name, + let objectName = node.object.name, propertyName = node.property.name; if (objectName === "process" && !node.computed && propertyName && propertyName === "env") { diff --git a/tools/eslint/lib/rules/no-process-exit.js b/tools/eslint/lib/rules/no-process-exit.js index 6d8674418b..045214e7e7 100644 --- a/tools/eslint/lib/rules/no-process-exit.js +++ b/tools/eslint/lib/rules/no-process-exit.js @@ -28,7 +28,7 @@ module.exports = { return { CallExpression: function(node) { - var callee = node.callee; + let callee = node.callee; if (callee.type === "MemberExpression" && callee.object.name === "process" && callee.property.name === "exit" diff --git a/tools/eslint/lib/rules/no-prototype-builtins.js b/tools/eslint/lib/rules/no-prototype-builtins.js index febb1459be..08b0b6dcf9 100644 --- a/tools/eslint/lib/rules/no-prototype-builtins.js +++ b/tools/eslint/lib/rules/no-prototype-builtins.js @@ -14,11 +14,13 @@ module.exports = { description: "disallow calling some `Object.prototype` methods directly on objects", category: "Possible Errors", recommended: false - } + }, + + schema: [] }, create: function(context) { - var DISALLOWED_PROPS = [ + let DISALLOWED_PROPS = [ "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable" @@ -33,7 +35,7 @@ module.exports = { if (node.callee.type !== "MemberExpression" || node.callee.computed) { return; } - var propName = node.callee.property.name; + let propName = node.callee.property.name; if (DISALLOWED_PROPS.indexOf(propName) > -1) { context.report({ diff --git a/tools/eslint/lib/rules/no-redeclare.js b/tools/eslint/lib/rules/no-redeclare.js index 4253cc8533..8a1540ff79 100644 --- a/tools/eslint/lib/rules/no-redeclare.js +++ b/tools/eslint/lib/rules/no-redeclare.js @@ -29,7 +29,7 @@ module.exports = { }, create: function(context) { - var options = { + let options = { builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals) }; @@ -41,18 +41,18 @@ module.exports = { */ function findVariablesInScope(scope) { scope.variables.forEach(function(variable) { - var hasBuiltin = options.builtinGlobals && "writeable" in variable; - var count = (hasBuiltin ? 1 : 0) + variable.identifiers.length; + let hasBuiltin = options.builtinGlobals && "writeable" in variable; + let count = (hasBuiltin ? 1 : 0) + variable.identifiers.length; if (count >= 2) { variable.identifiers.sort(function(a, b) { return a.range[1] - b.range[1]; }); - for (var i = (hasBuiltin ? 0 : 1), l = variable.identifiers.length; i < l; i++) { + for (let i = (hasBuiltin ? 0 : 1), l = variable.identifiers.length; i < l; i++) { context.report( variable.identifiers[i], - "'{{a}}' is already defined", + "'{{a}}' is already defined.", {a: variable.name}); } } @@ -67,7 +67,7 @@ module.exports = { * @private */ function checkForGlobal(node) { - var scope = context.getScope(), + let scope = context.getScope(), parserOptions = context.parserOptions, ecmaFeatures = parserOptions.ecmaFeatures || {}; diff --git a/tools/eslint/lib/rules/no-regex-spaces.js b/tools/eslint/lib/rules/no-regex-spaces.js index a2f1d48f71..de179894b3 100644 --- a/tools/eslint/lib/rules/no-regex-spaces.js +++ b/tools/eslint/lib/rules/no-regex-spaces.js @@ -21,7 +21,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Validate regular expressions @@ -31,7 +31,7 @@ module.exports = { * @private */ function checkRegex(node, value) { - var multipleSpacesRegex = /( {2,})+?/, + let multipleSpacesRegex = /( {2,})+?/, regexResults = multipleSpacesRegex.exec(value); if (regexResults !== null) { @@ -46,7 +46,7 @@ module.exports = { * @private */ function checkLiteral(node) { - var token = sourceCode.getFirstToken(node), + let token = sourceCode.getFirstToken(node), nodeType = token.type, nodeValue = token.value; diff --git a/tools/eslint/lib/rules/no-restricted-globals.js b/tools/eslint/lib/rules/no-restricted-globals.js index 3292705b13..19bd6a94ae 100644 --- a/tools/eslint/lib/rules/no-restricted-globals.js +++ b/tools/eslint/lib/rules/no-restricted-globals.js @@ -26,7 +26,7 @@ module.exports = { }, create: function(context) { - var restrictedGlobals = context.options; + let restrictedGlobals = context.options; // if no globals are restricted we don't need to check if (restrictedGlobals.length === 0) { @@ -40,7 +40,7 @@ module.exports = { * @private */ function reportReference(reference) { - context.report(reference.identifier, "Unexpected use of '{{name}}'", { + context.report(reference.identifier, "Unexpected use of '{{name}}'.", { name: reference.identifier.name }); } @@ -57,7 +57,7 @@ module.exports = { return { Program: function() { - var scope = context.getScope(); + let scope = context.getScope(); // Report variables declared elsewhere (ex: variables defined as "global" by eslint) scope.variables.forEach(function(variable) { @@ -77,4 +77,3 @@ module.exports = { }; } }; - diff --git a/tools/eslint/lib/rules/no-restricted-imports.js b/tools/eslint/lib/rules/no-restricted-imports.js index 3129ce7278..da768c135c 100644 --- a/tools/eslint/lib/rules/no-restricted-imports.js +++ b/tools/eslint/lib/rules/no-restricted-imports.js @@ -26,7 +26,7 @@ module.exports = { }, create: function(context) { - var restrictedImports = context.options; + let restrictedImports = context.options; // if no imports are restricted we don"t need to check if (restrictedImports.length === 0) { @@ -37,7 +37,7 @@ module.exports = { ImportDeclaration: function(node) { if (node && node.source && node.source.value) { - var value = node.source.value.trim(); + let value = node.source.value.trim(); if (restrictedImports.indexOf(value) !== -1) { context.report(node, "'{{importName}}' import is restricted from being used.", { diff --git a/tools/eslint/lib/rules/no-restricted-modules.js b/tools/eslint/lib/rules/no-restricted-modules.js index 43e5391562..eeb6bf270d 100644 --- a/tools/eslint/lib/rules/no-restricted-modules.js +++ b/tools/eslint/lib/rules/no-restricted-modules.js @@ -28,7 +28,7 @@ module.exports = { create: function(context) { // trim restricted module names - var restrictedModules = context.options; + let restrictedModules = context.options; // if no modules are restricted we don't need to check the CallExpressions if (restrictedModules.length === 0) { @@ -56,14 +56,14 @@ module.exports = { /** * Function to check if a node has an argument that is an restricted module and return its name. * @param {ASTNode} node The node to check - * @returns {undefined|String} restricted module name or undefined if node argument isn't restricted. + * @returns {undefined|string} restricted module name or undefined if node argument isn't restricted. */ function getRestrictedModuleName(node) { - var moduleName; + let moduleName; // node has arguments and first argument is string if (node.arguments.length && isString(node.arguments[0])) { - var argumentValue = node.arguments[0].value.trim(); + let argumentValue = node.arguments[0].value.trim(); // check if argument value is in restricted modules array if (restrictedModules.indexOf(argumentValue) !== -1) { @@ -77,7 +77,7 @@ module.exports = { return { CallExpression: function(node) { if (isRequireCall(node)) { - var restrictedModuleName = getRestrictedModuleName(node); + let restrictedModuleName = getRestrictedModuleName(node); if (restrictedModuleName) { context.report(node, "'{{moduleName}}' module is restricted from being used.", { diff --git a/tools/eslint/lib/rules/no-restricted-syntax.js b/tools/eslint/lib/rules/no-restricted-syntax.js index cd9eb603f9..84c62d63ac 100644 --- a/tools/eslint/lib/rules/no-restricted-syntax.js +++ b/tools/eslint/lib/rules/no-restricted-syntax.js @@ -8,7 +8,7 @@ // Rule Definition //------------------------------------------------------------------------------ -var nodeTypes = require("espree").Syntax; +let nodeTypes = require("espree").Syntax; module.exports = { meta: { diff --git a/tools/eslint/lib/rules/no-return-assign.js b/tools/eslint/lib/rules/no-return-assign.js index 38fc1cb0eb..5493506071 100644 --- a/tools/eslint/lib/rules/no-return-assign.js +++ b/tools/eslint/lib/rules/no-return-assign.js @@ -8,7 +8,7 @@ // Helpers //------------------------------------------------------------------------------ -var SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/; +let SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/; /** * Checks whether or not a node is enclosed in parentheses. @@ -17,8 +17,8 @@ var SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExp * @returns {boolean} Whether or not the node is enclosed in parentheses. */ function isEnclosedInParens(node, sourceCode) { - var prevToken = sourceCode.getTokenBefore(node); - var nextToken = sourceCode.getTokenAfter(node); + let prevToken = sourceCode.getTokenBefore(node); + let nextToken = sourceCode.getTokenAfter(node); return prevToken && prevToken.value === "(" && nextToken && nextToken.value === ")"; } @@ -43,8 +43,8 @@ module.exports = { }, create: function(context) { - var always = (context.options[0] || "except-parens") !== "except-parens"; - var sourceCode = context.getSourceCode(); + let always = (context.options[0] || "except-parens") !== "except-parens"; + let sourceCode = context.getSourceCode(); return { AssignmentExpression: function(node) { @@ -52,7 +52,7 @@ module.exports = { return; } - var parent = node.parent; + let parent = node.parent; // Find ReturnStatement or ArrowFunctionExpression in ancestors. while (parent && !SENTINEL_TYPE.test(parent.type)) { diff --git a/tools/eslint/lib/rules/no-script-url.js b/tools/eslint/lib/rules/no-script-url.js index 1985cf3b95..1c12490b43 100644 --- a/tools/eslint/lib/rules/no-script-url.js +++ b/tools/eslint/lib/rules/no-script-url.js @@ -28,7 +28,7 @@ module.exports = { Literal: function(node) { - var value; + let value; if (node.value && typeof node.value === "string") { value = node.value.toLowerCase(); diff --git a/tools/eslint/lib/rules/no-self-assign.js b/tools/eslint/lib/rules/no-self-assign.js index bcccc3d838..e3dc35e81e 100644 --- a/tools/eslint/lib/rules/no-self-assign.js +++ b/tools/eslint/lib/rules/no-self-assign.js @@ -16,11 +16,11 @@ * a Property. * @param {ASTNode|null} right - A right node to traverse. This is a Pattern or * a Property. - * @param {function} report - A callback function to report. + * @param {Function} report - A callback function to report. * @returns {void} */ function eachSelfAssignment(left, right, report) { - var i, j; + let i, j; if (!left || !right) { @@ -35,10 +35,10 @@ function eachSelfAssignment(left, right, report) { left.type === "ArrayPattern" && right.type === "ArrayExpression" ) { - var end = Math.min(left.elements.length, right.elements.length); + let end = Math.min(left.elements.length, right.elements.length); for (i = 0; i < end; ++i) { - var rightElement = right.elements[i]; + let rightElement = right.elements[i]; eachSelfAssignment(left.elements[i], rightElement, report); @@ -60,7 +60,7 @@ function eachSelfAssignment(left, right, report) { // Gets the index of the last spread property. // It's possible to overwrite properties followed by it. - var startJ = 0; + let startJ = 0; for (i = right.properties.length - 1; i >= 0; --i) { if (right.properties[i].type === "ExperimentalSpreadProperty") { diff --git a/tools/eslint/lib/rules/no-self-compare.js b/tools/eslint/lib/rules/no-self-compare.js index eef05080b7..c677e56ffd 100644 --- a/tools/eslint/lib/rules/no-self-compare.js +++ b/tools/eslint/lib/rules/no-self-compare.js @@ -26,7 +26,7 @@ module.exports = { return { BinaryExpression: function(node) { - var operators = ["===", "==", "!==", "!=", ">", "<", ">=", "<="]; + let operators = ["===", "==", "!==", "!=", ">", "<", ">=", "<="]; if (operators.indexOf(node.operator) > -1 && (node.left.type === "Identifier" && node.right.type === "Identifier" && node.left.name === node.right.name || diff --git a/tools/eslint/lib/rules/no-sequences.js b/tools/eslint/lib/rules/no-sequences.js index b0d318c7d0..51c3b8e808 100644 --- a/tools/eslint/lib/rules/no-sequences.js +++ b/tools/eslint/lib/rules/no-sequences.js @@ -21,12 +21,12 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Parts of the grammar that are required to have parens. */ - var parenthesized = { + let parenthesized = { DoWhileStatement: "test", IfStatement: "test", SwitchStatement: "discriminant", @@ -57,7 +57,7 @@ module.exports = { * @returns {boolean} True if the node has a paren on each side. */ function isParenthesised(node) { - var previousToken = sourceCode.getTokenBefore(node), + let previousToken = sourceCode.getTokenBefore(node), nextToken = sourceCode.getTokenAfter(node); return previousToken && nextToken && @@ -71,7 +71,7 @@ module.exports = { * @returns {boolean} True if two parens surround the node on each side. */ function isParenthesisedTwice(node) { - var previousToken = sourceCode.getTokenBefore(node, 1), + let previousToken = sourceCode.getTokenBefore(node, 1), nextToken = sourceCode.getTokenAfter(node, 1); return isParenthesised(node) && previousToken && nextToken && @@ -99,7 +99,7 @@ module.exports = { } } - var child = sourceCode.getTokenAfter(node.expressions[0]); + let child = sourceCode.getTokenAfter(node.expressions[0]); context.report(node, child.loc.start, "Unexpected use of comma operator."); } diff --git a/tools/eslint/lib/rules/no-shadow-restricted-names.js b/tools/eslint/lib/rules/no-shadow-restricted-names.js index b7731d9d67..d932363d6f 100644 --- a/tools/eslint/lib/rules/no-shadow-restricted-names.js +++ b/tools/eslint/lib/rules/no-shadow-restricted-names.js @@ -21,7 +21,7 @@ module.exports = { create: function(context) { - var RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"]; + let RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"]; /** * Check if the node name is present inside the restricted list diff --git a/tools/eslint/lib/rules/no-shadow.js b/tools/eslint/lib/rules/no-shadow.js index ee0dd69f3a..62f7504780 100644 --- a/tools/eslint/lib/rules/no-shadow.js +++ b/tools/eslint/lib/rules/no-shadow.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -43,7 +43,7 @@ module.exports = { create: function(context) { - var options = { + let options = { builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals), hoist: (context.options[0] && context.options[0].hoist) || "functions", allow: (context.options[0] && context.options[0].allow) || [] @@ -69,7 +69,7 @@ module.exports = { * @returns {boolean} Whether or not the variable of the class name in the class scope of ClassDeclaration. */ function isDuplicatedClassNameVariable(variable) { - var block = variable.scope.block; + let block = variable.scope.block; return block.type === "ClassDeclaration" && block.id === variable.identifiers[0]; } @@ -85,12 +85,12 @@ module.exports = { * @returns {boolean} Whether or not the variable is inside initializer of scopeVar. */ function isOnInitializer(variable, scopeVar) { - var outerScope = scopeVar.scope; - var outerDef = scopeVar.defs[0]; - var outer = outerDef && outerDef.parent && outerDef.parent.range; - var innerScope = variable.scope; - var innerDef = variable.defs[0]; - var inner = innerDef && innerDef.name.range; + let outerScope = scopeVar.scope; + let outerDef = scopeVar.defs[0]; + let outer = outerDef && outerDef.parent && outerDef.parent.range; + let innerScope = variable.scope; + let innerDef = variable.defs[0]; + let inner = innerDef && innerDef.name.range; return ( outer && @@ -108,7 +108,7 @@ module.exports = { * @returns {Array|undefined} The range of the variable's identifier node. */ function getNameRange(variable) { - var def = variable.defs[0]; + let def = variable.defs[0]; return def && def.name.range; } @@ -120,9 +120,9 @@ module.exports = { * @returns {boolean} Whether or not the variable is in TDZ of scopeVar. */ function isInTdz(variable, scopeVar) { - var outerDef = scopeVar.defs[0]; - var inner = getNameRange(variable); - var outer = getNameRange(scopeVar); + let outerDef = scopeVar.defs[0]; + let inner = getNameRange(variable); + let outer = getNameRange(scopeVar); return ( inner && @@ -140,10 +140,10 @@ module.exports = { * @returns {void} */ function checkForShadows(scope) { - var variables = scope.variables; + let variables = scope.variables; - for (var i = 0; i < variables.length; ++i) { - var variable = variables[i]; + for (let i = 0; i < variables.length; ++i) { + let variable = variables[i]; // Skips "arguments" or variables of a class name in the class scope of ClassDeclaration. if (variable.identifiers.length === 0 || @@ -154,7 +154,7 @@ module.exports = { } // Gets shadowed variable. - var shadowed = astUtils.getVariableByName(scope.upper, variable.name); + let shadowed = astUtils.getVariableByName(scope.upper, variable.name); if (shadowed && (shadowed.identifiers.length > 0 || (options.builtinGlobals && "writeable" in shadowed)) && @@ -172,9 +172,9 @@ module.exports = { return { "Program:exit": function() { - var globalScope = context.getScope(); - var stack = globalScope.childScopes.slice(); - var scope; + let globalScope = context.getScope(); + let stack = globalScope.childScopes.slice(); + let scope; while (stack.length) { scope = stack.pop(); diff --git a/tools/eslint/lib/rules/no-spaced-func.js b/tools/eslint/lib/rules/no-spaced-func.js index f0a1612113..90765645e8 100644 --- a/tools/eslint/lib/rules/no-spaced-func.js +++ b/tools/eslint/lib/rules/no-spaced-func.js @@ -23,7 +23,7 @@ module.exports = { create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Check if open space is present in a function name @@ -32,7 +32,7 @@ module.exports = { * @private */ function detectOpenSpaces(node) { - var lastCalleeToken = sourceCode.getLastToken(node.callee), + let lastCalleeToken = sourceCode.getLastToken(node.callee), prevToken = lastCalleeToken, parenToken = sourceCode.getTokenAfter(lastCalleeToken); diff --git a/tools/eslint/lib/rules/no-sparse-arrays.js b/tools/eslint/lib/rules/no-sparse-arrays.js index b1ae0ba740..4d4bfd9944 100644 --- a/tools/eslint/lib/rules/no-sparse-arrays.js +++ b/tools/eslint/lib/rules/no-sparse-arrays.js @@ -30,7 +30,7 @@ module.exports = { ArrayExpression: function(node) { - var emptySpot = node.elements.indexOf(null) > -1; + let emptySpot = node.elements.indexOf(null) > -1; if (emptySpot) { context.report(node, "Unexpected comma in middle of array."); diff --git a/tools/eslint/lib/rules/no-sync.js b/tools/eslint/lib/rules/no-sync.js index be6860e75a..ddd1f9484b 100644 --- a/tools/eslint/lib/rules/no-sync.js +++ b/tools/eslint/lib/rules/no-sync.js @@ -27,7 +27,7 @@ module.exports = { return { MemberExpression: function(node) { - var propertyName = node.property.name, + let propertyName = node.property.name, syncRegex = /.*Sync$/; if (syncRegex.exec(propertyName) !== null) { diff --git a/tools/eslint/lib/rules/no-tabs.js b/tools/eslint/lib/rules/no-tabs.js new file mode 100644 index 0000000000..ef873db2bd --- /dev/null +++ b/tools/eslint/lib/rules/no-tabs.js @@ -0,0 +1,47 @@ +/** + * @fileoverview Rule to check for tabs inside a file + * @author Gyandeep Singh + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ +const regex = /\t/; + +//------------------------------------------------------------------------------ +// Public Interface +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "Disallow tabs in file", + category: "Stylistic Issues", + recommended: false + }, + schema: [] + }, + + create(context) { + return { + Program(node) { + context.getSourceLines().forEach((line, index) => { + const match = regex.exec(line); + + if (match) { + context.report( + node, + { + line: index + 1, + column: match.index + 1 + }, + "Unexpected tab character." + ); + } + }); + } + }; + } +}; diff --git a/tools/eslint/lib/rules/no-this-before-super.js b/tools/eslint/lib/rules/no-this-before-super.js index fb172f47f3..82eda02160 100644 --- a/tools/eslint/lib/rules/no-this-before-super.js +++ b/tools/eslint/lib/rules/no-this-before-super.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -55,7 +55,7 @@ module.exports = { * - scope: The scope of the owner class. * - codePath: The code path of this constructor. */ - var funcInfo = null; + let funcInfo = null; /* * Information for each code path segment. @@ -64,7 +64,7 @@ module.exports = { * - superCalled: The flag which shows `super()` called in all code paths. * - invalidNodes: The array of invalid ThisExpression and Super nodes. */ - var segInfoMap = Object.create(null); + let segInfoMap = Object.create(null); /** * Gets whether or not `super()` is called in a given code path segment. @@ -101,10 +101,10 @@ module.exports = { * @returns {void} */ function setInvalid(node) { - var segments = funcInfo.codePath.currentSegments; + let segments = funcInfo.codePath.currentSegments; - for (var i = 0; i < segments.length; ++i) { - var segment = segments[i]; + for (let i = 0; i < segments.length; ++i) { + let segment = segments[i]; if (segment.reachable) { segInfoMap[segment.id].invalidNodes.push(node); @@ -117,10 +117,10 @@ module.exports = { * @returns {void} */ function setSuperCalled() { - var segments = funcInfo.codePath.currentSegments; + let segments = funcInfo.codePath.currentSegments; - for (var i = 0; i < segments.length; ++i) { - var segment = segments[i]; + for (let i = 0; i < segments.length; ++i) { + let segment = segments[i]; if (segment.reachable) { segInfoMap[segment.id].superCalled = true; @@ -140,7 +140,7 @@ module.exports = { if (isConstructorFunction(node)) { // Class > ClassBody > MethodDefinition > FunctionExpression - var classNode = node.parent.parent.parent; + let classNode = node.parent.parent.parent; funcInfo = { upper: funcInfo, @@ -172,7 +172,7 @@ module.exports = { * @returns {void} */ onCodePathEnd: function(codePath) { - var isDerivedClass = funcInfo.hasExtends; + let isDerivedClass = funcInfo.hasExtends; funcInfo = funcInfo.upper; if (!isDerivedClass) { @@ -180,10 +180,10 @@ module.exports = { } codePath.traverseSegments(function(segment, controller) { - var info = segInfoMap[segment.id]; + let info = segInfoMap[segment.id]; - for (var i = 0; i < info.invalidNodes.length; ++i) { - var invalidNode = info.invalidNodes[i]; + for (let i = 0; i < info.invalidNodes.length; ++i) { + let invalidNode = info.invalidNodes[i]; context.report({ message: "'{{kind}}' is not allowed before 'super()'.", @@ -238,7 +238,7 @@ module.exports = { funcInfo.codePath.traverseSegments( {first: toSegment, last: fromSegment}, function(segment, controller) { - var info = segInfoMap[segment.id]; + let info = segInfoMap[segment.id]; if (info.superCalled) { info.invalidNodes = []; diff --git a/tools/eslint/lib/rules/no-throw-literal.js b/tools/eslint/lib/rules/no-throw-literal.js index bedf94379e..69eda1c765 100644 --- a/tools/eslint/lib/rules/no-throw-literal.js +++ b/tools/eslint/lib/rules/no-throw-literal.js @@ -27,10 +27,11 @@ function couldBeError(node) { case "AssignmentExpression": return couldBeError(node.right); - case "SequenceExpression": - var exprs = node.expressions; + case "SequenceExpression": { + const exprs = node.expressions; return exprs.length !== 0 && couldBeError(exprs[exprs.length - 1]); + } case "LogicalExpression": return couldBeError(node.left) || couldBeError(node.right); diff --git a/tools/eslint/lib/rules/no-trailing-spaces.js b/tools/eslint/lib/rules/no-trailing-spaces.js index a08907fc95..6b82cfc38c 100644 --- a/tools/eslint/lib/rules/no-trailing-spaces.js +++ b/tools/eslint/lib/rules/no-trailing-spaces.js @@ -32,13 +32,13 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); - var BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u2028\u2029\u3000]", + let BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u2028\u2029\u3000]", SKIP_BLANK = "^" + BLANK_CLASS + "*$", NONBLANK = BLANK_CLASS + "+$"; - var options = context.options[0] || {}, + let options = context.options[0] || {}, skipBlankLines = options.skipBlankLines || false; /** @@ -78,7 +78,7 @@ module.exports = { // Let's hack. Since Espree does not return whitespace nodes, // fetch the source code and do matching via regexps. - var re = new RegExp(NONBLANK), + let re = new RegExp(NONBLANK), skipMatch = new RegExp(SKIP_BLANK), matches, lines = sourceCode.lines, @@ -90,14 +90,14 @@ module.exports = { fixRange = [], containingNode; - for (var i = 0, ii = lines.length; i < ii; i++) { + for (let i = 0, ii = lines.length; i < ii; i++) { matches = re.exec(lines[i]); // Always add linebreak length to line length to accommodate for line break (\n or \r\n) // Because during the fix time they also reserve one spot in the array. // Usually linebreak length is 2 for \r\n (CRLF) and 1 for \n (LF) - var linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1; - var lineLength = lines[i].length + linebreakLength; + let linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1; + let lineLength = lines[i].length + linebreakLength; if (matches) { location = { diff --git a/tools/eslint/lib/rules/no-undef-init.js b/tools/eslint/lib/rules/no-undef-init.js index 8622e45701..2683f61e8a 100644 --- a/tools/eslint/lib/rules/no-undef-init.js +++ b/tools/eslint/lib/rules/no-undef-init.js @@ -25,7 +25,7 @@ module.exports = { return { VariableDeclarator: function(node) { - var name = node.id.name, + let name = node.id.name, init = node.init && node.init.name; if (init === "undefined" && node.parent.kind !== "const") { diff --git a/tools/eslint/lib/rules/no-undef.js b/tools/eslint/lib/rules/no-undef.js index b76ce4bb5b..da9437157c 100644 --- a/tools/eslint/lib/rules/no-undef.js +++ b/tools/eslint/lib/rules/no-undef.js @@ -14,7 +14,7 @@ * @returns {boolean} Whether or not the node is the argument of a typeof operator. */ function hasTypeOfOperator(node) { - var parent = node.parent; + let parent = node.parent; return parent.type === "UnaryExpression" && parent.operator === "typeof"; } @@ -45,15 +45,15 @@ module.exports = { }, create: function(context) { - var options = context.options[0]; - var considerTypeOf = options && options.typeof === true || false; + let options = context.options[0]; + let considerTypeOf = options && options.typeof === true || false; return { "Program:exit": function(/* node */) { - var globalScope = context.getScope(); + let globalScope = context.getScope(); globalScope.through.forEach(function(ref) { - var identifier = ref.identifier; + let identifier = ref.identifier; if (!considerTypeOf && hasTypeOfOperator(identifier)) { return; diff --git a/tools/eslint/lib/rules/no-undefined.js b/tools/eslint/lib/rules/no-undefined.js index 3ad2128b4e..a34d665203 100644 --- a/tools/eslint/lib/rules/no-undefined.js +++ b/tools/eslint/lib/rules/no-undefined.js @@ -25,7 +25,7 @@ module.exports = { Identifier: function(node) { if (node.name === "undefined") { - var parent = context.getAncestors().pop(); + let parent = context.getAncestors().pop(); if (!parent || parent.type !== "MemberExpression" || node !== parent.property || parent.computed) { context.report(node, "Unexpected use of undefined."); diff --git a/tools/eslint/lib/rules/no-underscore-dangle.js b/tools/eslint/lib/rules/no-underscore-dangle.js index 4217f8adc5..a6a3b174fc 100644 --- a/tools/eslint/lib/rules/no-underscore-dangle.js +++ b/tools/eslint/lib/rules/no-underscore-dangle.js @@ -29,6 +29,9 @@ module.exports = { }, allowAfterThis: { type: "boolean" + }, + allowAfterSuper: { + type: "boolean" } }, additionalProperties: false @@ -38,9 +41,10 @@ module.exports = { create: function(context) { - var options = context.options[0] || {}; - var ALLOWED_VARIABLES = options.allow ? options.allow : []; - var allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false; + let options = context.options[0] || {}; + let ALLOWED_VARIABLES = options.allow ? options.allow : []; + let allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false; + let allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false; //------------------------------------------------------------------------- // Helpers @@ -65,7 +69,7 @@ module.exports = { * @private */ function hasTrailingUnderscore(identifier) { - var len = identifier.length; + let len = identifier.length; return identifier !== "_" && (identifier[0] === "_" || identifier[len - 1] === "_"); } @@ -100,7 +104,7 @@ module.exports = { */ function checkForTrailingUnderscoreInFunctionDeclaration(node) { if (node.id) { - var identifier = node.id.name; + let identifier = node.id.name; if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) { context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); @@ -115,7 +119,7 @@ module.exports = { * @private */ function checkForTrailingUnderscoreInVariableExpression(node) { - var identifier = node.id.name; + let identifier = node.id.name; if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) { @@ -130,11 +134,13 @@ module.exports = { * @private */ function checkForTrailingUnderscoreInMemberExpression(node) { - var identifier = node.property.name, - isMemberOfThis = node.object.type === "ThisExpression"; + let identifier = node.property.name, + isMemberOfThis = node.object.type === "ThisExpression", + isMemberOfSuper = node.object.type === "Super"; if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !(isMemberOfThis && allowAfterThis) && + !(isMemberOfSuper && allowAfterSuper) && !isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) { context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); } diff --git a/tools/eslint/lib/rules/no-unexpected-multiline.js b/tools/eslint/lib/rules/no-unexpected-multiline.js index af0beb2c4d..6fcb8c681a 100644 --- a/tools/eslint/lib/rules/no-unexpected-multiline.js +++ b/tools/eslint/lib/rules/no-unexpected-multiline.js @@ -20,11 +20,11 @@ module.exports = { create: function(context) { - var FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call."; - var PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access."; - var TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal."; + let FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call."; + let PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access."; + let TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal."; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Check to see if there is a newline between the node and the following open bracket @@ -35,8 +35,8 @@ module.exports = { * @private */ function checkForBreakAfter(node, msg) { - var nodeExpressionEnd = node; - var openParen = sourceCode.getTokenAfter(node); + let nodeExpressionEnd = node; + let openParen = sourceCode.getTokenAfter(node); // Move along until the end of the wrapped expression while (openParen.value === ")") { diff --git a/tools/eslint/lib/rules/no-unmodified-loop-condition.js b/tools/eslint/lib/rules/no-unmodified-loop-condition.js index ed49b5996e..099dd5f955 100644 --- a/tools/eslint/lib/rules/no-unmodified-loop-condition.js +++ b/tools/eslint/lib/rules/no-unmodified-loop-condition.js @@ -9,27 +9,26 @@ // Requirements //------------------------------------------------------------------------------ -var Map = require("es6-map"), - Traverser = require("../util/traverser"), +let Traverser = require("../util/traverser"), astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var pushAll = Function.apply.bind(Array.prototype.push); -var SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/; -var LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/; -var GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/; -var SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/; -var DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/; +let pushAll = Function.apply.bind(Array.prototype.push); +let SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/; +let LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/; // for-in/of statements don't have `test` property. +let GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/; +let SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/; +let DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/; /** - * @typedef {object} LoopConditionInfo + * @typedef {Object} LoopConditionInfo * @property {escope.Reference} reference - The reference. * @property {ASTNode} group - BinaryExpression or ConditionalExpression nodes * that the reference is belonging to. - * @property {function} isInLoop - The predicate which checks a given reference + * @property {Function} isInLoop - The predicate which checks a given reference * is in this loop. * @property {boolean} modified - The flag that the reference is modified in * this loop. @@ -43,7 +42,7 @@ var DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/; */ function isWriteReference(reference) { if (reference.init) { - var def = reference.resolved && reference.resolved.defs[0]; + let def = reference.resolved && reference.resolved.defs[0]; if (!def || def.type !== "Variable" || def.parent.kind !== "var") { return false; @@ -82,8 +81,8 @@ function isUnmodifiedAndNotBelongToGroup(condition) { * @returns {boolean} `true` if the reference is inside of the node. */ function isInRange(node, reference) { - var or = node.range; - var ir = reference.identifier.range; + let or = node.range; + let ir = reference.identifier.range; return or[0] <= ir[0] && ir[1] <= or[1]; } @@ -96,7 +95,7 @@ function isInRange(node, reference) { * @returns {boolean} `true` if the reference is inside of the loop node's * condition. */ -var isInLoop = { +let isInLoop = { WhileStatement: isInRange, DoWhileStatement: isInRange, ForStatement: function(node, reference) { @@ -115,7 +114,7 @@ var isInLoop = { * @returns {boolean} `true` if the node is dynamic. */ function hasDynamicExpressions(root) { - var retv = false, + let retv = false, traverser = new Traverser(); traverser.traverse(root, { @@ -143,9 +142,9 @@ function toLoopCondition(reference) { return null; } - var group = null; - var child = reference.identifier; - var node = child.parent; + let group = null; + let child = reference.identifier; + let node = child.parent; while (node) { if (SENTINEL_PATTERN.test(node.type)) { @@ -193,7 +192,7 @@ function toLoopCondition(reference) { * @returns {ASTNode|null} The function node or null. */ function getEncloseFunctionDeclaration(reference) { - var node = reference.identifier; + let node = reference.identifier; while (node) { if (node.type === "FunctionDeclaration") { @@ -214,13 +213,13 @@ function getEncloseFunctionDeclaration(reference) { * @returns {void} */ function updateModifiedFlag(conditions, modifiers) { - var funcNode, funcVar; + let funcNode, funcVar; - for (var i = 0; i < conditions.length; ++i) { - var condition = conditions[i]; + for (let i = 0; i < conditions.length; ++i) { + let condition = conditions[i]; - for (var j = 0; !condition.modified && j < modifiers.length; ++j) { - var modifier = modifiers[j], + for (let j = 0; !condition.modified && j < modifiers.length; ++j) { + let modifier = modifiers[j], inLoop; /* @@ -255,7 +254,7 @@ module.exports = { }, create: function(context) { - var groupMap = null; + let groupMap = null; /** * Reports a given condition info. @@ -264,7 +263,7 @@ module.exports = { * @returns {void} */ function report(condition) { - var node = condition.reference.identifier; + let node = condition.reference.identifier; context.report({ node: node, @@ -281,11 +280,11 @@ module.exports = { * @returns {void} */ function registerConditionsToGroup(conditions) { - for (var i = 0; i < conditions.length; ++i) { - var condition = conditions[i]; + for (let i = 0; i < conditions.length; ++i) { + let condition = conditions[i]; if (condition.group) { - var group = groupMap.get(condition.group); + let group = groupMap.get(condition.group); if (!group) { group = []; @@ -318,7 +317,7 @@ module.exports = { function checkReferences(variable) { // Gets references that exist in loop conditions. - var conditions = variable + let conditions = variable .references .map(toLoopCondition) .filter(Boolean); @@ -331,7 +330,7 @@ module.exports = { registerConditionsToGroup(conditions); // Check the conditions are modified. - var modifiers = variable.references.filter(isWriteReference); + let modifiers = variable.references.filter(isWriteReference); if (modifiers.length > 0) { updateModifiedFlag(conditions, modifiers); @@ -348,11 +347,11 @@ module.exports = { return { "Program:exit": function() { - var queue = [context.getScope()]; + let queue = [context.getScope()]; groupMap = new Map(); - var scope; + let scope; while ((scope = queue.pop())) { pushAll(queue, scope.childScopes); diff --git a/tools/eslint/lib/rules/no-unneeded-ternary.js b/tools/eslint/lib/rules/no-unneeded-ternary.js index 1c344a42e6..64c767ed0e 100644 --- a/tools/eslint/lib/rules/no-unneeded-ternary.js +++ b/tools/eslint/lib/rules/no-unneeded-ternary.js @@ -31,8 +31,8 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; - var defaultAssignment = options.defaultAssignment !== false; + let options = context.options[0] || {}; + let defaultAssignment = options.defaultAssignment !== false; /** * Test if the node is a boolean literal @@ -60,9 +60,9 @@ module.exports = { ConditionalExpression: function(node) { if (isBooleanLiteral(node.alternate) && isBooleanLiteral(node.consequent)) { - context.report(node, node.consequent.loc.start, "Unnecessary use of boolean literals in conditional expression"); + context.report(node, node.consequent.loc.start, "Unnecessary use of boolean literals in conditional expression."); } else if (!defaultAssignment && matchesDefaultAssignment(node)) { - context.report(node, node.consequent.loc.start, "Unnecessary use of conditional expression for default assignment"); + context.report(node, node.consequent.loc.start, "Unnecessary use of conditional expression for default assignment."); } } }; diff --git a/tools/eslint/lib/rules/no-unreachable.js b/tools/eslint/lib/rules/no-unreachable.js index c28a6d2f2f..d52b9f3517 100644 --- a/tools/eslint/lib/rules/no-unreachable.js +++ b/tools/eslint/lib/rules/no-unreachable.js @@ -26,6 +26,75 @@ function isUnreachable(segment) { return !segment.reachable; } +/** + * The class to distinguish consecutive unreachable statements. + */ +class ConsecutiveRange { + constructor(sourceCode) { + this.sourceCode = sourceCode; + this.startNode = null; + this.endNode = null; + } + + /** + * The location object of this range. + * @type {Object} + */ + get location() { + return { + start: this.startNode.loc.start, + end: this.endNode.loc.end + }; + } + + /** + * `true` if this range is empty. + * @type {boolean} + */ + get isEmpty() { + return !(this.startNode && this.endNode); + } + + /** + * Checks whether the given node is inside of this range. + * @param {ASTNode|Token} node - The node to check. + * @returns {boolean} `true` if the node is inside of this range. + */ + contains(node) { + return ( + node.range[0] >= this.startNode.range[0] && + node.range[1] <= this.endNode.range[1] + ); + } + + /** + * Checks whether the given node is consecutive to this range. + * @param {ASTNode} node - The node to check. + * @returns {boolean} `true` if the node is consecutive to this range. + */ + isConsecutive(node) { + return this.contains(this.sourceCode.getTokenBefore(node)); + } + + /** + * Merges the given node to this range. + * @param {ASTNode} node - The node to merge. + * @returns {void} + */ + merge(node) { + this.endNode = node; + } + + /** + * Resets this range by the given node or null. + * @param {ASTNode|null} node - The node to reset, or null. + * @returns {void} + */ + reset(node) { + this.startNode = this.endNode = node; + } +} + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -42,7 +111,9 @@ module.exports = { }, create: function(context) { - var currentCodePath = null; + let currentCodePath = null; + + const range = new ConsecutiveRange(context.getSourceCode()); /** * Reports a given node if it's unreachable. @@ -50,9 +121,42 @@ module.exports = { * @returns {void} */ function reportIfUnreachable(node) { - if (currentCodePath.currentSegments.every(isUnreachable)) { - context.report({message: "Unreachable code.", node: node}); + let nextNode = null; + + if (node && currentCodePath.currentSegments.every(isUnreachable)) { + + // Store this statement to distinguish consecutive statements. + if (range.isEmpty) { + range.reset(node); + return; + } + + // Skip if this statement is inside of the current range. + if (range.contains(node)) { + return; + } + + // Merge if this statement is consecutive to the current range. + if (range.isConsecutive(node)) { + range.merge(node); + return; + } + + nextNode = node; + } + + // Report the current range since this statement is reachable or is + // not consecutive to the current range. + if (!range.isEmpty) { + context.report({ + message: "Unreachable code.", + loc: range.location, + node: range.startNode + }); } + + // Update the current range. + range.reset(nextNode); } return { @@ -96,7 +200,11 @@ module.exports = { WithStatement: reportIfUnreachable, ExportNamedDeclaration: reportIfUnreachable, ExportDefaultDeclaration: reportIfUnreachable, - ExportAllDeclaration: reportIfUnreachable + ExportAllDeclaration: reportIfUnreachable, + + "Program:exit": function() { + reportIfUnreachable(); + } }; } }; diff --git a/tools/eslint/lib/rules/no-unsafe-finally.js b/tools/eslint/lib/rules/no-unsafe-finally.js index 8c3815459c..305cce28ad 100644 --- a/tools/eslint/lib/rules/no-unsafe-finally.js +++ b/tools/eslint/lib/rules/no-unsafe-finally.js @@ -9,9 +9,9 @@ // Helpers //------------------------------------------------------------------------------ -var SENTINEL_NODE_TYPE_RETURN_THROW = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/; -var SENTINEL_NODE_TYPE_BREAK = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement|SwitchStatement)$/; -var SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement)$/; +let SENTINEL_NODE_TYPE_RETURN_THROW = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/; +let SENTINEL_NODE_TYPE_BREAK = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement|SwitchStatement)$/; +let SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement)$/; //------------------------------------------------------------------------------ @@ -24,7 +24,9 @@ module.exports = { description: "disallow control flow statements in `finally` blocks", category: "Possible Errors", recommended: true - } + }, + + schema: [] }, create: function(context) { @@ -32,7 +34,7 @@ module.exports = { * Checks if the node is the finalizer of a TryStatement * * @param {ASTNode} node - node to check. - * @returns {Boolean} - true if the node is the finalizer of a TryStatement + * @returns {boolean} - true if the node is the finalizer of a TryStatement */ function isFinallyBlock(node) { return node.parent.type === "TryStatement" && node.parent.finalizer === node; @@ -42,12 +44,12 @@ module.exports = { * Climbs up the tree if the node is not a sentinel node * * @param {ASTNode} node - node to check. - * @param {String} label - label of the break or continue statement - * @returns {Boolean} - return whether the node is a finally block or a sentinel node + * @param {string} label - label of the break or continue statement + * @returns {boolean} - return whether the node is a finally block or a sentinel node */ function isInFinallyBlock(node, label) { - var labelInside = false; - var sentinelNodeType; + let labelInside = false; + let sentinelNodeType; if (node.type === "BreakStatement" && !node.label) { sentinelNodeType = SENTINEL_NODE_TYPE_BREAK; @@ -81,7 +83,7 @@ module.exports = { function check(node) { if (isInFinallyBlock(node, node.label)) { context.report({ - message: "Unsafe usage of " + node.type, + message: "Unsafe usage of " + node.type + ".", node: node, line: node.loc.line, column: node.loc.column diff --git a/tools/eslint/lib/rules/no-unused-expressions.js b/tools/eslint/lib/rules/no-unused-expressions.js index 9438268ab2..d2bdda70f2 100644 --- a/tools/eslint/lib/rules/no-unused-expressions.js +++ b/tools/eslint/lib/rules/no-unused-expressions.js @@ -33,7 +33,7 @@ module.exports = { }, create: function(context) { - var config = context.options[0] || {}, + let config = context.options[0] || {}, allowShortCircuit = config.allowShortCircuit || false, allowTernary = config.allowTernary || false; @@ -52,12 +52,12 @@ module.exports = { * @returns {a[]} the leading sequence of members in the given list that pass the given predicate */ function takeWhile(predicate, list) { - for (var i = 0, l = list.length; i < l; ++i) { + for (let i = 0; i < list.length; ++i) { if (!predicate(list[i])) { - break; + return list.slice(0, i); } } - return [].slice.call(list, 0, i); + return list.slice(); } /** @@ -74,7 +74,7 @@ module.exports = { * @returns {boolean} whether the given node is considered a directive in its current position */ function isDirective(node, ancestors) { - var parent = ancestors[ancestors.length - 1], + let parent = ancestors[ancestors.length - 1], grandparent = ancestors[ancestors.length - 2]; return (parent.type === "Program" || parent.type === "BlockStatement" && diff --git a/tools/eslint/lib/rules/no-unused-labels.js b/tools/eslint/lib/rules/no-unused-labels.js index 77713fc408..ec13c6168e 100644 --- a/tools/eslint/lib/rules/no-unused-labels.js +++ b/tools/eslint/lib/rules/no-unused-labels.js @@ -21,7 +21,7 @@ module.exports = { }, create: function(context) { - var scopeInfo = null; + let scopeInfo = null; /** * Adds a scope info to the stack. @@ -68,8 +68,8 @@ module.exports = { return; } - var label = node.label.name; - var info = scopeInfo; + let label = node.label.name; + let info = scopeInfo; while (info) { if (info.label === label) { diff --git a/tools/eslint/lib/rules/no-unused-vars.js b/tools/eslint/lib/rules/no-unused-vars.js index 39b7703c3c..951330de9b 100644 --- a/tools/eslint/lib/rules/no-unused-vars.js +++ b/tools/eslint/lib/rules/no-unused-vars.js @@ -9,8 +9,8 @@ // Requirements //------------------------------------------------------------------------------ -var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +let lodash = require("lodash"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -60,15 +60,15 @@ module.exports = { create: function(context) { - var MESSAGE = "'{{name}}' is defined but never used"; + let MESSAGE = "'{{name}}' is defined but never used."; - var config = { + let config = { vars: "all", args: "after-used", caughtErrors: "none" }; - var firstOption = context.options[0]; + let firstOption = context.options[0]; if (firstOption) { if (typeof firstOption === "string") { @@ -96,7 +96,7 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - var STATEMENT_TYPE = /(?:Statement|Declaration)$/; + let STATEMENT_TYPE = /(?:Statement|Declaration)$/; /** * Determines if a given variable is being exported from a module. @@ -106,11 +106,11 @@ module.exports = { */ function isExported(variable) { - var definition = variable.defs[0]; + let definition = variable.defs[0]; if (definition) { - var node = definition.node; + let node = definition.node; if (node.type === "VariableDeclarator") { node = node.parent; @@ -142,7 +142,7 @@ module.exports = { * @private */ function isSelfReference(ref, nodes) { - var scope = ref.from; + let scope = ref.from; while (scope) { if (nodes.indexOf(scope.block) >= 0) { @@ -156,11 +156,34 @@ module.exports = { } /** + * Checks whether a given node is inside of a loop or not. + * + * @param {ASTNode} node - A node to check. + * @returns {boolean} `true` if the node is inside of a loop. + * @private + */ + function isInsideOfLoop(node) { + while (node) { + if (astUtils.isLoop(node)) { + return true; + } + if (astUtils.isFunction(node)) { + return false; + } + + node = node.parent; + } + + return false; + } + + /** * Checks the position of given nodes. * * @param {ASTNode} inner - A node which is expected as inside. * @param {ASTNode} outer - A node which is expected as outside. * @returns {boolean} `true` if the `inner` node exists in the `outer` node. + * @private */ function isInside(inner, outer) { return ( @@ -173,17 +196,25 @@ module.exports = { * If a given reference is left-hand side of an assignment, this gets * the right-hand side node of the assignment. * + * In the following cases, this returns null. + * + * - The reference is not the LHS of an assignment expression. + * - The reference is inside of a loop. + * - The reference is inside of a function scope which is different from + * the declaration. + * * @param {escope.Reference} ref - A reference to check. * @param {ASTNode} prevRhsNode - The previous RHS node. - * @returns {ASTNode} The RHS node. + * @returns {ASTNode|null} The RHS node or null. + * @private */ function getRhsNode(ref, prevRhsNode) { - var id = ref.identifier; - var parent = id.parent; - var granpa = parent.parent; - var refScope = ref.from.variableScope; - var varScope = ref.resolved.scope.variableScope; - var canBeUsedLater = refScope !== varScope; + let id = ref.identifier; + let parent = id.parent; + let granpa = parent.parent; + let refScope = ref.from.variableScope; + let varScope = ref.resolved.scope.variableScope; + let canBeUsedLater = refScope !== varScope || isInsideOfLoop(id); /* * Inherits the previous node if this reference is in the node. @@ -213,10 +244,11 @@ module.exports = { * - the funcNode is assigned to a variable. * - the funcNode is bound as an argument of a function call. * - the function is bound to a property and the object satisfies above conditions. + * @private */ function isStorableFunction(funcNode, rhsNode) { - var node = funcNode; - var parent = funcNode.parent; + let node = funcNode; + let parent = funcNode.parent; while (parent && isInside(parent, rhsNode)) { switch (parent.type) { @@ -266,9 +298,10 @@ module.exports = { * @param {ASTNode} id - An Identifier node to check. * @param {ASTNode} rhsNode - The RHS node of the previous assignment. * @returns {boolean} `true` if the `id` node exists inside of a function node which can be used later. + * @private */ function isInsideOfStorableFunction(id, rhsNode) { - var funcNode = astUtils.getUpperFunction(id); + let funcNode = astUtils.getUpperFunction(id); return ( funcNode && @@ -283,11 +316,12 @@ module.exports = { * @param {escope.Reference} ref - A reference to check. * @param {ASTNode} rhsNode - The RHS node of the previous assignment. * @returns {boolean} The reference is a read to update itself. + * @private */ function isReadForItself(ref, rhsNode) { - var id = ref.identifier; - var parent = id.parent; - var granpa = parent.parent; + let id = ref.identifier; + let parent = id.parent; + let granpa = parent.parent; return ref.isRead() && ( @@ -319,7 +353,7 @@ module.exports = { * @private */ function isForInRef(ref) { - var target = ref.identifier.parent; + let target = ref.identifier.parent; // "for (var ...) { return; }" @@ -355,7 +389,7 @@ module.exports = { * @private */ function isUsedVariable(variable) { - var functionNodes = variable.defs.filter(function(def) { + let functionNodes = variable.defs.filter(function(def) { return def.type === "FunctionName"; }).map(function(def) { return def.node; @@ -368,7 +402,7 @@ module.exports = { return true; } - var forItself = isReadForItself(ref, rhsNode); + let forItself = isReadForItself(ref, rhsNode); rhsNode = getRhsNode(ref, rhsNode); @@ -388,13 +422,13 @@ module.exports = { * @private */ function collectUnusedVariables(scope, unusedVars) { - var variables = scope.variables; - var childScopes = scope.childScopes; - var i, l; + let variables = scope.variables; + let childScopes = scope.childScopes; + let i, l; if (scope.type !== "TDZ" && (scope.type !== "global" || config.vars === "all")) { for (i = 0, l = variables.length; i < l; ++i) { - var variable = variables[i]; + let variable = variables[i]; // skip a variable of class itself name in the class scope if (scope.type === "class" && scope.block.id === variable.identifiers[0]) { @@ -412,10 +446,10 @@ module.exports = { } // explicit global variables don't have definitions. - var def = variable.defs[0]; + let def = variable.defs[0]; if (def) { - var type = def.type; + let type = def.type; // skip catch variables if (type === "CatchClause") { @@ -480,13 +514,13 @@ module.exports = { * @private */ function getColumnInComment(variable, comment) { - var namePattern = new RegExp("[\\s,]" + lodash.escapeRegExp(variable.name) + "(?:$|[\\s,:])", "g"); + let namePattern = new RegExp("[\\s,]" + lodash.escapeRegExp(variable.name) + "(?:$|[\\s,:])", "g"); // To ignore the first text "global". namePattern.lastIndex = comment.value.indexOf("global") + 6; // Search a given variable name. - var match = namePattern.exec(comment.value); + let match = namePattern.exec(comment.value); return match ? match.index + 1 : 0; } @@ -500,11 +534,11 @@ module.exports = { * @private */ function getLocation(variable) { - var comment = variable.eslintExplicitGlobalComment; - var baseLoc = comment.loc.start; - var column = getColumnInComment(variable, comment); - var prefix = comment.value.slice(0, column); - var lineInComment = (prefix.match(/\n/g) || []).length; + let comment = variable.eslintExplicitGlobalComment; + let baseLoc = comment.loc.start; + let column = getColumnInComment(variable, comment); + let prefix = comment.value.slice(0, column); + let lineInComment = (prefix.match(/\n/g) || []).length; if (lineInComment > 0) { column -= 1 + prefix.lastIndexOf("\n"); @@ -526,10 +560,10 @@ module.exports = { return { "Program:exit": function(programNode) { - var unusedVars = collectUnusedVariables(context.getScope(), []); + let unusedVars = collectUnusedVariables(context.getScope(), []); - for (var i = 0, l = unusedVars.length; i < l; ++i) { - var unusedVar = unusedVars[i]; + for (let i = 0, l = unusedVars.length; i < l; ++i) { + let unusedVar = unusedVars[i]; if (unusedVar.eslintExplicitGlobal) { context.report({ diff --git a/tools/eslint/lib/rules/no-use-before-define.js b/tools/eslint/lib/rules/no-use-before-define.js index 889e709948..90dd05c8b1 100644 --- a/tools/eslint/lib/rules/no-use-before-define.js +++ b/tools/eslint/lib/rules/no-use-before-define.js @@ -9,17 +9,18 @@ // Helpers //------------------------------------------------------------------------------ -var SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/; +let SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/; +let FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/; /** * Parses a given value as options. * * @param {any} options - A value to parse. - * @returns {object} The parsed options. + * @returns {Object} The parsed options. */ function parseOptions(options) { - var functions = true; - var classes = true; + let functions = true; + let classes = true; if (typeof options === "string") { functions = (options !== "nofunc"); @@ -87,6 +88,14 @@ function isInRange(node, location) { /** * Checks whether or not a given reference is inside of the initializers of a given variable. * + * This returns `true` in the following cases: + * + * var a = a + * var [a = a] = list + * var {a = a} = obj + * for (var a in a) {} + * for (var a of a) {} + * * @param {Variable} variable - A variable to check. * @param {Reference} reference - A reference to check. * @returns {boolean} `true` if the reference is inside of the initializers. @@ -96,14 +105,19 @@ function isInInitializer(variable, reference) { return false; } - var node = variable.identifiers[0].parent; - var location = reference.identifier.range[1]; + let node = variable.identifiers[0].parent; + let location = reference.identifier.range[1]; while (node) { if (node.type === "VariableDeclarator") { if (isInRange(node.init, location)) { return true; } + if (FOR_IN_OF_TYPE.test(node.parent.parent.type) && + isInRange(node.parent.parent.right, location) + ) { + return true; + } break; } else if (node.type === "AssignmentPattern") { if (isInRange(node.right, location)) { @@ -151,10 +165,10 @@ module.exports = { }, create: function(context) { - var options = parseOptions(context.options[0]); + let options = parseOptions(context.options[0]); // Defines a function which checks whether or not a reference is allowed according to the option. - var isAllowed; + let isAllowed; if (options.functions && options.classes) { isAllowed = alwaysFalse; @@ -174,7 +188,7 @@ module.exports = { */ function findVariablesInScope(scope) { scope.references.forEach(function(reference) { - var variable = reference.resolved; + let variable = reference.resolved; // Skips when the reference is: // - initialization's. @@ -194,7 +208,7 @@ module.exports = { // Reports. context.report({ node: reference.identifier, - message: "'{{name}}' was used before it was defined", + message: "'{{name}}' was used before it was defined.", data: reference.identifier }); }); @@ -207,14 +221,14 @@ module.exports = { * @private */ function findVariables() { - var scope = context.getScope(); + let scope = context.getScope(); findVariablesInScope(scope); } - var ruleDefinition = { + let ruleDefinition = { "Program:exit": function(node) { - var scope = context.getScope(), + let scope = context.getScope(), ecmaFeatures = context.parserOptions.ecmaFeatures || {}; findVariablesInScope(scope); diff --git a/tools/eslint/lib/rules/no-useless-call.js b/tools/eslint/lib/rules/no-useless-call.js index 49cbbc5401..b05292ff79 100644 --- a/tools/eslint/lib/rules/no-useless-call.js +++ b/tools/eslint/lib/rules/no-useless-call.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -36,13 +36,13 @@ function isCallOrNonVariadicApply(node) { * @returns {boolean} the source code for the given node. */ function equalTokens(left, right, sourceCode) { - var tokensL = sourceCode.getTokens(left); - var tokensR = sourceCode.getTokens(right); + let tokensL = sourceCode.getTokens(left); + let tokensR = sourceCode.getTokens(right); if (tokensL.length !== tokensR.length) { return false; } - for (var i = 0; i < tokensL.length; ++i) { + for (let i = 0; i < tokensL.length; ++i) { if (tokensL[i].type !== tokensR[i].type || tokensL[i].value !== tokensR[i].value ) { @@ -83,7 +83,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { CallExpression: function(node) { @@ -91,9 +91,9 @@ module.exports = { return; } - var applied = node.callee.object; - var expectedThis = (applied.type === "MemberExpression") ? applied.object : null; - var thisArg = node.arguments[0]; + let applied = node.callee.object; + let expectedThis = (applied.type === "MemberExpression") ? applied.object : null; + let thisArg = node.arguments[0]; if (isValidThisArg(expectedThis, thisArg, sourceCode)) { context.report( diff --git a/tools/eslint/lib/rules/no-useless-computed-key.js b/tools/eslint/lib/rules/no-useless-computed-key.js index 2e0ac18019..f25b9e5474 100644 --- a/tools/eslint/lib/rules/no-useless-computed-key.js +++ b/tools/eslint/lib/rules/no-useless-computed-key.js @@ -8,7 +8,7 @@ // Rule Definition //------------------------------------------------------------------------------ -var MESSAGE_UNNECESSARY_COMPUTED = "Unnecessarily computed property [{{property}}] found."; +let MESSAGE_UNNECESSARY_COMPUTED = "Unnecessarily computed property [{{property}}] found."; module.exports = { meta: { @@ -16,10 +16,12 @@ module.exports = { description: "disallow unnecessary computed property keys in object literals", category: "ECMAScript 6", recommended: false - } + }, + + schema: [] }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { Property: function(node) { @@ -27,7 +29,7 @@ module.exports = { return; } - var key = node.key, + let key = node.key, nodeType = typeof key.value; if (key.type === "Literal" && (nodeType === "string" || nodeType === "number")) { diff --git a/tools/eslint/lib/rules/no-useless-concat.js b/tools/eslint/lib/rules/no-useless-concat.js index 8569d4276a..6c4cecd7b6 100644 --- a/tools/eslint/lib/rules/no-useless-concat.js +++ b/tools/eslint/lib/rules/no-useless-concat.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -29,7 +29,7 @@ function isConcatenation(node) { * @returns {ASTNode} node */ function getLeft(node) { - var left = node.left; + let left = node.left; while (isConcatenation(left)) { left = left.right; @@ -43,7 +43,7 @@ function getLeft(node) { * @returns {ASTNode} node */ function getRight(node) { - var right = node.right; + let right = node.right; while (isConcatenation(right)) { right = right.left; @@ -67,7 +67,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { BinaryExpression: function(node) { @@ -78,8 +78,8 @@ module.exports = { } // account for the `foo + "a" + "b"` case - var left = getLeft(node); - var right = getRight(node); + let left = getLeft(node); + let right = getRight(node); if (astUtils.isStringLiteral(left) && astUtils.isStringLiteral(right) && @@ -87,7 +87,7 @@ module.exports = { ) { // move warning location to operator - var operatorToken = sourceCode.getTokenAfter(left); + let operatorToken = sourceCode.getTokenAfter(left); while (operatorToken.value !== "+") { operatorToken = sourceCode.getTokenAfter(operatorToken); diff --git a/tools/eslint/lib/rules/no-useless-constructor.js b/tools/eslint/lib/rules/no-useless-constructor.js index b91ab4bcae..f6be08f69d 100644 --- a/tools/eslint/lib/rules/no-useless-constructor.js +++ b/tools/eslint/lib/rules/no-useless-constructor.js @@ -109,7 +109,7 @@ function isPassingThrough(ctorParams, superArgs) { return false; } - for (var i = 0; i < ctorParams.length; ++i) { + for (let i = 0; i < ctorParams.length; ++i) { if (!isValidPair(ctorParams[i], superArgs[i])) { return false; } @@ -163,9 +163,9 @@ module.exports = { return; } - var body = node.value.body.body; - var ctorParams = node.value.params; - var superClass = node.parent.parent.superClass; + let body = node.value.body.body; + let ctorParams = node.value.params; + let superClass = node.parent.parent.superClass; if (superClass ? isRedundantSuperCall(body, ctorParams) : (body.length === 0)) { context.report({ diff --git a/tools/eslint/lib/rules/no-useless-escape.js b/tools/eslint/lib/rules/no-useless-escape.js index 036831fc39..226a9da165 100644 --- a/tools/eslint/lib/rules/no-useless-escape.js +++ b/tools/eslint/lib/rules/no-useless-escape.js @@ -9,7 +9,7 @@ // Rule Definition //------------------------------------------------------------------------------ -var VALID_STRING_ESCAPES = [ +let VALID_STRING_ESCAPES = [ "\\", "n", "r", @@ -23,7 +23,7 @@ var VALID_STRING_ESCAPES = [ "\r" ]; -var VALID_REGEX_ESCAPES = [ +let VALID_REGEX_ESCAPES = [ "\\", ".", "-", @@ -80,8 +80,8 @@ module.exports = { * @returns {void} */ function validate(escapes, node, elm) { - var escapeNotFound = escapes.indexOf(elm[0][1]) === -1; - var isQuoteEscape = elm[0][1] === node.raw[0]; + let escapeNotFound = escapes.indexOf(elm[0][1]) === -1; + let isQuoteEscape = elm[0][1] === node.raw[0]; if (escapeNotFound && !isQuoteEscape) { context.report({ @@ -90,7 +90,7 @@ module.exports = { line: node.loc.start.line, column: node.loc.start.column + elm.index }, - message: "Unnecessary escape character: " + elm[0] + message: "Unnecessary escape character: " + elm[0] + "." }); } } @@ -102,8 +102,8 @@ module.exports = { * @returns {void} */ function check(node) { - var nodeEscapes, match; - var pattern = /\\[^\d]/g; + let nodeEscapes, match; + let pattern = /\\[^\d]/g; if (typeof node.value === "string") { diff --git a/tools/eslint/lib/rules/no-useless-rename.js b/tools/eslint/lib/rules/no-useless-rename.js index ec2282784b..80539e5772 100644 --- a/tools/eslint/lib/rules/no-useless-rename.js +++ b/tools/eslint/lib/rules/no-useless-rename.js @@ -31,7 +31,7 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}, + let options = context.options[0] || {}, ignoreDestructuring = options.ignoreDestructuring === true, ignoreImport = options.ignoreImport === true, ignoreExport = options.ignoreExport === true; @@ -49,7 +49,7 @@ module.exports = { * @returns {void} */ function reportError(node, initial, result, type) { - var name = initial.type === "Identifier" ? initial.name : initial.value; + let name = initial.type === "Identifier" ? initial.name : initial.value; return context.report({ node: node, @@ -73,7 +73,7 @@ module.exports = { * @returns {void} */ function checkDestructured(node) { - var properties, + let properties, i; if (ignoreDestructuring) { diff --git a/tools/eslint/lib/rules/no-var.js b/tools/eslint/lib/rules/no-var.js index 2e9948a330..fc7783d716 100644 --- a/tools/eslint/lib/rules/no-var.js +++ b/tools/eslint/lib/rules/no-var.js @@ -6,6 +6,72 @@ "use strict"; //------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +let SCOPE_NODE_TYPE = /^(?:Program|BlockStatement|SwitchStatement|ForStatement|ForInStatement|ForOfStatement)$/; + +/** + * Gets the scope node which directly contains a given node. + * + * @param {ASTNode} node - A node to get. This is a `VariableDeclaration` or + * an `Identifier`. + * @returns {ASTNode} A scope node. This is one of `Program`, `BlockStatement`, + * `SwitchStatement`, `ForStatement`, `ForInStatement`, and + * `ForOfStatement`. + */ +function getScopeNode(node) { + while (node) { + if (SCOPE_NODE_TYPE.test(node.type)) { + return node; + } + + node = node.parent; + } + + /* istanbul ignore next : unreachable */ + return null; +} + +/** + * Checks whether a given variable is redeclared or not. + * + * @param {escope.Variable} variable - A variable to check. + * @returns {boolean} `true` if the variable is redeclared. + */ +function isRedeclared(variable) { + return variable.defs.length >= 2; +} + +/** + * Checks whether a given variable is used from outside of the specified scope. + * + * @param {ASTNode} scopeNode - A scope node to check. + * @returns {Function} The predicate function which checks whether a given + * variable is used from outside of the specified scope. + */ +function isUsedFromOutsideOf(scopeNode) { + + /** + * Checks whether a given reference is inside of the specified scope or not. + * + * @param {escope.Reference} reference - A reference to check. + * @returns {boolean} `true` if the reference is inside of the specified + * scope. + */ + function isOutsideOfScope(reference) { + let scope = scopeNode.range; + let id = reference.identifier.range; + + return id[0] < scope[0] || id[1] > scope[1]; + } + + return function(variable) { + return variable.references.some(isOutsideOfScope); + }; +} + +//------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -17,19 +83,80 @@ module.exports = { recommended: false }, - schema: [] + schema: [], + fixable: "code" }, create: function(context) { + let sourceCode = context.getSourceCode(); + + /** + * Checks whether it can fix a given variable declaration or not. + * It cannot fix if the following cases: + * + * - A variable is declared on a SwitchCase node. + * - A variable is redeclared. + * - A variable is used from outside the scope. + * + * ## A variable is declared on a SwitchCase node. + * + * If this rule modifies 'var' declarations on a SwitchCase node, it + * would generate the warnings of 'no-case-declarations' rule. And the + * 'eslint:recommended' preset includes 'no-case-declarations' rule, so + * this rule doesn't modify those declarations. + * + * ## A variable is redeclared. + * + * The language spec disallows redeclarations of `let` declarations. + * Those variables would cause syntax errors. + * + * ## A variable is used from outside the scope. + * + * The language spec disallows accesses from outside of the scope for + * `let` declarations. Those variables would cause reference errors. + * + * @param {ASTNode} node - A variable declaration node to check. + * @returns {boolean} `true` if it can fix the node. + */ + function canFix(node) { + let variables = context.getDeclaredVariables(node); + let scopeNode = getScopeNode(node); + + return !( + node.parent.type === "SwitchCase" || + variables.some(isRedeclared) || + variables.some(isUsedFromOutsideOf(scopeNode)) + ); + } + + /** + * Reports a given variable declaration node. + * + * @param {ASTNode} node - A variable declaration node to report. + * @returns {void} + */ + function report(node) { + let varToken = sourceCode.getFirstToken(node); + + context.report({ + node: node, + message: "Unexpected var, use let or const instead.", + + fix: function(fixer) { + if (canFix(node)) { + return fixer.replaceText(varToken, "let"); + } + return null; + } + }); + } return { VariableDeclaration: function(node) { if (node.kind === "var") { - context.report(node, "Unexpected var, use let or const instead."); + report(node); } } - }; - } }; diff --git a/tools/eslint/lib/rules/no-warning-comments.js b/tools/eslint/lib/rules/no-warning-comments.js index dadf231f5c..7db6ed1234 100644 --- a/tools/eslint/lib/rules/no-warning-comments.js +++ b/tools/eslint/lib/rules/no-warning-comments.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -40,7 +40,7 @@ module.exports = { create: function(context) { - var configuration = context.options[0] || {}, + let configuration = context.options[0] || {}, warningTerms = configuration.terms || ["todo", "fixme", "xxx"], location = configuration.location || "start", selfConfigRegEx = /\bno-warning-comments\b/, @@ -51,11 +51,11 @@ module.exports = { * location ("start" or "anywhere"). If the term starts or ends with non word characters, then the match will not * require word boundaries on that side. * - * @param {String} term A term to convert to a RegExp + * @param {string} term A term to convert to a RegExp * @returns {RegExp} The term converted to a RegExp */ function convertToRegExp(term) { - var escaped = term.replace(/[-\/\\$\^*+?.()|\[\]{}]/g, "\\$&"), + let escaped = term.replace(/[-\/\\$\^*+?.()|\[\]{}]/g, "\\$&"), suffix, prefix; @@ -89,11 +89,11 @@ module.exports = { /** * Checks the specified comment for matches of the configured warning terms and returns the matches. - * @param {String} comment The comment which is checked. + * @param {string} comment The comment which is checked. * @returns {Array} All matched warning terms for this comment. */ function commentContainsWarningTerm(comment) { - var matches = []; + let matches = []; warningRegExps.forEach(function(regex, index) { if (regex.test(comment)) { @@ -114,7 +114,7 @@ module.exports = { return; } - var matches = commentContainsWarningTerm(node.value); + let matches = commentContainsWarningTerm(node.value); matches.forEach(function(matchedTerm) { context.report(node, "Unexpected '" + matchedTerm + "' comment."); diff --git a/tools/eslint/lib/rules/no-whitespace-before-property.js b/tools/eslint/lib/rules/no-whitespace-before-property.js index 347c63d934..fd13ba9d5d 100644 --- a/tools/eslint/lib/rules/no-whitespace-before-property.js +++ b/tools/eslint/lib/rules/no-whitespace-before-property.js @@ -4,7 +4,7 @@ */ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -23,7 +23,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -36,7 +36,7 @@ module.exports = { * @private */ function findOpeningBracket(node) { - var token = sourceCode.getTokenBefore(node.property); + let token = sourceCode.getTokenBefore(node.property); while (token.value !== "[") { token = sourceCode.getTokenBefore(token); @@ -53,7 +53,7 @@ module.exports = { * @private */ function reportError(node, leftToken, rightToken) { - var replacementText = node.computed ? "" : "."; + let replacementText = node.computed ? "" : "."; context.report({ node: node, @@ -73,8 +73,8 @@ module.exports = { return { MemberExpression: function(node) { - var rightToken; - var leftToken; + let rightToken; + let leftToken; if (!astUtils.isTokenOnSameLine(node.object, node.property)) { return; diff --git a/tools/eslint/lib/rules/object-curly-newline.js b/tools/eslint/lib/rules/object-curly-newline.js index aaa4af02a2..b69bd19044 100644 --- a/tools/eslint/lib/rules/object-curly-newline.js +++ b/tools/eslint/lib/rules/object-curly-newline.js @@ -9,14 +9,14 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ // Schema objects. -var OPTION_VALUE = { +let OPTION_VALUE = { oneOf: [ { enum: ["always", "never"] @@ -41,12 +41,12 @@ var OPTION_VALUE = { /** * Normalizes a given option value. * - * @param {string|object|undefined} value - An option value to parse. + * @param {string|Object|undefined} value - An option value to parse. * @returns {{multiline: boolean, minProperties: number}} Normalized option object. */ function normalizeOptionValue(value) { - var multiline = false; - var minProperties = Number.POSITIVE_INFINITY; + let multiline = false; + let minProperties = Number.POSITIVE_INFINITY; if (value) { if (value === "always") { @@ -67,7 +67,7 @@ function normalizeOptionValue(value) { /** * Normalizes a given option value. * - * @param {string|object|undefined} options - An option value to parse. + * @param {string|Object|undefined} options - An option value to parse. * @returns {{ObjectExpression: {multiline: boolean, minProperties: number}, ObjectPattern: {multiline: boolean, minProperties: number}}} Normalized option object. */ function normalizeOptions(options) { @@ -78,7 +78,7 @@ function normalizeOptions(options) { }; } - var value = normalizeOptionValue(options); + let value = normalizeOptionValue(options); return {ObjectExpression: value, ObjectPattern: value}; } @@ -114,8 +114,8 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); - var normalizedOptions = normalizeOptions(context.options[0]); + let sourceCode = context.getSourceCode(); + let normalizedOptions = normalizeOptions(context.options[0]); /** * Reports a given node if it violated this rule. @@ -125,12 +125,12 @@ module.exports = { * @returns {void} */ function check(node) { - var options = normalizedOptions[node.type]; - var openBrace = sourceCode.getFirstToken(node); - var closeBrace = sourceCode.getLastToken(node); - var first = sourceCode.getTokenOrCommentAfter(openBrace); - var last = sourceCode.getTokenOrCommentBefore(closeBrace); - var needsLinebreaks = ( + let options = normalizedOptions[node.type]; + let openBrace = sourceCode.getFirstToken(node); + let closeBrace = sourceCode.getLastToken(node); + let first = sourceCode.getTokenOrCommentAfter(openBrace); + let last = sourceCode.getTokenOrCommentBefore(closeBrace); + let needsLinebreaks = ( node.properties.length >= options.minProperties || ( options.multiline && @@ -153,7 +153,7 @@ module.exports = { if (needsLinebreaks) { if (astUtils.isTokenOnSameLine(openBrace, first)) { context.report({ - message: "Expected a line break after this open brace.", + message: "Expected a line break after this opening brace.", node: node, loc: openBrace.loc.start, fix: function(fixer) { @@ -163,7 +163,7 @@ module.exports = { } if (astUtils.isTokenOnSameLine(last, closeBrace)) { context.report({ - message: "Expected a line break before this close brace.", + message: "Expected a line break before this closing brace.", node: node, loc: closeBrace.loc.start, fix: function(fixer) { @@ -174,7 +174,7 @@ module.exports = { } else { if (!astUtils.isTokenOnSameLine(openBrace, first)) { context.report({ - message: "Unexpected a line break after this open brace.", + message: "Unexpected line break after this opening brace.", node: node, loc: openBrace.loc.start, fix: function(fixer) { @@ -187,7 +187,7 @@ module.exports = { } if (!astUtils.isTokenOnSameLine(last, closeBrace)) { context.report({ - message: "Unexpected a line break before this close brace.", + message: "Unexpected line break before this closing brace.", node: node, loc: closeBrace.loc.start, fix: function(fixer) { diff --git a/tools/eslint/lib/rules/object-curly-spacing.js b/tools/eslint/lib/rules/object-curly-spacing.js index e5dfb8d036..4fe1f85758 100644 --- a/tools/eslint/lib/rules/object-curly-spacing.js +++ b/tools/eslint/lib/rules/object-curly-spacing.js @@ -4,7 +4,7 @@ */ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -40,7 +40,7 @@ module.exports = { }, create: function(context) { - var spaced = context.options[0] === "always", + let spaced = context.options[0] === "always", sourceCode = context.getSourceCode(); /** @@ -54,7 +54,7 @@ module.exports = { return context.options[1] ? context.options[1][option] === !spaced : false; } - var options = { + let options = { spaced: spaced, arraysInObjectsException: isOptionSet("arraysInObjects"), objectsInObjectsException: isOptionSet("objectsInObjects") @@ -74,9 +74,9 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "There should be no space after '" + token.value + "'", + message: "There should be no space after '" + token.value + "'.", fix: function(fixer) { - var nextToken = context.getSourceCode().getTokenAfter(token); + let nextToken = context.getSourceCode().getTokenAfter(token); return fixer.removeRange([token.range[1], nextToken.range[0]]); } @@ -93,9 +93,9 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "There should be no space before '" + token.value + "'", + message: "There should be no space before '" + token.value + "'.", fix: function(fixer) { - var previousToken = context.getSourceCode().getTokenBefore(token); + let previousToken = context.getSourceCode().getTokenBefore(token); return fixer.removeRange([previousToken.range[1], token.range[0]]); } @@ -112,7 +112,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "A space is required after '" + token.value + "'", + message: "A space is required after '" + token.value + "'.", fix: function(fixer) { return fixer.insertTextAfter(token, " "); } @@ -129,7 +129,7 @@ module.exports = { context.report({ node: node, loc: token.loc.start, - message: "A space is required before '" + token.value + "'", + message: "A space is required before '" + token.value + "'.", fix: function(fixer) { return fixer.insertTextBefore(token, " "); } @@ -146,7 +146,7 @@ module.exports = { * @returns {void} */ function validateBraceSpacing(node, first, second, penultimate, last) { - var shouldCheckPenultimate, + let shouldCheckPenultimate, penultimateType, closingCurlyBraceMustBeSpaced, firstSpaced, @@ -195,7 +195,7 @@ module.exports = { return; } - var first = sourceCode.getFirstToken(node), + let first = sourceCode.getFirstToken(node), last = sourceCode.getLastToken(node), second = sourceCode.getTokenAfter(first), penultimate = sourceCode.getTokenBefore(last); @@ -213,7 +213,7 @@ module.exports = { return; } - var firstSpecifier = node.specifiers[0], + let firstSpecifier = node.specifiers[0], lastSpecifier = node.specifiers[node.specifiers.length - 1]; if (lastSpecifier.type !== "ImportSpecifier") { @@ -223,7 +223,7 @@ module.exports = { firstSpecifier = node.specifiers[1]; } - var first = sourceCode.getTokenBefore(firstSpecifier), + let first = sourceCode.getTokenBefore(firstSpecifier), last = sourceCode.getTokenAfter(lastSpecifier); // to support a trailing comma. @@ -231,7 +231,7 @@ module.exports = { last = sourceCode.getTokenAfter(last); } - var second = sourceCode.getTokenAfter(first), + let second = sourceCode.getTokenAfter(first), penultimate = sourceCode.getTokenBefore(last); validateBraceSpacing(node, first, second, penultimate, last); @@ -247,7 +247,7 @@ module.exports = { return; } - var firstSpecifier = node.specifiers[0], + let firstSpecifier = node.specifiers[0], lastSpecifier = node.specifiers[node.specifiers.length - 1], first = sourceCode.getTokenBefore(firstSpecifier), last = sourceCode.getTokenAfter(lastSpecifier); @@ -257,7 +257,7 @@ module.exports = { last = sourceCode.getTokenAfter(last); } - var second = sourceCode.getTokenAfter(first), + let second = sourceCode.getTokenAfter(first), penultimate = sourceCode.getTokenBefore(last); validateBraceSpacing(node, first, second, penultimate, last); diff --git a/tools/eslint/lib/rules/object-property-newline.js b/tools/eslint/lib/rules/object-property-newline.js index eb96152bb1..fef7b871b4 100644 --- a/tools/eslint/lib/rules/object-property-newline.js +++ b/tools/eslint/lib/rules/object-property-newline.js @@ -31,21 +31,21 @@ module.exports = { }, create: function(context) { - var allowSameLine = context.options[0] && Boolean(context.options[0].allowMultiplePropertiesPerLine); - var errorMessage = allowSameLine ? - "Object properties must go on a new line if they aren't all on the same line" : - "Object properties must go on a new line"; + let allowSameLine = context.options[0] && Boolean(context.options[0].allowMultiplePropertiesPerLine); + let errorMessage = allowSameLine ? + "Object properties must go on a new line if they aren't all on the same line." : + "Object properties must go on a new line."; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { ObjectExpression: function(node) { - var lastTokenOfPreviousProperty, firstTokenOfCurrentProperty; + let lastTokenOfPreviousProperty, firstTokenOfCurrentProperty; if (allowSameLine) { if (node.properties.length > 1) { - var firstTokenOfFirstProperty = sourceCode.getFirstToken(node.properties[0]); - var lastTokenOfLastProperty = sourceCode.getLastToken(node.properties[node.properties.length - 1]); + let firstTokenOfFirstProperty = sourceCode.getFirstToken(node.properties[0]); + let lastTokenOfLastProperty = sourceCode.getLastToken(node.properties[node.properties.length - 1]); if (firstTokenOfFirstProperty.loc.end.line === lastTokenOfLastProperty.loc.start.line) { @@ -55,7 +55,7 @@ module.exports = { } } - for (var i = 1; i < node.properties.length; i++) { + for (let i = 1; i < node.properties.length; i++) { lastTokenOfPreviousProperty = sourceCode.getLastToken(node.properties[i - 1]); firstTokenOfCurrentProperty = sourceCode.getFirstToken(node.properties[i]); diff --git a/tools/eslint/lib/rules/object-shorthand.js b/tools/eslint/lib/rules/object-shorthand.js index a528c00d38..1d08178d57 100644 --- a/tools/eslint/lib/rules/object-shorthand.js +++ b/tools/eslint/lib/rules/object-shorthand.js @@ -5,7 +5,7 @@ "use strict"; -var OPTIONS = { +let OPTIONS = { always: "always", never: "never", methods: "methods", @@ -83,14 +83,14 @@ module.exports = { }, create: function(context) { - var APPLY = context.options[0] || OPTIONS.always; - var APPLY_TO_METHODS = APPLY === OPTIONS.methods || APPLY === OPTIONS.always; - var APPLY_TO_PROPS = APPLY === OPTIONS.properties || APPLY === OPTIONS.always; - var APPLY_NEVER = APPLY === OPTIONS.never; + let APPLY = context.options[0] || OPTIONS.always; + let APPLY_TO_METHODS = APPLY === OPTIONS.methods || APPLY === OPTIONS.always; + let APPLY_TO_PROPS = APPLY === OPTIONS.properties || APPLY === OPTIONS.always; + let APPLY_NEVER = APPLY === OPTIONS.never; - var PARAMS = context.options[1] || {}; - var IGNORE_CONSTRUCTORS = PARAMS.ignoreConstructors; - var AVOID_QUOTES = PARAMS.avoidQuotes; + let PARAMS = context.options[1] || {}; + let IGNORE_CONSTRUCTORS = PARAMS.ignoreConstructors; + let AVOID_QUOTES = PARAMS.avoidQuotes; //-------------------------------------------------------------------------- // Helpers @@ -103,7 +103,7 @@ module.exports = { * @private */ function isConstructor(name) { - var firstChar = name.charAt(0); + let firstChar = name.charAt(0); return firstChar === firstChar.toUpperCase(); } @@ -123,7 +123,7 @@ module.exports = { return { Property: function(node) { - var isConciseProperty = node.method || node.shorthand, + let isConciseProperty = node.method || node.shorthand, type; // Ignore destructuring assignment diff --git a/tools/eslint/lib/rules/one-var-declaration-per-line.js b/tools/eslint/lib/rules/one-var-declaration-per-line.js index f4cdb84b18..e7a29fb115 100644 --- a/tools/eslint/lib/rules/one-var-declaration-per-line.js +++ b/tools/eslint/lib/rules/one-var-declaration-per-line.js @@ -25,8 +25,8 @@ module.exports = { create: function(context) { - var ERROR_MESSAGE = "Expected variable declaration to be on a new line."; - var always = context.options[0] === "always"; + let ERROR_MESSAGE = "Expected variable declaration to be on a new line."; + let always = context.options[0] === "always"; //-------------------------------------------------------------------------- // Helpers @@ -54,8 +54,8 @@ module.exports = { return; } - var declarations = node.declarations; - var prev; + let declarations = node.declarations; + let prev; declarations.forEach(function(current) { if (prev && prev.loc.end.line === current.loc.start.line) { diff --git a/tools/eslint/lib/rules/one-var.js b/tools/eslint/lib/rules/one-var.js index 2bd49f511f..10cdb626e5 100644 --- a/tools/eslint/lib/rules/one-var.js +++ b/tools/eslint/lib/rules/one-var.js @@ -57,12 +57,12 @@ module.exports = { create: function(context) { - var MODE_ALWAYS = "always", + let MODE_ALWAYS = "always", MODE_NEVER = "never"; - var mode = context.options[0] || MODE_ALWAYS; + let mode = context.options[0] || MODE_ALWAYS; - var options = { + let options = { }; if (typeof mode === "string") { // simple options configuration with just a string @@ -113,8 +113,8 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - var functionStack = []; - var blockStack = []; + let functionStack = []; + let blockStack = []; /** * Increments the blockStack counter. @@ -166,7 +166,7 @@ module.exports = { * @private */ function recordTypes(statementType, declarations, currentScope) { - for (var i = 0; i < declarations.length; i++) { + for (let i = 0; i < declarations.length; i++) { if (declarations[i].init === null) { if (options[statementType] && options[statementType].uninitialized === MODE_ALWAYS) { currentScope.uninitialized = true; @@ -185,7 +185,7 @@ module.exports = { * @returns {Object} The scope associated with statementType */ function getCurrentScope(statementType) { - var currentScope; + let currentScope; if (statementType === "var") { currentScope = functionStack[functionStack.length - 1]; @@ -204,9 +204,9 @@ module.exports = { * @private */ function countDeclarations(declarations) { - var counts = { uninitialized: 0, initialized: 0 }; + let counts = { uninitialized: 0, initialized: 0 }; - for (var i = 0; i < declarations.length; i++) { + for (let i = 0; i < declarations.length; i++) { if (declarations[i].init === null) { counts.uninitialized++; } else { @@ -225,9 +225,9 @@ module.exports = { */ function hasOnlyOneStatement(statementType, declarations) { - var declarationCounts = countDeclarations(declarations); - var currentOptions = options[statementType] || {}; - var currentScope = getCurrentScope(statementType); + let declarationCounts = countDeclarations(declarations); + let currentOptions = options[statementType] || {}; + let currentScope = getCurrentScope(statementType); if (currentOptions.uninitialized === MODE_ALWAYS && currentOptions.initialized === MODE_ALWAYS) { if (currentScope.uninitialized || currentScope.initialized) { @@ -266,7 +266,7 @@ module.exports = { SwitchStatement: startBlock, VariableDeclaration: function(node) { - var parent = node.parent, + let parent = node.parent, type, declarations, declarationCounts; type = node.kind; @@ -296,7 +296,7 @@ module.exports = { // never if (parent.type !== "ForStatement" || parent.init !== node) { - var totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized; + let totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized; if (totalDeclarations > 1) { diff --git a/tools/eslint/lib/rules/operator-assignment.js b/tools/eslint/lib/rules/operator-assignment.js index 7e60c9efd4..3088ff174f 100644 --- a/tools/eslint/lib/rules/operator-assignment.js +++ b/tools/eslint/lib/rules/operator-assignment.js @@ -93,7 +93,7 @@ module.exports = { * @returns {void} */ function verify(node) { - var expr, left, operator; + let expr, left, operator; if (node.operator !== "=" || node.right.type !== "BinaryExpression") { return; diff --git a/tools/eslint/lib/rules/operator-linebreak.js b/tools/eslint/lib/rules/operator-linebreak.js index 8f17155b86..2b2f1274aa 100644 --- a/tools/eslint/lib/rules/operator-linebreak.js +++ b/tools/eslint/lib/rules/operator-linebreak.js @@ -5,7 +5,7 @@ "use strict"; -var lodash = require("lodash"), +let lodash = require("lodash"), astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ @@ -44,10 +44,10 @@ module.exports = { create: function(context) { - var usedDefaultGlobal = !context.options[0]; - var globalStyle = context.options[0] || "after"; - var options = context.options[1] || {}; - var styleOverrides = options.overrides ? lodash.assign({}, options.overrides) : {}; + let usedDefaultGlobal = !context.options[0]; + let globalStyle = context.options[0] || "after"; + let options = context.options[1] || {}; + let styleOverrides = options.overrides ? lodash.assign({}, options.overrides) : {}; if (usedDefaultGlobal && !styleOverrides["?"]) { styleOverrides["?"] = "before"; @@ -57,7 +57,7 @@ module.exports = { styleOverrides[":"] = "before"; } - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -71,8 +71,8 @@ module.exports = { * @returns {void} */ function validateNode(node, leftSide) { - var leftToken = sourceCode.getLastToken(leftSide); - var operatorToken = sourceCode.getTokenAfter(leftToken); + let leftToken = sourceCode.getLastToken(leftSide); + let operatorToken = sourceCode.getTokenAfter(leftToken); // When the left part of a binary expression is a single expression wrapped in // parentheses (ex: `(a) + b`), leftToken will be the last token of the expression @@ -84,10 +84,10 @@ module.exports = { operatorToken = sourceCode.getTokenAfter(operatorToken); } - var rightToken = sourceCode.getTokenAfter(operatorToken); - var operator = operatorToken.value; - var operatorStyleOverride = styleOverrides[operator]; - var style = operatorStyleOverride || globalStyle; + let rightToken = sourceCode.getTokenAfter(operatorToken); + let operator = operatorToken.value; + let operatorStyleOverride = styleOverrides[operator]; + let style = operatorStyleOverride || globalStyle; // if single line if (astUtils.isTokenOnSameLine(leftToken, operatorToken) && @@ -123,7 +123,7 @@ module.exports = { context.report(node, { line: operatorToken.loc.end.line, column: operatorToken.loc.end.column - }, "There should be no line break before or after '" + operator + "'"); + }, "There should be no line break before or after '" + operator + "'."); } } diff --git a/tools/eslint/lib/rules/padded-blocks.js b/tools/eslint/lib/rules/padded-blocks.js index 7ec24c65d7..2754cda4de 100644 --- a/tools/eslint/lib/rules/padded-blocks.js +++ b/tools/eslint/lib/rules/padded-blocks.js @@ -47,8 +47,8 @@ module.exports = { }, create: function(context) { - var options = {}; - var config = context.options[0] || "always"; + let options = {}; + let config = context.options[0] || "always"; if (typeof config === "string") { options.blocks = config === "always"; @@ -64,10 +64,10 @@ module.exports = { } } - var ALWAYS_MESSAGE = "Block must be padded by blank lines.", + let ALWAYS_MESSAGE = "Block must be padded by blank lines.", NEVER_MESSAGE = "Block must not be padded by blank lines."; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Gets the open brace token from a given node. @@ -96,7 +96,7 @@ module.exports = { * @returns {boolean} Whether or not the token is followed by a blank line. */ function isTokenTopPadded(token) { - var tokenStartLine = token.loc.start.line, + let tokenStartLine = token.loc.start.line, expectedFirstLine = tokenStartLine + 2, first, firstLine; @@ -116,7 +116,7 @@ module.exports = { * @returns {boolean} Whether or not the token is preceeded by a blank line */ function isTokenBottomPadded(token) { - var blockEnd = token.loc.end.line, + let blockEnd = token.loc.end.line, expectedLastLine = blockEnd - 2, last, lastLine; @@ -156,7 +156,7 @@ module.exports = { * @returns {void} undefined. */ function checkPadding(node) { - var openBrace = getOpenBrace(node), + let openBrace = getOpenBrace(node), closeBrace = sourceCode.getLastToken(node), blockHasTopPadding = isTokenTopPadded(openBrace), blockHasBottomPadding = isTokenBottomPadded(closeBrace); @@ -184,7 +184,7 @@ module.exports = { } } else { if (blockHasTopPadding) { - var nextToken = sourceCode.getTokenOrCommentAfter(openBrace); + let nextToken = sourceCode.getTokenOrCommentAfter(openBrace); context.report({ node: node, @@ -197,7 +197,7 @@ module.exports = { } if (blockHasBottomPadding) { - var previousToken = sourceCode.getTokenOrCommentBefore(closeBrace); + let previousToken = sourceCode.getTokenOrCommentBefore(closeBrace); context.report({ node: node, @@ -211,7 +211,7 @@ module.exports = { } } - var rule = {}; + let rule = {}; if (options.hasOwnProperty("switches")) { rule.SwitchStatement = function(node) { diff --git a/tools/eslint/lib/rules/prefer-arrow-callback.js b/tools/eslint/lib/rules/prefer-arrow-callback.js index 4c4c2e6f2b..185bf16057 100644 --- a/tools/eslint/lib/rules/prefer-arrow-callback.js +++ b/tools/eslint/lib/rules/prefer-arrow-callback.js @@ -35,10 +35,10 @@ function checkMetaProperty(node, metaName, propertyName) { * @returns {escope.Variable} The found variable object. */ function getVariableOfArguments(scope) { - var variables = scope.variables; + let variables = scope.variables; - for (var i = 0; i < variables.length; ++i) { - var variable = variables[i]; + for (let i = 0; i < variables.length; ++i) { + let variable = variables[i]; if (variable.name === "arguments") { @@ -58,13 +58,13 @@ function getVariableOfArguments(scope) { /** * Checkes whether or not a given node is a callback. * @param {ASTNode} node - A node to check. - * @returns {object} + * @returns {Object} * {boolean} retv.isCallback - `true` if the node is a callback. * {boolean} retv.isLexicalThis - `true` if the node is with `.bind(this)`. */ function getCallbackInfo(node) { - var retv = {isCallback: false, isLexicalThis: false}; - var parent = node.parent; + let retv = {isCallback: false, isLexicalThis: false}; + let parent = node.parent; while (node) { switch (parent.type) { @@ -144,10 +144,10 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; + let options = context.options[0] || {}; - var allowUnboundThis = options.allowUnboundThis !== false; // default to true - var allowNamedFunctions = options.allowNamedFunctions; + let allowUnboundThis = options.allowUnboundThis !== false; // default to true + let allowNamedFunctions = options.allowNamedFunctions; /* * {Array<{this: boolean, super: boolean, meta: boolean}>} @@ -155,7 +155,7 @@ module.exports = { * - super - A flag which shows there are one or more Super. * - meta - A flag which shows there are one or more MethProperty. */ - var stack = []; + let stack = []; /** * Pushes new function scope with all `false` flags. @@ -182,7 +182,7 @@ module.exports = { // If there are below, it cannot replace with arrow functions merely. ThisExpression: function() { - var info = stack[stack.length - 1]; + let info = stack[stack.length - 1]; if (info) { info.this = true; @@ -190,7 +190,7 @@ module.exports = { }, Super: function() { - var info = stack[stack.length - 1]; + let info = stack[stack.length - 1]; if (info) { info.super = true; @@ -198,7 +198,7 @@ module.exports = { }, MetaProperty: function(node) { - var info = stack[stack.length - 1]; + let info = stack[stack.length - 1]; if (info && checkMetaProperty(node, "new", "target")) { info.meta = true; @@ -212,7 +212,7 @@ module.exports = { // Main. FunctionExpression: enterScope, "FunctionExpression:exit": function(node) { - var scopeInfo = exitScope(); + let scopeInfo = exitScope(); // Skip named function expressions if (allowNamedFunctions && node.id && node.id.name) { @@ -225,21 +225,21 @@ module.exports = { } // Skip recursive functions. - var nameVar = context.getDeclaredVariables(node)[0]; + let nameVar = context.getDeclaredVariables(node)[0]; if (isFunctionName(nameVar) && nameVar.references.length > 0) { return; } // Skip if it's using arguments. - var variable = getVariableOfArguments(context.getScope()); + let variable = getVariableOfArguments(context.getScope()); if (variable && variable.references.length > 0) { return; } // Reports if it's a callback which can replace with arrows. - var callbackInfo = getCallbackInfo(node); + let callbackInfo = getCallbackInfo(node); if (callbackInfo.isCallback && (!allowUnboundThis || !scopeInfo.this || callbackInfo.isLexicalThis) && diff --git a/tools/eslint/lib/rules/prefer-const.js b/tools/eslint/lib/rules/prefer-const.js index 7b8ac42519..5935e02b2c 100644 --- a/tools/eslint/lib/rules/prefer-const.js +++ b/tools/eslint/lib/rules/prefer-const.js @@ -9,16 +9,15 @@ // Requirements //------------------------------------------------------------------------------ -var Map = require("es6-map"); -var lodash = require("lodash"); +let lodash = require("lodash"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var PATTERN_TYPE = /^(?:.+?Pattern|RestElement|Property)$/; -var DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/; -var DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/; +let PATTERN_TYPE = /^(?:.+?Pattern|RestElement|Property)$/; +let DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/; +let DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/; /** * Adds multiple items to the tail of an array. @@ -27,7 +26,7 @@ var DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/; * @param {any[]} values - Items to be added. * @returns {void} */ -var pushAll = Function.apply.bind(Array.prototype.push); +let pushAll = Function.apply.bind(Array.prototype.push); /** * Checks whether a given node is located at `ForStatement.init` or not. @@ -46,7 +45,7 @@ function isInitOfForStatement(node) { * @returns {boolean} `true` if the node can become a VariableDeclaration. */ function canBecomeVariableDeclaration(identifier) { - var node = identifier.parent; + let node = identifier.parent; while (PATTERN_TYPE.test(node.type)) { node = node.parent; @@ -88,15 +87,15 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) { } // Finds the unique WriteReference. - var writer = null; - var isReadBeforeInit = false; - var references = variable.references; + let writer = null; + let isReadBeforeInit = false; + let references = variable.references; - for (var i = 0; i < references.length; ++i) { - var reference = references[i]; + for (let i = 0; i < references.length; ++i) { + let reference = references[i]; if (reference.isWrite()) { - var isReassigned = ( + let isReassigned = ( writer !== null && writer.identifier !== reference.identifier ); @@ -116,7 +115,7 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) { // If the assignment is from a different scope, ignore it. // If the assignment cannot change to a declaration, ignore it. - var shouldBeConst = ( + let shouldBeConst = ( writer !== null && writer.from === variable.scope && canBecomeVariableDeclaration(writer.identifier) @@ -145,7 +144,7 @@ function getDestructuringHost(reference) { if (!reference.isWrite()) { return null; } - var node = reference.identifier.parent; + let node = reference.identifier.parent; while (PATTERN_TYPE.test(node.type)) { node = node.parent; @@ -169,17 +168,17 @@ function getDestructuringHost(reference) { * @returns {Map<ASTNode, ASTNode[]>} Grouped identifier nodes. */ function groupByDestructuring(variables, ignoreReadBeforeAssign) { - var identifierMap = new Map(); + let identifierMap = new Map(); - for (var i = 0; i < variables.length; ++i) { - var variable = variables[i]; - var references = variable.references; - var identifier = getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign); - var prevId = null; + for (let i = 0; i < variables.length; ++i) { + let variable = variables[i]; + let references = variable.references; + let identifier = getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign); + let prevId = null; - for (var j = 0; j < references.length; ++j) { - var reference = references[j]; - var id = reference.identifier; + for (let j = 0; j < references.length; ++j) { + let reference = references[j]; + let id = reference.identifier; // Avoid counting a reference twice or more for default values of // destructuring. @@ -189,7 +188,7 @@ function groupByDestructuring(variables, ignoreReadBeforeAssign) { prevId = id; // Add the identifier node into the destructuring group. - var group = getDestructuringHost(reference); + let group = getDestructuringHost(reference); if (group) { if (identifierMap.has(group)) { @@ -209,7 +208,7 @@ function groupByDestructuring(variables, ignoreReadBeforeAssign) { * * @param {ASTNode} node – The node to search from. * @param {string} type – The type field of the parent node. - * @param {function} shouldStop – a predicate that returns true if the traversal should stop, and false otherwise. + * @param {Function} shouldStop – a predicate that returns true if the traversal should stop, and false otherwise. * @returns {ASTNode} The closest ancestor with the specified type; null if no such ancestor exists. */ function findUp(node, type, shouldStop) { @@ -249,10 +248,10 @@ module.exports = { }, create: function(context) { - var options = context.options[0] || {}; - var checkingMixedDestructuring = options.destructuring !== "all"; - var ignoreReadBeforeAssign = options.ignoreReadBeforeAssign === true; - var variables = null; + let options = context.options[0] || {}; + let checkingMixedDestructuring = options.destructuring !== "all"; + let ignoreReadBeforeAssign = options.ignoreReadBeforeAssign === true; + let variables = null; /** * Reports a given Identifier node. @@ -261,7 +260,7 @@ module.exports = { * @returns {void} */ function report(node) { - var reportArgs = { + let reportArgs = { node: node, message: "'{{name}}' is never reassigned. Use 'const' instead.", data: node @@ -318,7 +317,7 @@ module.exports = { * @returns {void} */ function checkVariable(variable) { - var node = getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign); + let node = getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign); if (node) { report(node); diff --git a/tools/eslint/lib/rules/prefer-reflect.js b/tools/eslint/lib/rules/prefer-reflect.js index 38bb093ba6..b2b0b9abda 100644 --- a/tools/eslint/lib/rules/prefer-reflect.js +++ b/tools/eslint/lib/rules/prefer-reflect.js @@ -45,7 +45,7 @@ module.exports = { }, create: function(context) { - var existingNames = { + let existingNames = { apply: "Function.prototype.apply", call: "Function.prototype.call", defineProperty: "Object.defineProperty", @@ -57,7 +57,7 @@ module.exports = { preventExtensions: "Object.preventExtensions" }; - var reflectSubsitutes = { + let reflectSubsitutes = { apply: "Reflect.apply", call: "Reflect.apply", defineProperty: "Reflect.defineProperty", @@ -69,7 +69,7 @@ module.exports = { preventExtensions: "Reflect.preventExtensions" }; - var exceptions = (context.options[0] || {}).exceptions || []; + let exceptions = (context.options[0] || {}).exceptions || []; /** * Reports the Reflect violation based on the `existing` and `substitute` @@ -79,7 +79,7 @@ module.exports = { * @returns {void} */ function report(node, existing, substitute) { - context.report(node, "Avoid using {{existing}}, instead use {{substitute}}", { + context.report(node, "Avoid using {{existing}}, instead use {{substitute}}.", { existing: existing, substitute: substitute }); @@ -87,19 +87,19 @@ module.exports = { return { CallExpression: function(node) { - var methodName = (node.callee.property || {}).name; - var isReflectCall = (node.callee.object || {}).name === "Reflect"; - var hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName); - var userConfiguredException = exceptions.indexOf(methodName) !== -1; + let methodName = (node.callee.property || {}).name; + let isReflectCall = (node.callee.object || {}).name === "Reflect"; + let hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName); + let userConfiguredException = exceptions.indexOf(methodName) !== -1; if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) { report(node, existingNames[methodName], reflectSubsitutes[methodName]); } }, UnaryExpression: function(node) { - var isDeleteOperator = node.operator === "delete"; - var targetsIdentifier = node.argument.type === "Identifier"; - var userConfiguredException = exceptions.indexOf("delete") !== -1; + let isDeleteOperator = node.operator === "delete"; + let targetsIdentifier = node.argument.type === "Identifier"; + let userConfiguredException = exceptions.indexOf("delete") !== -1; if (isDeleteOperator && !targetsIdentifier && !userConfiguredException) { report(node, "the delete keyword", "Reflect.deleteProperty"); diff --git a/tools/eslint/lib/rules/prefer-rest-params.js b/tools/eslint/lib/rules/prefer-rest-params.js index 0ce1d8a122..5a9164ed7f 100644 --- a/tools/eslint/lib/rules/prefer-rest-params.js +++ b/tools/eslint/lib/rules/prefer-rest-params.js @@ -15,10 +15,10 @@ * @returns {escope.Variable} The found variable object. */ function getVariableOfArguments(scope) { - var variables = scope.variables; + let variables = scope.variables; - for (var i = 0; i < variables.length; ++i) { - var variable = variables[i]; + for (let i = 0; i < variables.length; ++i) { + let variable = variables[i]; if (variable.name === "arguments") { @@ -68,7 +68,7 @@ module.exports = { * @returns {void} */ function checkForArguments() { - var argumentsVar = getVariableOfArguments(context.getScope()); + let argumentsVar = getVariableOfArguments(context.getScope()); if (argumentsVar) { argumentsVar.references.forEach(report); diff --git a/tools/eslint/lib/rules/prefer-spread.js b/tools/eslint/lib/rules/prefer-spread.js index 67f1e855b0..58fc85ca90 100644 --- a/tools/eslint/lib/rules/prefer-spread.js +++ b/tools/eslint/lib/rules/prefer-spread.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -35,13 +35,13 @@ function isVariadicApplyCalling(node) { * @returns {boolean} the source code for the given node. */ function equalTokens(left, right, sourceCode) { - var tokensL = sourceCode.getTokens(left); - var tokensR = sourceCode.getTokens(right); + let tokensL = sourceCode.getTokens(left); + let tokensR = sourceCode.getTokens(right); if (tokensL.length !== tokensR.length) { return false; } - for (var i = 0; i < tokensL.length; ++i) { + for (let i = 0; i < tokensL.length; ++i) { if (tokensL[i].type !== tokensR[i].type || tokensL[i].value !== tokensR[i].value ) { @@ -82,7 +82,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { CallExpression: function(node) { @@ -90,9 +90,9 @@ module.exports = { return; } - var applied = node.callee.object; - var expectedThis = (applied.type === "MemberExpression") ? applied.object : null; - var thisArg = node.arguments[0]; + let applied = node.callee.object; + let expectedThis = (applied.type === "MemberExpression") ? applied.object : null; + let thisArg = node.arguments[0]; if (isValidThisArg(expectedThis, thisArg, sourceCode)) { context.report(node, "use the spread operator instead of the '.apply()'."); diff --git a/tools/eslint/lib/rules/prefer-template.js b/tools/eslint/lib/rules/prefer-template.js index 0165aaecd6..4a0da8e197 100644 --- a/tools/eslint/lib/rules/prefer-template.js +++ b/tools/eslint/lib/rules/prefer-template.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -66,7 +66,7 @@ module.exports = { }, create: function(context) { - var done = Object.create(null); + let done = Object.create(null); /** * Reports if a given node is string concatenation with non string literals. @@ -79,7 +79,7 @@ module.exports = { return; } - var topBinaryExpr = getTopConcatBinaryExpression(node.parent); + let topBinaryExpr = getTopConcatBinaryExpression(node.parent); // Checks whether or not this node had been checked already. if (done[topBinaryExpr.range[0]]) { diff --git a/tools/eslint/lib/rules/quote-props.js b/tools/eslint/lib/rules/quote-props.js index 1fd2e74a5a..ec65647450 100644 --- a/tools/eslint/lib/rules/quote-props.js +++ b/tools/eslint/lib/rules/quote-props.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -var espree = require("espree"), +let espree = require("espree"), keywords = require("../util/keywords"); //------------------------------------------------------------------------------ @@ -66,7 +66,7 @@ module.exports = { create: function(context) { - var MODE = context.options[0], + let MODE = context.options[0], KEYWORDS = context.options[1] && context.options[1].keywords, CHECK_UNNECESSARY = !context.options[1] || context.options[1].unnecessary !== false, NUMBERS = context.options[1] && context.options[1].numbers, @@ -106,7 +106,7 @@ module.exports = { * @returns {void} */ function checkUnnecessaryQuotes(node) { - var key = node.key, + let key = node.key, isKeywordToken, tokens; @@ -147,7 +147,7 @@ module.exports = { * @returns {void} */ function checkOmittedQuotes(node) { - var key = node.key; + let key = node.key; if (!node.method && !node.computed && !node.shorthand && !(key.type === "Literal" && typeof key.value === "string")) { context.report(node, MESSAGE_UNQUOTED, { @@ -163,12 +163,12 @@ module.exports = { * @returns {void} */ function checkConsistency(node, checkQuotesRedundancy) { - var quotes = false, + let quotes = false, lackOfQuotes = false, necessaryQuotes = false; node.properties.forEach(function(property) { - var key = property.key, + let key = property.key, tokens; if (!key || property.method || property.computed || property.shorthand) { diff --git a/tools/eslint/lib/rules/quotes.js b/tools/eslint/lib/rules/quotes.js index d4e9203811..18635da537 100644 --- a/tools/eslint/lib/rules/quotes.js +++ b/tools/eslint/lib/rules/quotes.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ -var QUOTE_SETTINGS = { +let QUOTE_SETTINGS = { double: { quote: "\"", alternateQuote: "'", @@ -45,8 +45,8 @@ var QUOTE_SETTINGS = { QUOTE_SETTINGS.double.convert = QUOTE_SETTINGS.single.convert = QUOTE_SETTINGS.backtick.convert = function(str) { - var newQuote = this.quote; - var oldQuote = str[0]; + let newQuote = this.quote; + let oldQuote = str[0]; if (newQuote === oldQuote) { return str; @@ -65,8 +65,7 @@ QUOTE_SETTINGS.backtick.convert = function(str) { }) + newQuote; }; -var AVOID_ESCAPE = "avoid-escape", - FUNCTION_TYPE = /^(?:Arrow)?Function(?:Declaration|Expression)$/; +let AVOID_ESCAPE = "avoid-escape"; //------------------------------------------------------------------------------ // Rule Definition @@ -110,7 +109,7 @@ module.exports = { create: function(context) { - var quoteOption = context.options[0], + let quoteOption = context.options[0], settings = QUOTE_SETTINGS[quoteOption || "double"], options = context.options[1], avoidEscape = options && options.avoidEscape === true, @@ -155,15 +154,15 @@ module.exports = { * @private */ function isPartOfDirectivePrologue(node) { - var block = node.parent.parent; + let block = node.parent.parent; - if (block.type !== "Program" && (block.type !== "BlockStatement" || !FUNCTION_TYPE.test(block.parent.type))) { + if (block.type !== "Program" && (block.type !== "BlockStatement" || !astUtils.isFunction(block.parent))) { return false; } // Check the node is at a prologue. - for (var i = 0; i < block.body.length; ++i) { - var statement = block.body[i]; + for (let i = 0; i < block.body.length; ++i) { + let statement = block.body[i]; if (statement === node.parent) { return true; @@ -183,7 +182,7 @@ module.exports = { * @private */ function isAllowedAsNonBacktick(node) { - var parent = node.parent; + let parent = node.parent; switch (parent.type) { @@ -210,7 +209,7 @@ module.exports = { return { Literal: function(node) { - var val = node.value, + let val = node.value, rawVal = node.raw, isValid; @@ -242,7 +241,7 @@ module.exports = { return; } - var shouldWarn = node.quasis.length === 1 && (node.quasis[0].value.cooked.indexOf("\n") === -1); + let shouldWarn = node.quasis.length === 1 && (node.quasis[0].value.cooked.indexOf("\n") === -1); if (shouldWarn) { context.report({ diff --git a/tools/eslint/lib/rules/radix.js b/tools/eslint/lib/rules/radix.js index 05a1c130a9..4c9cb73beb 100644 --- a/tools/eslint/lib/rules/radix.js +++ b/tools/eslint/lib/rules/radix.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var MODE_ALWAYS = "always", +let MODE_ALWAYS = "always", MODE_AS_NEEDED = "as-needed"; /** @@ -92,7 +92,7 @@ module.exports = { }, create: function(context) { - var mode = context.options[0] || MODE_ALWAYS; + let mode = context.options[0] || MODE_ALWAYS; /** * Checks the arguments of a given CallExpression node and reports it if it @@ -102,7 +102,7 @@ module.exports = { * @returns {void} */ function checkArguments(node) { - var args = node.arguments; + let args = node.arguments; switch (args.length) { case 0: @@ -139,14 +139,14 @@ module.exports = { return { "Program:exit": function() { - var scope = context.getScope(); - var variable; + let scope = context.getScope(); + let variable; // Check `parseInt()` variable = astUtils.getVariableByName(scope, "parseInt"); if (!isShadowed(variable)) { variable.references.forEach(function(reference) { - var node = reference.identifier; + let node = reference.identifier; if (astUtils.isCallee(node)) { checkArguments(node.parent); @@ -158,7 +158,7 @@ module.exports = { variable = astUtils.getVariableByName(scope, "Number"); if (!isShadowed(variable)) { variable.references.forEach(function(reference) { - var node = reference.identifier.parent; + let node = reference.identifier.parent; if (isParseIntMethod(node) && astUtils.isCallee(node)) { checkArguments(node.parent); diff --git a/tools/eslint/lib/rules/require-jsdoc.js b/tools/eslint/lib/rules/require-jsdoc.js index 083e79b1f5..1503c0ff88 100644 --- a/tools/eslint/lib/rules/require-jsdoc.js +++ b/tools/eslint/lib/rules/require-jsdoc.js @@ -4,7 +4,7 @@ */ "use strict"; -var lodash = require("lodash"); +let lodash = require("lodash"); module.exports = { meta: { @@ -40,13 +40,13 @@ module.exports = { }, create: function(context) { - var source = context.getSourceCode(); - var DEFAULT_OPTIONS = { + let source = context.getSourceCode(); + let DEFAULT_OPTIONS = { FunctionDeclaration: true, MethodDefinition: false, ClassDeclaration: false }; - var options = lodash.assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {}); + let options = lodash.assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {}); /** * Report the error message @@ -64,7 +64,7 @@ module.exports = { */ function checkClassMethodJsDoc(node) { if (node.parent.type === "MethodDefinition") { - var jsdocComment = source.getJSDocComment(node); + let jsdocComment = source.getJSDocComment(node); if (!jsdocComment) { report(node); @@ -78,7 +78,7 @@ module.exports = { * @returns {void} */ function checkJsDoc(node) { - var jsdocComment = source.getJSDocComment(node); + let jsdocComment = source.getJSDocComment(node); if (!jsdocComment) { report(node); diff --git a/tools/eslint/lib/rules/require-yield.js b/tools/eslint/lib/rules/require-yield.js index cde7d8c2c4..a4bb292b7a 100644 --- a/tools/eslint/lib/rules/require-yield.js +++ b/tools/eslint/lib/rules/require-yield.js @@ -21,7 +21,7 @@ module.exports = { }, create: function(context) { - var stack = []; + let stack = []; /** * If the node is a generator function, start counting `yield` keywords. @@ -45,7 +45,7 @@ module.exports = { return; } - var countYield = stack.pop(); + let countYield = stack.pop(); if (countYield === 0 && node.body.body.length > 0) { context.report( diff --git a/tools/eslint/lib/rules/rest-spread-spacing.js b/tools/eslint/lib/rules/rest-spread-spacing.js index 7ffafa5319..3be2a43421 100644 --- a/tools/eslint/lib/rules/rest-spread-spacing.js +++ b/tools/eslint/lib/rules/rest-spread-spacing.js @@ -25,7 +25,7 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(), + let sourceCode = context.getSourceCode(), alwaysSpace = context.options[0] === "always"; //-------------------------------------------------------------------------- @@ -38,7 +38,7 @@ module.exports = { * @returns {void} */ function checkWhiteSpace(node) { - var operator = sourceCode.getFirstToken(node), + let operator = sourceCode.getFirstToken(node), nextToken = sourceCode.getTokenAfter(operator), hasWhitespace = sourceCode.isSpaceBetweenTokens(operator, nextToken), type; @@ -67,7 +67,7 @@ module.exports = { line: operator.loc.end.line, column: operator.loc.end.column }, - message: "Expected whitespace after {{type}} operator", + message: "Expected whitespace after {{type}} operator.", data: { type: type }, @@ -82,7 +82,7 @@ module.exports = { line: operator.loc.end.line, column: operator.loc.end.column }, - message: "Unexpected whitespace after {{type}} operator", + message: "Unexpected whitespace after {{type}} operator.", data: { type: type }, diff --git a/tools/eslint/lib/rules/semi-spacing.js b/tools/eslint/lib/rules/semi-spacing.js index 830044d2f3..261905f96f 100644 --- a/tools/eslint/lib/rules/semi-spacing.js +++ b/tools/eslint/lib/rules/semi-spacing.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -39,7 +39,7 @@ module.exports = { create: function(context) { - var config = context.options[0], + let config = context.options[0], requireSpaceBefore = false, requireSpaceAfter = true, sourceCode = context.getSourceCode(); @@ -59,7 +59,7 @@ module.exports = { * @returns {boolean} True if the given token has leading space, false if not. */ function hasLeadingSpace(token) { - var tokenBefore = sourceCode.getTokenBefore(token); + let tokenBefore = sourceCode.getTokenBefore(token); return tokenBefore && astUtils.isTokenOnSameLine(tokenBefore, token) && sourceCode.isSpaceBetweenTokens(tokenBefore, token); } @@ -70,7 +70,7 @@ module.exports = { * @returns {boolean} True if the given token has trailing space, false if not. */ function hasTrailingSpace(token) { - var tokenAfter = sourceCode.getTokenAfter(token); + let tokenAfter = sourceCode.getTokenAfter(token); return tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter) && sourceCode.isSpaceBetweenTokens(token, tokenAfter); } @@ -81,7 +81,7 @@ module.exports = { * @returns {boolean} Whether or not the token is the last in its line. */ function isLastTokenInCurrentLine(token) { - var tokenAfter = sourceCode.getTokenAfter(token); + let tokenAfter = sourceCode.getTokenAfter(token); return !(tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter)); } @@ -92,7 +92,7 @@ module.exports = { * @returns {boolean} Whether or not the token is the first in its line. */ function isFirstTokenInCurrentLine(token) { - var tokenBefore = sourceCode.getTokenBefore(token); + let tokenBefore = sourceCode.getTokenBefore(token); return !(tokenBefore && astUtils.isTokenOnSameLine(token, tokenBefore)); } @@ -103,7 +103,7 @@ module.exports = { * @returns {boolean} Whether or not the next token of a given token is a closing parenthesis. */ function isBeforeClosingParen(token) { - var nextToken = sourceCode.getTokenAfter(token); + let nextToken = sourceCode.getTokenAfter(token); return ( nextToken && @@ -128,7 +128,7 @@ module.exports = { * @returns {void} */ function checkSemicolonSpacing(token, node) { - var location; + let location; if (isSemicolon(token)) { location = token.loc.start; @@ -140,7 +140,7 @@ module.exports = { loc: location, message: "Unexpected whitespace before semicolon.", fix: function(fixer) { - var tokenBefore = sourceCode.getTokenBefore(token); + let tokenBefore = sourceCode.getTokenBefore(token); return fixer.removeRange([tokenBefore.range[1], token.range[0]]); } @@ -167,7 +167,7 @@ module.exports = { loc: location, message: "Unexpected whitespace after semicolon.", fix: function(fixer) { - var tokenAfter = sourceCode.getTokenAfter(token); + let tokenAfter = sourceCode.getTokenAfter(token); return fixer.removeRange([token.range[1], tokenAfter.range[0]]); } @@ -195,7 +195,7 @@ module.exports = { * @returns {void} */ function checkNode(node) { - var token = sourceCode.getLastToken(node); + let token = sourceCode.getLastToken(node); checkSemicolonSpacing(token, node); } diff --git a/tools/eslint/lib/rules/semi.js b/tools/eslint/lib/rules/semi.js index d530725040..80b1e9d002 100644 --- a/tools/eslint/lib/rules/semi.js +++ b/tools/eslint/lib/rules/semi.js @@ -53,9 +53,9 @@ module.exports = { create: function(context) { - var OPT_OUT_PATTERN = /[\[\(\/\+\-]/; // One of [(/+- - var options = context.options[1]; - var never = context.options[0] === "never", + let OPT_OUT_PATTERN = /[\[\(\/\+\-]/; // One of [(/+- + let options = context.options[1]; + let never = context.options[0] === "never", exceptOneLine = options && options.omitLastInOneLineBlock === true, sourceCode = context.getSourceCode(); @@ -70,7 +70,7 @@ module.exports = { * @returns {void} */ function report(node, missing) { - var message, + let message, fix, lastToken = sourceCode.getLastToken(node), loc = lastToken.loc; @@ -115,7 +115,7 @@ module.exports = { * @returns {boolean} whether the semicolon is unnecessary. */ function isUnnecessarySemicolon(lastToken) { - var isDivider, isOptOutToken, lastTokenLine, nextToken, nextTokenLine; + let isDivider, isOptOutToken, lastTokenLine, nextToken, nextTokenLine; if (!isSemicolon(lastToken)) { return false; @@ -141,13 +141,13 @@ module.exports = { * @returns {boolean} whether the node is in a one-liner block statement. */ function isOneLinerBlock(node) { - var nextToken = sourceCode.getTokenAfter(node); + let nextToken = sourceCode.getTokenAfter(node); if (!nextToken || nextToken.value !== "}") { return false; } - var parent = node.parent; + let parent = node.parent; return parent && parent.type === "BlockStatement" && parent.loc.start.line === parent.loc.end.line; @@ -159,7 +159,7 @@ module.exports = { * @returns {void} */ function checkForSemicolon(node) { - var lastToken = sourceCode.getLastToken(node); + let lastToken = sourceCode.getLastToken(node); if (never) { if (isUnnecessarySemicolon(lastToken)) { @@ -184,7 +184,7 @@ module.exports = { * @returns {void} */ function checkForSemicolonForVariableDeclaration(node) { - var ancestors = context.getAncestors(), + let ancestors = context.getAncestors(), parentIndex = ancestors.length - 1, parent = ancestors[parentIndex]; diff --git a/tools/eslint/lib/rules/sort-imports.js b/tools/eslint/lib/rules/sort-imports.js index 18b34f86a0..c8d3340b0c 100644 --- a/tools/eslint/lib/rules/sort-imports.js +++ b/tools/eslint/lib/rules/sort-imports.js @@ -44,7 +44,7 @@ module.exports = { create: function(context) { - var configuration = context.options[0] || {}, + let configuration = context.options[0] || {}, ignoreCase = configuration.ignoreCase || false, ignoreMemberSort = configuration.ignoreMemberSort || false, memberSyntaxSortOrder = configuration.memberSyntaxSortOrder || ["none", "all", "multiple", "single"], @@ -98,7 +98,7 @@ module.exports = { return { ImportDeclaration: function(node) { if (previousDeclaration) { - var currentLocalMemberName = getFirstLocalMemberName(node), + let currentLocalMemberName = getFirstLocalMemberName(node), currentMemberSyntaxGroupIndex = getMemberParameterGroupIndex(node), previousLocalMemberName = getFirstLocalMemberName(previousDeclaration), previousMemberSyntaxGroupIndex = getMemberParameterGroupIndex(previousDeclaration); @@ -137,17 +137,17 @@ module.exports = { // Multiple members of an import declaration should also be sorted alphabetically. if (!ignoreMemberSort && node.specifiers.length > 1) { - var previousSpecifier = null; - var previousSpecifierName = null; + let previousSpecifier = null; + let previousSpecifierName = null; - for (var i = 0; i < node.specifiers.length; ++i) { - var currentSpecifier = node.specifiers[i]; + for (let i = 0; i < node.specifiers.length; ++i) { + let currentSpecifier = node.specifiers[i]; if (currentSpecifier.type !== "ImportSpecifier") { continue; } - var currentSpecifierName = currentSpecifier.local.name; + let currentSpecifierName = currentSpecifier.local.name; if (ignoreCase) { currentSpecifierName = currentSpecifierName.toLowerCase(); diff --git a/tools/eslint/lib/rules/sort-vars.js b/tools/eslint/lib/rules/sort-vars.js index 8a7b0e710a..4b8187f36a 100644 --- a/tools/eslint/lib/rules/sort-vars.js +++ b/tools/eslint/lib/rules/sort-vars.js @@ -32,7 +32,7 @@ module.exports = { create: function(context) { - var configuration = context.options[0] || {}, + let configuration = context.options[0] || {}, ignoreCase = configuration.ignoreCase || false; return { @@ -42,7 +42,7 @@ module.exports = { return memo; } - var lastVariableName = memo.id.name, + let lastVariableName = memo.id.name, currenVariableName = decl.id.name; if (ignoreCase) { @@ -51,7 +51,7 @@ module.exports = { } if (currenVariableName < lastVariableName) { - context.report(decl, "Variables within the same declaration block should be sorted alphabetically"); + context.report(decl, "Variables within the same declaration block should be sorted alphabetically."); return memo; } else { return decl; diff --git a/tools/eslint/lib/rules/space-before-blocks.js b/tools/eslint/lib/rules/space-before-blocks.js index 468b320447..b695e7ac12 100644 --- a/tools/eslint/lib/rules/space-before-blocks.js +++ b/tools/eslint/lib/rules/space-before-blocks.js @@ -5,7 +5,7 @@ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -48,7 +48,7 @@ module.exports = { }, create: function(context) { - var config = context.options[0], + let config = context.options[0], sourceCode = context.getSourceCode(), checkFunctions = true, checkKeywords = true, @@ -81,7 +81,7 @@ module.exports = { * @returns {void} undefined. */ function checkPrecedingSpace(node) { - var precedingToken = sourceCode.getTokenBefore(node), + let precedingToken = sourceCode.getTokenBefore(node), hasSpace, parent, requireSpace; @@ -127,7 +127,7 @@ module.exports = { * @returns {void} undefined. */ function checkSpaceBeforeCaseBlock(node) { - var cases = node.cases, + let cases = node.cases, firstCase, openingBrace; diff --git a/tools/eslint/lib/rules/space-before-function-paren.js b/tools/eslint/lib/rules/space-before-function-paren.js index 2d26e41e4a..b43d11ed13 100644 --- a/tools/eslint/lib/rules/space-before-function-paren.js +++ b/tools/eslint/lib/rules/space-before-function-paren.js @@ -43,7 +43,7 @@ module.exports = { create: function(context) { - var configuration = context.options[0], + let configuration = context.options[0], sourceCode = context.getSourceCode(), requireAnonymousFunctionSpacing = true, forbidAnonymousFunctionSpacing = false, @@ -70,7 +70,7 @@ module.exports = { * @returns {boolean} Whether the function has a name. */ function isNamedFunction(node) { - var parent; + let parent; if (node.id) { return true; @@ -93,7 +93,7 @@ module.exports = { * @returns {void} */ function validateSpacingBeforeParentheses(node) { - var isNamed = isNamedFunction(node), + let isNamed = isNamedFunction(node), leftToken, rightToken, location; diff --git a/tools/eslint/lib/rules/space-in-parens.js b/tools/eslint/lib/rules/space-in-parens.js index 11361aec12..bd8c6eb3af 100644 --- a/tools/eslint/lib/rules/space-in-parens.js +++ b/tools/eslint/lib/rules/space-in-parens.js @@ -4,7 +4,7 @@ */ "use strict"; -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -42,7 +42,7 @@ module.exports = { create: function(context) { - var MISSING_SPACE_MESSAGE = "There must be a space inside this paren.", + let MISSING_SPACE_MESSAGE = "There must be a space inside this paren.", REJECTED_SPACE_MESSAGE = "There should be no spaces inside this paren.", ALWAYS = context.options[0] === "always", @@ -64,7 +64,7 @@ module.exports = { * @private */ function getExceptions() { - var openers = [], + let openers = [], closers = []; if (options.braceException) { @@ -96,7 +96,7 @@ module.exports = { //-------------------------------------------------------------------------- // Helpers //-------------------------------------------------------------------------- - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Determines if a token is one of the exceptions for the opener paren @@ -217,7 +217,7 @@ module.exports = { return { Program: function checkParenSpaces(node) { - var tokens, prevToken, nextToken; + let tokens, prevToken, nextToken; exceptions = getExceptions(); tokens = sourceCode.tokensAndComments; diff --git a/tools/eslint/lib/rules/space-infix-ops.js b/tools/eslint/lib/rules/space-infix-ops.js index bea82ba0b6..9f5b08773a 100644 --- a/tools/eslint/lib/rules/space-infix-ops.js +++ b/tools/eslint/lib/rules/space-infix-ops.js @@ -32,29 +32,29 @@ module.exports = { }, create: function(context) { - var int32Hint = context.options[0] ? context.options[0].int32Hint === true : false; + let int32Hint = context.options[0] ? context.options[0].int32Hint === true : false; - var OPERATORS = [ + let OPERATORS = [ "*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in", "instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=", "?", ":", ",", "**" ]; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Returns the first token which violates the rule * @param {ASTNode} left - The left node of the main node * @param {ASTNode} right - The right node of the main node - * @returns {object} The violator token or null + * @returns {Object} The violator token or null * @private */ function getFirstNonSpacedToken(left, right) { - var op, + let op, tokens = sourceCode.getTokensBetween(left, right, 1); - for (var i = 1, l = tokens.length - 1; i < l; ++i) { + for (let i = 1, l = tokens.length - 1; i < l; ++i) { op = tokens[i]; if ( op.type === "Punctuator" && @@ -70,7 +70,7 @@ module.exports = { /** * Reports an AST node as a rule violation * @param {ASTNode} mainNode - The node to report - * @param {object} culpritToken - The token which has a problem + * @param {Object} culpritToken - The token which has a problem * @returns {void} * @private */ @@ -80,9 +80,9 @@ module.exports = { loc: culpritToken.loc.start, message: "Infix operators must be spaced.", fix: function(fixer) { - var previousToken = sourceCode.getTokenBefore(culpritToken); - var afterToken = sourceCode.getTokenAfter(culpritToken); - var fixString = ""; + let previousToken = sourceCode.getTokenBefore(culpritToken); + let afterToken = sourceCode.getTokenAfter(culpritToken); + let fixString = ""; if (culpritToken.range[0] - previousToken.range[1] === 0) { fixString = " "; @@ -106,7 +106,11 @@ module.exports = { * @private */ function checkBinary(node) { - var nonSpacedNode = getFirstNonSpacedToken(node.left, node.right); + if (node.left.typeAnnotation) { + return; + } + + let nonSpacedNode = getFirstNonSpacedToken(node.left, node.right); if (nonSpacedNode) { if (!(int32Hint && sourceCode.getText(node).substr(-2) === "|0")) { @@ -122,8 +126,8 @@ module.exports = { * @private */ function checkConditional(node) { - var nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent); - var nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate); + let nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent); + let nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate); if (nonSpacedConsequesntNode) { report(node, nonSpacedConsequesntNode); @@ -139,7 +143,7 @@ module.exports = { * @private */ function checkVar(node) { - var nonSpacedNode; + let nonSpacedNode; if (node.init) { nonSpacedNode = getFirstNonSpacedToken(node.id, node.init); diff --git a/tools/eslint/lib/rules/space-unary-ops.js b/tools/eslint/lib/rules/space-unary-ops.js index fdb1c03e98..77a98150b8 100644 --- a/tools/eslint/lib/rules/space-unary-ops.js +++ b/tools/eslint/lib/rules/space-unary-ops.js @@ -41,9 +41,9 @@ module.exports = { }, create: function(context) { - var options = context.options && Array.isArray(context.options) && context.options[0] || { words: true, nonwords: false }; + let options = context.options && Array.isArray(context.options) && context.options[0] || { words: true, nonwords: false }; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -91,8 +91,8 @@ module.exports = { /** * Verify Unary Word Operator has spaces after the word operator * @param {ASTnode} node AST node - * @param {object} firstToken first token from the AST node - * @param {object} secondToken second token from the AST node + * @param {Object} firstToken first token from the AST node + * @param {Object} secondToken second token from the AST node * @param {string} word The word to be used for reporting * @returns {void} */ @@ -111,8 +111,8 @@ module.exports = { /** * Verify Unary Word Operator doesn't have spaces after the word operator * @param {ASTnode} node AST node - * @param {object} firstToken first token from the AST node - * @param {object} secondToken second token from the AST node + * @param {Object} firstToken first token from the AST node + * @param {Object} secondToken second token from the AST node * @param {string} word The word to be used for reporting * @returns {void} */ @@ -133,8 +133,8 @@ module.exports = { /** * Check Unary Word Operators for spaces after the word operator * @param {ASTnode} node AST node - * @param {object} firstToken first token from the AST node - * @param {object} secondToken second token from the AST node + * @param {Object} firstToken first token from the AST node + * @param {Object} secondToken second token from the AST node * @param {string} word The word to be used for reporting * @returns {void} */ @@ -160,7 +160,7 @@ module.exports = { * @returns {void} */ function checkForSpacesAfterYield(node) { - var tokens = sourceCode.getFirstTokens(node, 3), + let tokens = sourceCode.getFirstTokens(node, 3), word = "yield"; if (!node.argument || node.delegate) { @@ -173,8 +173,8 @@ module.exports = { /** * Verifies UnaryExpression, UpdateExpression and NewExpression have spaces before or after the operator * @param {ASTnode} node AST node - * @param {object} firstToken First token in the expression - * @param {object} secondToken Second token in the expression + * @param {Object} firstToken First token in the expression + * @param {Object} secondToken Second token in the expression * @returns {void} */ function verifyNonWordsHaveSpaces(node, firstToken, secondToken) { @@ -207,8 +207,8 @@ module.exports = { /** * Verifies UnaryExpression, UpdateExpression and NewExpression don't have spaces before or after the operator * @param {ASTnode} node AST node - * @param {object} firstToken First token in the expression - * @param {object} secondToken Second token in the expression + * @param {Object} firstToken First token in the expression + * @param {Object} secondToken Second token in the expression * @returns {void} */ function verifyNonWordsDontHaveSpaces(node, firstToken, secondToken) { @@ -241,7 +241,7 @@ module.exports = { * @returns {void} */ function checkForSpaces(node) { - var tokens = sourceCode.getFirstTokens(node, 2), + let tokens = sourceCode.getFirstTokens(node, 2), firstToken = tokens[0], secondToken = tokens[1]; @@ -250,7 +250,7 @@ module.exports = { return; } - var operator = node.prefix ? tokens[0].value : tokens[1].value; + let operator = node.prefix ? tokens[0].value : tokens[1].value; if (overrideExistsForOperator(node, operator)) { if (overrideEnforcesSpaces(node, operator)) { diff --git a/tools/eslint/lib/rules/spaced-comment.js b/tools/eslint/lib/rules/spaced-comment.js index 149862024c..7141ba1f42 100644 --- a/tools/eslint/lib/rules/spaced-comment.js +++ b/tools/eslint/lib/rules/spaced-comment.js @@ -4,7 +4,7 @@ */ "use strict"; -var lodash = require("lodash"); +let lodash = require("lodash"); //------------------------------------------------------------------------------ // Helpers @@ -16,7 +16,7 @@ var lodash = require("lodash"); * @returns {string} An escaped string. */ function escape(s) { - var isOneChar = s.length === 1; + let isOneChar = s.length === 1; s = lodash.escapeRegExp(s); return isOneChar ? s : "(?:" + s + ")"; @@ -50,38 +50,16 @@ function parseMarkersOption(markers) { } /** - * Creates RegExp object for `always` mode. - * Generated pattern is below: + * Creates string pattern for exceptions. + * Generated pattern: * - * 1. First, a marker or nothing. - * 2. Next, a space or an exception pattern sequence. + * 1. A space or an exception pattern sequence. * - * @param {string[]} markers - A marker list. - * @param {string[]} exceptions - A exception pattern list. - * @returns {RegExp} A RegExp object for `always` mode. + * @param {string[]} exceptions - An exception pattern list. + * @returns {string} A regular expression string for exceptions. */ -function createAlwaysStylePattern(markers, exceptions) { - var pattern = "^"; - - /* - * A marker or nothing. - * ["*"] ==> "\*?" - * ["*", "!"] ==> "(?:\*|!)?" - * ["*", "/", "!<"] ==> "(?:\*|\/|(?:!<))?" ==> https://jex.im/regulex/#!embed=false&flags=&re=(%3F%3A%5C*%7C%5C%2F%7C(%3F%3A!%3C))%3F - */ - if (markers.length === 1) { - - // the marker. - pattern += escape(markers[0]); - } else { - - // one of markers. - pattern += "(?:"; - pattern += markers.map(escape).join("|"); - pattern += ")"; - } - - pattern += "?"; // or nothing. +function createExceptionsPattern(exceptions) { + let pattern = ""; /* * A space or an exception pattern sequence. @@ -105,21 +83,59 @@ function createAlwaysStylePattern(markers, exceptions) { pattern += escapeAndRepeat(exceptions[0]); } else { - // a sequence of one of exception patterns. + // a sequence of one of the exception patterns. pattern += "(?:"; pattern += exceptions.map(escapeAndRepeat).join("|"); pattern += ")"; } - pattern += "(?:$|[\n\r]))"; // the sequence continues until the end. + pattern += "(?:$|[\n\r]))"; } + return pattern; +} + +/** + * Creates RegExp object for `always` mode. + * Generated pattern for beginning of comment: + * + * 1. First, a marker or nothing. + * 2. Next, a space or an exception pattern sequence. + * + * @param {string[]} markers - A marker list. + * @param {string[]} exceptions - An exception pattern list. + * @returns {RegExp} A RegExp object for the beginning of a comment in `always` mode. + */ +function createAlwaysStylePattern(markers, exceptions) { + let pattern = "^"; + + /* + * A marker or nothing. + * ["*"] ==> "\*?" + * ["*", "!"] ==> "(?:\*|!)?" + * ["*", "/", "!<"] ==> "(?:\*|\/|(?:!<))?" ==> https://jex.im/regulex/#!embed=false&flags=&re=(%3F%3A%5C*%7C%5C%2F%7C(%3F%3A!%3C))%3F + */ + if (markers.length === 1) { + + // the marker. + pattern += escape(markers[0]); + } else { + + // one of markers. + pattern += "(?:"; + pattern += markers.map(escape).join("|"); + pattern += ")"; + } + + pattern += "?"; // or nothing. + pattern += createExceptionsPattern(exceptions); + return new RegExp(pattern); } /** * Creates RegExp object for `never` mode. - * Generated pattern is below: + * Generated pattern for beginning of comment: * * 1. First, a marker or nothing (captured). * 2. Next, a space or a tab. @@ -128,7 +144,7 @@ function createAlwaysStylePattern(markers, exceptions) { * @returns {RegExp} A RegExp object for `never` mode. */ function createNeverStylePattern(markers) { - var pattern = "^(" + markers.map(escape).join("|") + ")?[ \t]+"; + let pattern = "^(" + markers.map(escape).join("|") + ")?[ \t]+"; return new RegExp(pattern); } @@ -198,6 +214,9 @@ module.exports = { items: { type: "string" } + }, + balanced: { + type: "boolean" } }, additionalProperties: false @@ -211,21 +230,25 @@ module.exports = { create: function(context) { // Unless the first option is never, require a space - var requireSpace = context.options[0] !== "never"; + let requireSpace = context.options[0] !== "never"; /* * Parse the second options. * If markers don't include `"*"`, it's added automatically for JSDoc * comments. */ - var config = context.options[1] || {}; - var styleRules = ["block", "line"].reduce(function(rule, type) { - var markers = parseMarkersOption(config[type] && config[type].markers || config.markers); - var exceptions = config[type] && config[type].exceptions || config.exceptions || []; + let config = context.options[1] || {}; + let balanced = config.block && config.block.balanced; + + let styleRules = ["block", "line"].reduce(function(rule, type) { + let markers = parseMarkersOption(config[type] && config[type].markers || config.markers); + let exceptions = config[type] && config[type].exceptions || config.exceptions || []; + let endNeverPattern = "[ \t]+$"; // Create RegExp object for valid patterns. rule[type] = { - regex: requireSpace ? createAlwaysStylePattern(markers, exceptions) : createNeverStylePattern(markers), + beginRegex: requireSpace ? createAlwaysStylePattern(markers, exceptions) : createNeverStylePattern(markers), + endRegex: balanced && requireSpace ? new RegExp(createExceptionsPattern(exceptions) + "$") : new RegExp(endNeverPattern), hasExceptions: exceptions.length > 0, markers: new RegExp("^(" + markers.map(escape).join("|") + ")") }; @@ -234,20 +257,20 @@ module.exports = { }, {}); /** - * Reports a spacing error with an appropriate message. + * Reports a beginning spacing error with an appropriate message. * @param {ASTNode} node - A comment node to check. - * @param {string} message - An error message to report + * @param {string} message - An error message to report. * @param {Array} match - An array of match results for markers. * @returns {void} */ - function report(node, message, match) { - var type = node.type.toLowerCase(), + function reportBegin(node, message, match) { + let type = node.type.toLowerCase(), commentIdentifier = type === "block" ? "/*" : "//"; context.report({ node: node, fix: function(fixer) { - var start = node.range[0], + let start = node.range[0], end = start + 2; if (requireSpace) { @@ -265,12 +288,36 @@ module.exports = { } /** + * Reports an ending spacing error with an appropriate message. + * @param {ASTNode} node - A comment node to check. + * @param {string} message - An error message to report. + * @param {string} match - An array of the matched whitespace characters. + * @returns {void} + */ + function reportEnd(node, message, match) { + context.report({ + node: node, + fix: function(fixer) { + if (requireSpace) { + return fixer.insertTextAfterRange([node.start, node.end - 2], " "); + } else { + let end = node.end - 2, + start = end - match[0].length; + + return fixer.replaceTextRange([start, end], ""); + } + }, + message: message + }); + } + + /** * Reports a given comment if it's invalid. * @param {ASTNode} node - a comment node to check. * @returns {void} */ function checkCommentForSpace(node) { - var type = node.type.toLowerCase(), + let type = node.type.toLowerCase(), rule = styleRules[type], commentIdentifier = type === "block" ? "/*" : "//"; @@ -279,28 +326,37 @@ module.exports = { return; } + let beginMatch = rule.beginRegex.exec(node.value); + let endMatch = rule.endRegex.exec(node.value); + // Checks. if (requireSpace) { - if (!rule.regex.test(node.value)) { - var hasMarker = rule.markers.exec(node.value); - var marker = hasMarker ? commentIdentifier + hasMarker[0] : commentIdentifier; + if (!beginMatch) { + let hasMarker = rule.markers.exec(node.value); + let marker = hasMarker ? commentIdentifier + hasMarker[0] : commentIdentifier; if (rule.hasExceptions) { - report(node, "Expected exception block, space or tab after '" + marker + "' in comment.", hasMarker); + reportBegin(node, "Expected exception block, space or tab after '" + marker + "' in comment.", hasMarker); } else { - report(node, "Expected space or tab after '" + marker + "' in comment.", hasMarker); + reportBegin(node, "Expected space or tab after '" + marker + "' in comment.", hasMarker); } } - } else { - var matched = rule.regex.exec(node.value); - if (matched) { - if (!matched[1]) { - report(node, "Unexpected space or tab after '" + commentIdentifier + "' in comment.", matched); + if (balanced && type === "block" && !endMatch) { + reportEnd(node, "Expected space or tab before '*/' in comment."); + } + } else { + if (beginMatch) { + if (!beginMatch[1]) { + reportBegin(node, "Unexpected space or tab after '" + commentIdentifier + "' in comment.", beginMatch); } else { - report(node, "Unexpected space or tab after marker (" + matched[1] + ") in comment.", matched); + reportBegin(node, "Unexpected space or tab after marker (" + beginMatch[1] + ") in comment.", beginMatch); } } + + if (balanced && type === "block" && endMatch) { + reportEnd(node, "Unexpected space or tab before '*/' in comment.", endMatch); + } } } diff --git a/tools/eslint/lib/rules/strict.js b/tools/eslint/lib/rules/strict.js index 45021517c7..5f54b15e79 100644 --- a/tools/eslint/lib/rules/strict.js +++ b/tools/eslint/lib/rules/strict.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -var lodash = require("lodash"); +let lodash = require("lodash"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var messages = { +let messages = { function: "Use the function form of 'use strict'.", global: "Use the global form of 'use strict'.", multiple: "Multiple 'use strict' directives.", @@ -35,7 +35,7 @@ var messages = { * @returns {ASTNode[]} All of the Use Strict Directives. */ function getUseStrictDirectives(statements) { - var directives = [], + let directives = [], i, statement; for (i = 0; i < statements.length; i++) { @@ -96,7 +96,7 @@ module.exports = { create: function(context) { - var mode = context.options[0] || "safe", + let mode = context.options[0] || "safe", ecmaFeatures = context.parserOptions.ecmaFeatures || {}, scopes = [], classScopes = [], @@ -117,7 +117,7 @@ module.exports = { * @returns {void} */ function reportSlice(nodes, start, end, message) { - var i; + let i; for (i = start; i < end; i++) { context.report(nodes[i], message); @@ -152,7 +152,7 @@ module.exports = { * @returns {void} */ function enterFunctionInFunctionMode(node, useStrictDirectives) { - var isInClass = classScopes.length > 0, + let isInClass = classScopes.length > 0, isParentGlobal = scopes.length === 0 && classScopes.length === 0, isParentStrict = scopes.length > 0 && scopes[scopes.length - 1], isStrict = useStrictDirectives.length > 0; @@ -194,7 +194,7 @@ module.exports = { * @returns {void} */ function enterFunction(node) { - var isBlock = node.body.type === "BlockStatement", + let isBlock = node.body.type === "BlockStatement", useStrictDirectives = isBlock ? getUseStrictDirectives(node.body.body) : []; @@ -212,7 +212,7 @@ module.exports = { rule = { Program: function(node) { - var useStrictDirectives = getUseStrictDirectives(node.body); + let useStrictDirectives = getUseStrictDirectives(node.body); if (node.sourceType === "module") { mode = "module"; diff --git a/tools/eslint/lib/rules/template-curly-spacing.js b/tools/eslint/lib/rules/template-curly-spacing.js index 144a035369..36c33e5330 100644 --- a/tools/eslint/lib/rules/template-curly-spacing.js +++ b/tools/eslint/lib/rules/template-curly-spacing.js @@ -9,14 +9,14 @@ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +let astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var OPEN_PAREN = /\$\{$/; -var CLOSE_PAREN = /^\}/; +let OPEN_PAREN = /\$\{$/; +let CLOSE_PAREN = /^\}/; //------------------------------------------------------------------------------ // Rule Definition @@ -38,9 +38,9 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); - var always = context.options[0] === "always"; - var prefix = always ? "Expected" : "Unexpected"; + let sourceCode = context.getSourceCode(); + let always = context.options[0] === "always"; + let prefix = always ? "Expected" : "Unexpected"; /** * Checks spacing before `}` of a given token. @@ -48,7 +48,7 @@ module.exports = { * @returns {void} */ function checkSpacingBefore(token) { - var prevToken = sourceCode.getTokenBefore(token); + let prevToken = sourceCode.getTokenBefore(token); if (prevToken && CLOSE_PAREN.test(token.value) && @@ -77,7 +77,7 @@ module.exports = { * @returns {void} */ function checkSpacingAfter(token) { - var nextToken = sourceCode.getTokenAfter(token); + let nextToken = sourceCode.getTokenAfter(token); if (nextToken && OPEN_PAREN.test(token.value) && @@ -105,7 +105,7 @@ module.exports = { return { TemplateElement: function(node) { - var token = sourceCode.getFirstToken(node); + let token = sourceCode.getFirstToken(node); checkSpacingBefore(token); checkSpacingAfter(token); diff --git a/tools/eslint/lib/rules/unicode-bom.js b/tools/eslint/lib/rules/unicode-bom.js index a152b03ac9..931d840b55 100644 --- a/tools/eslint/lib/rules/unicode-bom.js +++ b/tools/eslint/lib/rules/unicode-bom.js @@ -35,7 +35,7 @@ module.exports = { Program: function checkUnicodeBOM(node) { - var sourceCode = context.getSourceCode(), + let sourceCode = context.getSourceCode(), location = {column: 0, line: 1}, requireBOM = context.options[0] || "never"; diff --git a/tools/eslint/lib/rules/valid-jsdoc.js b/tools/eslint/lib/rules/valid-jsdoc.js index 65ed539d55..8af117e30e 100644 --- a/tools/eslint/lib/rules/valid-jsdoc.js +++ b/tools/eslint/lib/rules/valid-jsdoc.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -var doctrine = require("doctrine"); +let doctrine = require("doctrine"); //------------------------------------------------------------------------------ // Rule Definition @@ -61,7 +61,7 @@ module.exports = { create: function(context) { - var options = context.options[0] || {}, + let options = context.options[0] || {}, prefer = options.prefer || {}, sourceCode = context.getSourceCode(), @@ -78,7 +78,7 @@ module.exports = { //-------------------------------------------------------------------------- // Using a stack to store if a function returns or not (handling nested functions) - var fns = []; + let fns = []; /** * Check if node type is a Class @@ -110,7 +110,7 @@ module.exports = { * @private */ function addReturn(node) { - var functionState = fns[fns.length - 1]; + let functionState = fns[fns.length - 1]; if (functionState && node.argument !== null) { functionState.returnPresent = true; @@ -148,8 +148,8 @@ module.exports = { * @private */ function getCurrentExpectedTypes(type) { - var currentType; - var expectedType; + let currentType; + let expectedType; if (type.name) { currentType = type.name; @@ -177,8 +177,8 @@ module.exports = { return; } - var typesToCheck = []; - var elements = []; + let typesToCheck = []; + let elements = []; switch (type.type) { case "TypeApplication": // {Array.<String>} @@ -223,7 +223,7 @@ module.exports = { * @private */ function checkJSDoc(node) { - var jsdocNode = sourceCode.getJSDocComment(node), + let jsdocNode = sourceCode.getJSDocComment(node), functionData = fns.pop(), hasReturns = false, hasConstructor = false, @@ -336,7 +336,7 @@ module.exports = { } // check the parameters - var jsdocParams = Object.keys(params); + let jsdocParams = Object.keys(params); if (node.params) { node.params.forEach(function(param, i) { @@ -344,7 +344,7 @@ module.exports = { param = param.left; } - var name = param.name; + let name = param.name; // TODO(nzakas): Figure out logical things to do with destructured, default, rest params if (param.type === "Identifier") { @@ -363,7 +363,7 @@ module.exports = { } if (options.matchDescription) { - var regex = new RegExp(options.matchDescription); + let regex = new RegExp(options.matchDescription); if (!regex.test(jsdoc.description)) { context.report(jsdocNode, "JSDoc description does not satisfy the regex pattern."); diff --git a/tools/eslint/lib/rules/valid-typeof.js b/tools/eslint/lib/rules/valid-typeof.js index 289375a88b..dc378d9401 100644 --- a/tools/eslint/lib/rules/valid-typeof.js +++ b/tools/eslint/lib/rules/valid-typeof.js @@ -21,7 +21,7 @@ module.exports = { create: function(context) { - var VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function"], + let VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function"], OPERATORS = ["==", "===", "!=", "!=="]; //-------------------------------------------------------------------------- @@ -31,7 +31,7 @@ module.exports = { return { UnaryExpression: function(node) { - var parent, sibling; + let parent, sibling; if (node.operator === "typeof") { parent = context.getAncestors().pop(); @@ -40,7 +40,7 @@ module.exports = { sibling = parent.left === node ? parent.right : parent.left; if (sibling.type === "Literal" && VALID_TYPES.indexOf(sibling.value) === -1) { - context.report(sibling, "Invalid typeof comparison value"); + context.report(sibling, "Invalid typeof comparison value."); } } } diff --git a/tools/eslint/lib/rules/vars-on-top.js b/tools/eslint/lib/rules/vars-on-top.js index 25bef0411d..e94e487559 100644 --- a/tools/eslint/lib/rules/vars-on-top.js +++ b/tools/eslint/lib/rules/vars-on-top.js @@ -21,7 +21,7 @@ module.exports = { }, create: function(context) { - var errorMessage = "All 'var' declarations must be at the top of the function scope."; + let errorMessage = "All 'var' declarations must be at the top of the function scope."; //-------------------------------------------------------------------------- // Helpers @@ -29,7 +29,7 @@ module.exports = { /** * @param {ASTNode} node - any node - * @returns {Boolean} whether the given node structurally represents a directive + * @returns {boolean} whether the given node structurally represents a directive */ function looksLikeDirective(node) { return node.type === "ExpressionStatement" && @@ -39,7 +39,7 @@ module.exports = { /** * Check to see if its a ES6 import declaration * @param {ASTNode} node - any node - * @returns {Boolean} whether the given node represents a import declaration + * @returns {boolean} whether the given node represents a import declaration */ function looksLikeImport(node) { return node.type === "ImportDeclaration" || node.type === "ImportSpecifier" || @@ -67,10 +67,10 @@ module.exports = { * Checks whether this variable is on top of the block body * @param {ASTNode} node - The node to check * @param {ASTNode[]} statements - collection of ASTNodes for the parent node block - * @returns {Boolean} True if var is on top otherwise false + * @returns {boolean} True if var is on top otherwise false */ function isVarOnTop(node, statements) { - var i = 0, + let i = 0, l = statements.length; // skip over directives @@ -125,9 +125,9 @@ module.exports = { return { VariableDeclaration: function(node) { - var ancestors = context.getAncestors(); - var parent = ancestors.pop(); - var grandParent = ancestors.pop(); + let ancestors = context.getAncestors(); + let parent = ancestors.pop(); + let grandParent = ancestors.pop(); if (node.kind === "var") { // check variable is `var` type and not `let` or `const` if (parent.type === "ExportNamedDeclaration") { diff --git a/tools/eslint/lib/rules/wrap-iife.js b/tools/eslint/lib/rules/wrap-iife.js index 2f73699a42..78554091c9 100644 --- a/tools/eslint/lib/rules/wrap-iife.js +++ b/tools/eslint/lib/rules/wrap-iife.js @@ -26,9 +26,9 @@ module.exports = { create: function(context) { - var style = context.options[0] || "outside"; + let style = context.options[0] || "outside"; - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Check if the node is wrapped in () @@ -37,7 +37,7 @@ module.exports = { * @private */ function wrapped(node) { - var previousToken = sourceCode.getTokenBefore(node), + let previousToken = sourceCode.getTokenBefore(node), nextToken = sourceCode.getTokenAfter(node); return previousToken && previousToken.value === "(" && @@ -48,7 +48,7 @@ module.exports = { CallExpression: function(node) { if (node.callee.type === "FunctionExpression") { - var callExpressionWrapped = wrapped(node), + let callExpressionWrapped = wrapped(node), functionExpressionWrapped = wrapped(node.callee); if (!callExpressionWrapped && !functionExpressionWrapped) { diff --git a/tools/eslint/lib/rules/wrap-regex.js b/tools/eslint/lib/rules/wrap-regex.js index 1aed713bdd..44750a3fbd 100644 --- a/tools/eslint/lib/rules/wrap-regex.js +++ b/tools/eslint/lib/rules/wrap-regex.js @@ -21,12 +21,12 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); return { Literal: function(node) { - var token = sourceCode.getFirstToken(node), + let token = sourceCode.getFirstToken(node), nodeType = token.type, source, grandparent, diff --git a/tools/eslint/lib/rules/yield-star-spacing.js b/tools/eslint/lib/rules/yield-star-spacing.js index e2911b7200..c9ca64e0c2 100644 --- a/tools/eslint/lib/rules/yield-star-spacing.js +++ b/tools/eslint/lib/rules/yield-star-spacing.js @@ -39,9 +39,9 @@ module.exports = { }, create: function(context) { - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); - var mode = (function(option) { + let mode = (function(option) { if (!option || typeof option === "string") { return { before: { before: true, after: false }, @@ -64,11 +64,11 @@ module.exports = { */ function checkSpacing(side, leftToken, rightToken) { if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken) !== mode[side]) { - var after = leftToken.value === "*"; - var spaceRequired = mode[side]; - var node = after ? leftToken : rightToken; - var type = spaceRequired ? "Missing" : "Unexpected"; - var message = type + " space " + side + " *."; + let after = leftToken.value === "*"; + let spaceRequired = mode[side]; + let node = after ? leftToken : rightToken; + let type = spaceRequired ? "Missing" : "Unexpected"; + let message = type + " space " + side + " *."; context.report({ node: node, @@ -96,10 +96,10 @@ module.exports = { return; } - var tokens = sourceCode.getFirstTokens(node, 3); - var yieldToken = tokens[0]; - var starToken = tokens[1]; - var nextToken = tokens[2]; + let tokens = sourceCode.getFirstTokens(node, 3); + let yieldToken = tokens[0]; + let starToken = tokens[1]; + let nextToken = tokens[2]; checkSpacing("before", yieldToken, starToken); checkSpacing("after", starToken, nextToken); diff --git a/tools/eslint/lib/rules/yoda.js b/tools/eslint/lib/rules/yoda.js index 0373e91a4a..29f0602b98 100644 --- a/tools/eslint/lib/rules/yoda.js +++ b/tools/eslint/lib/rules/yoda.js @@ -10,7 +10,7 @@ /** * Determines whether an operator is a comparison operator. - * @param {String} operator The operator to check. + * @param {string} operator The operator to check. * @returns {boolean} Whether or not it is a comparison operator. */ function isComparisonOperator(operator) { @@ -19,7 +19,7 @@ function isComparisonOperator(operator) { /** * Determines whether an operator is an equality operator. - * @param {String} operator The operator to check. + * @param {string} operator The operator to check. * @returns {boolean} Whether or not it is an equality operator. */ function isEqualityOperator(operator) { @@ -29,7 +29,7 @@ function isEqualityOperator(operator) { /** * Determines whether an operator is one used in a range test. * Allowed operators are `<` and `<=`. - * @param {String} operator The operator to check. + * @param {string} operator The operator to check. * @returns {boolean} Whether the operator is used in range tests. */ function isRangeTestOperator(operator) { @@ -147,11 +147,11 @@ module.exports = { create: function(context) { // Default to "never" (!always) if no option - var always = (context.options[0] === "always"); - var exceptRange = (context.options[1] && context.options[1].exceptRange); - var onlyEquality = (context.options[1] && context.options[1].onlyEquality); + let always = (context.options[0] === "always"); + let exceptRange = (context.options[1] && context.options[1].exceptRange); + let onlyEquality = (context.options[1] && context.options[1].onlyEquality); - var sourceCode = context.getSourceCode(); + let sourceCode = context.getSourceCode(); /** * Determines whether node represents a range test. @@ -161,18 +161,18 @@ module.exports = { * must be less than or equal to the literal on the right side so that the * test makes any sense. * @param {ASTNode} node LogicalExpression node to test. - * @returns {Boolean} Whether node is a range test. + * @returns {boolean} Whether node is a range test. */ function isRangeTest(node) { - var left = node.left, + let left = node.left, right = node.right; /** * Determines whether node is of the form `0 <= x && x < 1`. - * @returns {Boolean} Whether node is a "between" range test. + * @returns {boolean} Whether node is a "between" range test. */ function isBetweenTest() { - var leftLiteral, rightLiteral; + let leftLiteral, rightLiteral; return (node.operator === "&&" && (leftLiteral = getNormalizedLiteral(left.left)) && @@ -183,10 +183,10 @@ module.exports = { /** * Determines whether node is of the form `x < 0 || 1 <= x`. - * @returns {Boolean} Whether node is an "outside" range test. + * @returns {boolean} Whether node is an "outside" range test. */ function isOutsideTest() { - var leftLiteral, rightLiteral; + let leftLiteral, rightLiteral; return (node.operator === "||" && (leftLiteral = getNormalizedLiteral(left.right)) && @@ -197,12 +197,12 @@ module.exports = { /** * Determines whether node is wrapped in parentheses. - * @returns {Boolean} Whether node is preceded immediately by an open + * @returns {boolean} Whether node is preceded immediately by an open * paren token and followed immediately by a close * paren token. */ function isParenWrapped() { - var tokenBefore, tokenAfter; + let tokenBefore, tokenAfter; return ((tokenBefore = sourceCode.getTokenBefore(node)) && tokenBefore.value === "(" && |