Browse Source

tools: update ESLint to 3.3.0 and enable rules

Update ESLint 3.3.0 and update .eslintrc:

* replace deprecated no-negated-in-lhs rule with no-unsafe-negation
  * http://eslint.org/docs/rules/no-negated-in-lhs
  * http://eslint.org/docs/rules/no-unsafe-negation
* enable no-template-curly-in-string
  * http://eslint.org/docs/rules/no-template-curly-in-string
* enable no-global-assign
  * http://eslint.org/docs/rules/no-global-assign
* enable func-call-spacing
  * http://eslint.org/docs/rules/func-call-spacing

PR-URL: https://github.com/nodejs/node/pull/8097
Reviewed-By: targos - Michaël Zasso <mic.besace@gmail.com>
Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
v7.x
Rich Trott 9 years ago
parent
commit
05b566a5ef
  1. 5
      .eslintrc
  2. 5
      tools/eslint/conf/category-list.json
  3. 2
      tools/eslint/conf/environments.js
  4. 11
      tools/eslint/conf/eslint-all.js
  5. 5
      tools/eslint/conf/eslint.json
  6. 163
      tools/eslint/lib/ast-utils.js
  7. 93
      tools/eslint/lib/cli-engine.js
  8. 40
      tools/eslint/lib/cli.js
  9. 34
      tools/eslint/lib/code-path-analysis/code-path-analyzer.js
  10. 14
      tools/eslint/lib/code-path-analysis/code-path-segment.js
  11. 200
      tools/eslint/lib/code-path-analysis/code-path-state.js
  12. 14
      tools/eslint/lib/code-path-analysis/code-path.js
  13. 24
      tools/eslint/lib/code-path-analysis/debug-helpers.js
  14. 18
      tools/eslint/lib/code-path-analysis/fork-context.js
  15. 47
      tools/eslint/lib/config.js
  16. 62
      tools/eslint/lib/config/autoconfig.js
  17. 51
      tools/eslint/lib/config/config-file.js
  18. 78
      tools/eslint/lib/config/config-initializer.js
  19. 24
      tools/eslint/lib/config/config-ops.js
  20. 31
      tools/eslint/lib/config/config-rule.js
  21. 13
      tools/eslint/lib/config/config-validator.js
  22. 2
      tools/eslint/lib/config/environments.js
  23. 17
      tools/eslint/lib/config/plugins.js
  24. 140
      tools/eslint/lib/eslint.js
  25. 31
      tools/eslint/lib/file-finder.js
  26. 4
      tools/eslint/lib/formatters/checkstyle.js
  27. 2
      tools/eslint/lib/formatters/compact.js
  28. 21
      tools/eslint/lib/formatters/html.js
  29. 4
      tools/eslint/lib/formatters/jslint-xml.js
  30. 6
      tools/eslint/lib/formatters/junit.js
  31. 4
      tools/eslint/lib/formatters/stylish.js
  32. 12
      tools/eslint/lib/formatters/table.js
  33. 8
      tools/eslint/lib/formatters/tap.js
  34. 2
      tools/eslint/lib/formatters/unix.js
  35. 2
      tools/eslint/lib/formatters/visualstudio.js
  36. 25
      tools/eslint/lib/ignored-paths.js
  37. 31
      tools/eslint/lib/internal-rules/internal-no-invalid-meta.js
  38. 4
      tools/eslint/lib/load-rules.js
  39. 2
      tools/eslint/lib/options.js
  40. 9
      tools/eslint/lib/rule-context.js
  41. 6
      tools/eslint/lib/rules.js
  42. 12
      tools/eslint/lib/rules/accessor-pairs.js
  43. 16
      tools/eslint/lib/rules/array-bracket-spacing.js
  44. 44
      tools/eslint/lib/rules/array-callback-return.js
  45. 14
      tools/eslint/lib/rules/arrow-body-style.js
  46. 72
      tools/eslint/lib/rules/arrow-parens.js
  47. 14
      tools/eslint/lib/rules/arrow-spacing.js
  48. 8
      tools/eslint/lib/rules/block-scoped-var.js
  49. 12
      tools/eslint/lib/rules/block-spacing.js
  50. 31
      tools/eslint/lib/rules/brace-style.js
  51. 9
      tools/eslint/lib/rules/callback-return.js
  52. 16
      tools/eslint/lib/rules/camelcase.js
  53. 26
      tools/eslint/lib/rules/comma-dangle.js
  54. 20
      tools/eslint/lib/rules/comma-spacing.js
  55. 19
      tools/eslint/lib/rules/comma-style.js
  56. 10
      tools/eslint/lib/rules/complexity.js
  57. 10
      tools/eslint/lib/rules/computed-property-spacing.js
  58. 8
      tools/eslint/lib/rules/consistent-return.js
  59. 12
      tools/eslint/lib/rules/consistent-this.js
  60. 36
      tools/eslint/lib/rules/constructor-super.js
  61. 22
      tools/eslint/lib/rules/curly.js
  62. 16
      tools/eslint/lib/rules/default-case.js
  63. 10
      tools/eslint/lib/rules/dot-location.js
  64. 8
      tools/eslint/lib/rules/dot-notation.js
  65. 2
      tools/eslint/lib/rules/eol-last.js
  66. 77
      tools/eslint/lib/rules/eqeqeq.js
  67. 153
      tools/eslint/lib/rules/func-call-spacing.js
  68. 8
      tools/eslint/lib/rules/func-names.js
  69. 10
      tools/eslint/lib/rules/func-style.js
  70. 22
      tools/eslint/lib/rules/generator-star-spacing.js
  71. 12
      tools/eslint/lib/rules/global-require.js
  72. 2
      tools/eslint/lib/rules/guard-for-in.js
  73. 8
      tools/eslint/lib/rules/handle-callback-err.js
  74. 4
      tools/eslint/lib/rules/id-blacklist.js
  75. 22
      tools/eslint/lib/rules/id-length.js
  76. 8
      tools/eslint/lib/rules/id-match.js
  77. 92
      tools/eslint/lib/rules/indent.js
  78. 14
      tools/eslint/lib/rules/init-declarations.js
  79. 8
      tools/eslint/lib/rules/jsx-quotes.js
  80. 56
      tools/eslint/lib/rules/key-spacing.js
  81. 60
      tools/eslint/lib/rules/keyword-spacing.js
  82. 17
      tools/eslint/lib/rules/linebreak-style.js
  83. 36
      tools/eslint/lib/rules/lines-around-comment.js
  84. 8
      tools/eslint/lib/rules/max-depth.js
  85. 30
      tools/eslint/lib/rules/max-len.js
  86. 24
      tools/eslint/lib/rules/max-lines.js
  87. 10
      tools/eslint/lib/rules/max-nested-callbacks.js
  88. 4
      tools/eslint/lib/rules/max-params.js
  89. 12
      tools/eslint/lib/rules/max-statements-per-line.js
  90. 10
      tools/eslint/lib/rules/max-statements.js
  91. 6
      tools/eslint/lib/rules/multiline-ternary.js
  92. 58
      tools/eslint/lib/rules/new-cap.js
  93. 6
      tools/eslint/lib/rules/new-parens.js
  94. 53
      tools/eslint/lib/rules/newline-after-var.js
  95. 19
      tools/eslint/lib/rules/newline-before-return.js
  96. 12
      tools/eslint/lib/rules/newline-per-chained-call.js
  97. 33
      tools/eslint/lib/rules/no-alert.js
  98. 8
      tools/eslint/lib/rules/no-bitwise.js
  99. 2
      tools/eslint/lib/rules/no-caller.js
  100. 2
      tools/eslint/lib/rules/no-case-declarations.js

5
.eslintrc

@ -19,17 +19,19 @@ rules:
no-func-assign: 2
no-invalid-regexp: 2
no-irregular-whitespace: 2
no-negated-in-lhs: 2
no-obj-calls: 2
no-proto: 2
no-template-curly-in-string: 2
no-unexpected-multiline: 2
no-unreachable: 2
no-unsafe-negation: 2
use-isnan: 2
valid-typeof: 2
# Best Practices
# http://eslint.org/docs/rules/#best-practices
no-fallthrough: 2
no-global-assign: 2
no-multi-spaces: 2
no-octal: 2
no-redeclare: 2
@ -58,6 +60,7 @@ rules:
brace-style: [2, 1tbs, {allowSingleLine: true}]
comma-spacing: 2
eol-last: 2
func-call-spacing: 2
indent: [2, 2, {SwitchCase: 1, MemberExpression: 1}]
key-spacing: [2, {mode: minimum}]
keyword-spacing: 2

5
tools/eslint/conf/category-list.json

@ -8,6 +8,11 @@
{ "name": "Stylistic Issues", "description": "These rules relate to style guidelines, and are therefore quite subjective:" },
{ "name": "ECMAScript 6", "description": "These rules relate to ES6, also known as ES2015:" }
],
"deprecated": {
"name": "Deprecated",
"description": "These rules have been deprecated and replaced by newer rules:",
"rules": []
},
"removed": {
"name": "Removed",
"description": "These rules from older versions of ESLint have been replaced by newer rules:",

2
tools/eslint/conf/environments.js

@ -8,7 +8,7 @@
// Requirements
//------------------------------------------------------------------------------
let globals = require("globals");
const globals = require("globals");
//------------------------------------------------------------------------------
// Public Interface

11
tools/eslint/conf/eslint-all.js

@ -9,17 +9,16 @@
// Requirements
//------------------------------------------------------------------------------
let fs = require("fs"),
path = require("path");
const load = require("../lib/load-rules"),
rules = require("../lib/rules");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
let ruleFiles = fs.readdirSync(path.resolve(__dirname, "../lib/rules"));
let enabledRules = ruleFiles.reduce(function(result, filename) {
if (path.extname(filename) === ".js") {
result[path.basename(filename, ".js")] = "error";
const enabledRules = Object.keys(load()).reduce((result, ruleId) => {
if (!rules.get(ruleId).meta.deprecated) {
result[ruleId] = "error";
}
return result;
}, {});

5
tools/eslint/conf/eslint.json

@ -41,6 +41,7 @@
"no-fallthrough": "error",
"no-floating-decimal": "off",
"no-func-assign": "error",
"no-global-assign": "off",
"no-implicit-coercion": "off",
"no-implicit-globals": "off",
"no-implied-eval": "off",
@ -113,6 +114,7 @@
"no-unneeded-ternary": "off",
"no-unreachable": "error",
"no-unsafe-finally": "error",
"no-unsafe-negation": "off",
"no-unused-expressions": "off",
"no-unused-labels": "error",
"no-unused-vars": "error",
@ -152,6 +154,7 @@
"dot-notation": "off",
"eol-last": "off",
"eqeqeq": "off",
"func-call-spacing": "off",
"func-names": "off",
"func-style": "off",
"generator-star-spacing": "off",
@ -204,6 +207,7 @@
"rest-spread-spacing": "off",
"semi": "off",
"semi-spacing": "off",
"sort-keys": "off",
"sort-imports": "off",
"sort-vars": "off",
"space-before-blocks": "off",
@ -221,6 +225,7 @@
"vars-on-top": "off",
"wrap-iife": "off",
"wrap-regex": "off",
"no-template-curly-in-string": "off",
"yield-star-spacing": "off",
"yoda": "off"
}

163
tools/eslint/lib/ast-utils.js

@ -9,19 +9,19 @@
// Requirements
//------------------------------------------------------------------------------
let esutils = require("esutils");
const esutils = require("esutils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
let anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/;
let anyLoopPattern = /^(?:DoWhile|For|ForIn|ForOf|While)Statement$/;
let arrayOrTypedArrayPattern = /Array$/;
let arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/;
let bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/;
let breakableTypePattern = /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/;
let thisTagPattern = /^[\s\*]*@this/m;
const anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/;
const anyLoopPattern = /^(?:DoWhile|For|ForIn|ForOf|While)Statement$/;
const arrayOrTypedArrayPattern = /Array$/;
const arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/;
const bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/;
const breakableTypePattern = /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/;
const thisTagPattern = /^[\s\*]*@this/m;
/**
* Checks reference if is non initializer and writable.
@ -32,15 +32,14 @@ let thisTagPattern = /^[\s\*]*@this/m;
* @private
*/
function isModifyingReference(reference, index, references) {
let identifier = reference.identifier,
modifyingDifferentIdentifier;
const identifier = reference.identifier;
/*
* Destructuring assignments can have multiple default value, so
* possibly there are multiple writeable references for the same
* identifier.
*/
modifyingDifferentIdentifier = index === 0 ||
const modifyingDifferentIdentifier = index === 0 ||
references[index - 1].identifier !== identifier;
return (identifier &&
@ -50,16 +49,23 @@ function isModifyingReference(reference, index, references) {
);
}
/**
* Checks whether the given string starts with uppercase or not.
*
* @param {string} s - The string to check.
* @returns {boolean} `true` if the string starts with uppercase.
*/
function startsWithUpperCase(s) {
return s[0] !== s[0].toLocaleLowerCase();
}
/**
* Checks whether or not a node is a constructor.
* @param {ASTNode} node - A function node to check.
* @returns {boolean} Wehether or not a node is a constructor.
*/
function isES5Constructor(node) {
return (
node.id &&
node.id.name[0] !== node.id.name[0].toLocaleLowerCase()
);
return (node.id && startsWithUpperCase(node.id.name));
}
/**
@ -160,7 +166,7 @@ function isMethodWhichHasThisArg(node) {
* @returns {boolean} Whether or not the node has a `@this` tag in its comments.
*/
function hasJSDocThisTag(node, sourceCode) {
let jsdocComment = sourceCode.getJSDocComment(node);
const jsdocComment = sourceCode.getJSDocComment(node);
if (jsdocComment && thisTagPattern.test(jsdocComment.value)) {
return true;
@ -183,7 +189,7 @@ function hasJSDocThisTag(node, sourceCode) {
* @private
*/
function isParenthesised(sourceCode, node) {
let previousToken = sourceCode.getTokenBefore(node),
const previousToken = sourceCode.getTokenBefore(node),
nextToken = sourceCode.getTokenAfter(node);
return Boolean(previousToken && nextToken) &&
@ -285,7 +291,7 @@ module.exports = {
* @returns {boolean} `true` if the node is an ESLint directive comment
*/
isDirectiveComment: function(node) {
let comment = node.value.trim();
const comment = node.value.trim();
return (
node.type === "Line" && comment.indexOf("eslint-") === 0 ||
@ -321,7 +327,7 @@ module.exports = {
let scope = initScope;
while (scope) {
let variable = scope.set.get(name);
const variable = scope.set.get(name);
if (variable) {
return variable;
@ -345,9 +351,9 @@ module.exports = {
* If the location is below, this judges `this` is valid.
*
* - The location is not on an object literal.
* - The location does not assign to a property.
* - The location is not assigned to a variable which starts with an uppercase letter.
* - The location is not on an ES2015 class.
* - The location does not call its `bind`/`call`/`apply` method directly.
* - Its `bind`/`call`/`apply` method is not called directly.
* - The function is not a callback of array methods (such as `.forEach()`) if `thisArg` is given.
*
* @param {ASTNode} node - A function node to check.
@ -358,9 +364,10 @@ module.exports = {
if (isES5Constructor(node) || hasJSDocThisTag(node, sourceCode)) {
return false;
}
const isAnonymous = node.id === null;
while (node) {
let parent = node.parent;
const parent = node.parent;
switch (parent.type) {
@ -392,25 +399,44 @@ module.exports = {
// e.g.
// var obj = { foo() { ... } };
// var obj = { foo: function() { ... } };
case "Property":
return false;
// e.g.
// obj.foo = foo() { ... };
case "AssignmentExpression":
return (
parent.right !== node ||
parent.left.type !== "MemberExpression"
);
// e.g.
// class A { constructor() { ... } }
// class A { foo() { ... } }
// class A { get foo() { ... } }
// class A { set foo() { ... } }
// class A { static foo() { ... } }
case "Property":
case "MethodDefinition":
return parent.value !== node;
// e.g.
// obj.foo = function foo() { ... };
// Foo = function() { ... };
// [obj.foo = function foo() { ... }] = a;
// [Foo = function() { ... }] = a;
case "AssignmentExpression":
case "AssignmentPattern":
if (parent.right === node) {
if (parent.left.type === "MemberExpression") {
return false;
}
if (isAnonymous &&
parent.left.type === "Identifier" &&
startsWithUpperCase(parent.left.name)
) {
return false;
}
}
return true;
// e.g.
// var Foo = function() { ... };
case "VariableDeclarator":
return !(
isAnonymous &&
parent.init === node &&
parent.id.type === "Identifier" &&
startsWithUpperCase(parent.id.name)
);
// e.g.
// var foo = function foo() { ... }.bind(obj);
@ -585,5 +611,74 @@ module.exports = {
*/
isFunction: function(node) {
return Boolean(node && anyFunctionPattern.test(node.type));
},
/**
* Gets the property name of a given node.
* The node can be a MemberExpression, a Property, or a MethodDefinition.
*
* If the name is dynamic, this returns `null`.
*
* For examples:
*
* a.b // => "b"
* a["b"] // => "b"
* a['b'] // => "b"
* a[`b`] // => "b"
* a[100] // => "100"
* a[b] // => null
* a["a" + "b"] // => null
* a[tag`b`] // => null
* a[`${b}`] // => null
*
* let a = {b: 1} // => "b"
* let a = {["b"]: 1} // => "b"
* let a = {['b']: 1} // => "b"
* let a = {[`b`]: 1} // => "b"
* let a = {[100]: 1} // => "100"
* let a = {[b]: 1} // => null
* let a = {["a" + "b"]: 1} // => null
* let a = {[tag`b`]: 1} // => null
* let a = {[`${b}`]: 1} // => null
*
* @param {ASTNode} node - The node to get.
* @returns {string|null} The property name if static. Otherwise, null.
*/
getStaticPropertyName(node) {
let prop;
switch (node && node.type) {
case "Property":
case "MethodDefinition":
prop = node.key;
break;
case "MemberExpression":
prop = node.property;
break;
// no default
}
switch (prop && prop.type) {
case "Literal":
return String(prop.value);
case "TemplateLiteral":
if (prop.expressions.length === 0 && prop.quasis.length === 1) {
return prop.quasis[0].value.cooked;
}
break;
case "Identifier":
if (!node.computed) {
return prop.name;
}
break;
// no default
}
return null;
}
};

93
tools/eslint/lib/cli-engine.js

@ -15,12 +15,8 @@
// Requirements
//------------------------------------------------------------------------------
let fs = require("fs"),
const fs = require("fs"),
path = require("path"),
lodash = require("lodash"),
debug = require("debug"),
rules = require("./rules"),
eslint = require("./eslint"),
defaultOptions = require("../conf/cli-options"),
@ -36,6 +32,7 @@ let fs = require("fs"),
pkg = require("../package.json");
const debug = require("debug")("eslint:cli-engine");
//------------------------------------------------------------------------------
// Typedefs
@ -84,8 +81,6 @@ let fs = require("fs"),
// Helpers
//------------------------------------------------------------------------------
debug = debug("eslint:cli-engine");
/**
* It will calculate the error and warning count for collection of messages per file
* @param {Object[]} messages - Collection of messages
@ -137,12 +132,11 @@ function calculateStatsPerRun(results) {
* @private
*/
function multipassFix(text, config, options) {
const MAX_PASSES = 10;
let messages = [],
fixedResult,
fixed = false,
passNumber = 0,
MAX_PASSES = 10;
passNumber = 0;
/**
* This loop continues until one of the following is true:
@ -213,12 +207,9 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
eslint.reset();
let filePath,
config,
messages,
stats,
fileExtension,
processor,
loadedPlugins,
fixedResult;
if (filename) {
@ -228,15 +219,15 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
filename = filename || "<text>";
debug("Linting " + filename);
config = configHelper.getConfig(filePath);
const config = configHelper.getConfig(filePath);
if (config.plugins) {
Plugins.loadAll(config.plugins);
}
loadedPlugins = Plugins.getAll();
const loadedPlugins = Plugins.getAll();
for (let plugin in loadedPlugins) {
for (const plugin in loadedPlugins) {
if (loadedPlugins[plugin].processors && Object.keys(loadedPlugins[plugin].processors).indexOf(fileExtension) >= 0) {
processor = loadedPlugins[plugin].processors[fileExtension];
break;
@ -245,8 +236,8 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
if (processor) {
debug("Using processor");
let parsedBlocks = processor.preprocess(text, filename);
let unprocessedMessages = [];
const parsedBlocks = processor.preprocess(text, filename);
const unprocessedMessages = [];
parsedBlocks.forEach(function(block) {
unprocessedMessages.push(eslint.verify(block, config, {
@ -275,9 +266,9 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
}
}
stats = calculateStatsPerFile(messages);
const stats = calculateStatsPerFile(messages);
let result = {
const result = {
filePath: filename,
messages: messages,
errorCount: stats.errorCount,
@ -302,7 +293,7 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
*/
function processFile(filename, configHelper, options) {
let text = fs.readFileSync(path.resolve(filename), "utf8"),
const text = fs.readFileSync(path.resolve(filename), "utf8"),
result = processText(text, configHelper, filename, options.fix, options.allowInlineConfig);
return result;
@ -318,9 +309,9 @@ function processFile(filename, configHelper, options) {
*/
function createIgnoreResult(filePath, baseDir) {
let message;
let isHidden = /^\./.test(path.basename(filePath));
let isInNodeModules = baseDir && /^node_modules/.test(path.relative(baseDir, filePath));
let isInBowerComponents = baseDir && /^bower_components/.test(path.relative(baseDir, filePath));
const isHidden = /^\./.test(path.basename(filePath));
const isInNodeModules = baseDir && /^node_modules/.test(path.relative(baseDir, filePath));
const isInBowerComponents = baseDir && /^bower_components/.test(path.relative(baseDir, filePath));
if (isHidden) {
message = "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern \'!<relative/path/to/filename>\'\") to override.";
@ -377,8 +368,8 @@ function getCacheFile(cacheFile, cwd) {
*/
cacheFile = path.normalize(cacheFile);
let resolvedCacheFile = path.resolve(cwd, cacheFile);
let looksLikeADirectory = cacheFile[cacheFile.length - 1 ] === path.sep;
const resolvedCacheFile = path.resolve(cwd, cacheFile);
const looksLikeADirectory = cacheFile[cacheFile.length - 1 ] === path.sep;
/**
* return the name for the cache file in case the provided parameter is a directory
@ -442,7 +433,7 @@ function getCacheFile(cacheFile, cwd) {
*/
function CLIEngine(options) {
options = lodash.assign(
options = Object.assign(
Object.create(null),
defaultOptions,
{cwd: process.cwd()},
@ -455,7 +446,7 @@ function CLIEngine(options) {
*/
this.options = options;
let cacheFile = getCacheFile(this.options.cacheLocation || this.options.cacheFile, this.options.cwd);
const cacheFile = getCacheFile(this.options.cacheLocation || this.options.cacheFile, this.options.cwd);
/**
* Cache used to avoid operating on files that haven't changed since the
@ -467,7 +458,7 @@ function CLIEngine(options) {
// load in additional rules
if (this.options.rulePaths) {
let cwd = this.options.cwd;
const cwd = this.options.cwd;
this.options.rulePaths.forEach(function(rulesdir) {
debug("Loading rules from " + rulesdir);
@ -502,7 +493,7 @@ CLIEngine.getFormatter = function(format) {
// if there's a slash, then it's a file
if (format.indexOf("/") > -1) {
let cwd = this.options ? this.options.cwd : process.cwd();
const cwd = this.options ? this.options.cwd : process.cwd();
formatterPath = path.resolve(cwd, format);
} else {
@ -527,10 +518,10 @@ CLIEngine.getFormatter = function(format) {
* @returns {LintResult[]} The filtered results.
*/
CLIEngine.getErrorResults = function(results) {
let filtered = [];
const filtered = [];
results.forEach(function(result) {
let filteredMessages = result.messages.filter(isErrorMessage);
const filteredMessages = result.messages.filter(isErrorMessage);
if (filteredMessages.length > 0) {
filtered.push({
@ -588,14 +579,11 @@ CLIEngine.prototype = {
* @returns {Object} The results for all files that were linted.
*/
executeOnFiles: function(patterns) {
let results = [],
const results = [],
options = this.options,
fileCache = this._fileCache,
configHelper = new Config(options),
fileList,
stats,
startTime,
prevConfig; // the previous configuration used
configHelper = new Config(options);
let prevConfig; // the previous configuration used
/**
* Calculates the hash of the config file used to validate a given file
@ -603,7 +591,7 @@ CLIEngine.prototype = {
* @returns {string} the hash of the config
*/
function hashOfConfigFor(filename) {
let config = configHelper.getConfig(filename);
const config = configHelper.getConfig(filename);
if (!prevConfig) {
prevConfig = {};
@ -618,7 +606,7 @@ CLIEngine.prototype = {
*/
prevConfig.config = config;
let eslintVersion = pkg.version;
const eslintVersion = pkg.version;
prevConfig.hash = hash(eslintVersion + "_" + stringify(config));
}
@ -650,11 +638,11 @@ CLIEngine.prototype = {
* the file has changed
*/
descriptor = fileCache.getFileDescriptor(filename);
let meta = descriptor.meta || {};
const meta = descriptor.meta || {};
hashOfConfig = hashOfConfigFor(filename);
let changed = descriptor.changed || meta.hashOfConfig !== hashOfConfig;
const changed = descriptor.changed || meta.hashOfConfig !== hashOfConfig;
if (!changed) {
debug("Skipping file since hasn't changed: " + filename);
@ -676,7 +664,7 @@ CLIEngine.prototype = {
debug("Processing " + filename);
let res = processFile(filename, configHelper, options);
const res = processFile(filename, configHelper, options);
if (options.cache) {
@ -706,17 +694,18 @@ CLIEngine.prototype = {
results.push(res);
}
startTime = Date.now();
const startTime = Date.now();
patterns = this.resolveFileGlobPatterns(patterns);
fileList = globUtil.listFilesToProcess(patterns, options);
const fileList = globUtil.listFilesToProcess(patterns, options);
fileList.forEach(function(fileInfo) {
executeOnFile(fileInfo.filename, fileInfo.ignored);
});
stats = calculateStatsPerRun(results);
const stats = calculateStatsPerRun(results);
if (options.cache) {
@ -742,8 +731,7 @@ CLIEngine.prototype = {
*/
executeOnText: function(text, filename, warnIgnored) {
let results = [],
stats,
const results = [],
options = this.options,
configHelper = new Config(options),
ignoredPaths = new IgnoredPaths(options);
@ -761,7 +749,7 @@ CLIEngine.prototype = {
results.push(processText(text, configHelper, filename, options.fix, options.allowInlineConfig));
}
stats = calculateStatsPerRun(results);
const stats = calculateStatsPerRun(results);
return {
results: results,
@ -778,7 +766,7 @@ CLIEngine.prototype = {
* @returns {Object} A configuration object for the file.
*/
getConfigForFile: function(filePath) {
let configHelper = new Config(this.options);
const configHelper = new Config(this.options);
return configHelper.getConfig(filePath);
},
@ -789,10 +777,9 @@ CLIEngine.prototype = {
* @returns {boolean} Whether or not the given path is ignored.
*/
isPathIgnored: function(filePath) {
let ignoredPaths;
let resolvedPath = path.resolve(this.options.cwd, filePath);
const resolvedPath = path.resolve(this.options.cwd, filePath);
const ignoredPaths = new IgnoredPaths(this.options);
ignoredPaths = new IgnoredPaths(this.options);
return ignoredPaths.contains(resolvedPath);
},

40
tools/eslint/lib/cli.js

@ -15,22 +15,20 @@
// Requirements
//------------------------------------------------------------------------------
let fs = require("fs"),
const fs = require("fs"),
path = require("path"),
debug = require("debug"),
shell = require("shelljs"),
options = require("./options"),
CLIEngine = require("./cli-engine"),
mkdirp = require("mkdirp"),
log = require("./logging");
const debug = require("debug")("eslint:cli");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
debug = debug("eslint:cli");
/**
* Translates the CLI options into the options expected by the CLIEngine.
* @param {Object} cliOptions The CLI options to translate.
@ -70,9 +68,7 @@ function translateOptions(cliOptions) {
* @private
*/
function printResults(engine, results, format, outputFile) {
let formatter,
output,
filePath;
let formatter;
try {
formatter = engine.getFormatter(format);
@ -81,13 +77,13 @@ function printResults(engine, results, format, outputFile) {
return false;
}
output = formatter(results);
const output = formatter(results);
if (output) {
if (outputFile) {
filePath = path.resolve(process.cwd(), outputFile);
const filePath = path.resolve(process.cwd(), outputFile);
if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
if (shell.test("-d", filePath)) {
log.error("Cannot write to output file path, it is a directory: %s", outputFile);
return false;
}
@ -116,7 +112,7 @@ function printResults(engine, results, format, outputFile) {
* Encapsulates all CLI behavior for eslint. Makes it easier to test as well as
* for other Node.js programs to effectively run the CLI.
*/
let cli = {
const cli = {
/**
* Executes the CLI based on an array of arguments that is passed in.
@ -126,11 +122,7 @@ let cli = {
*/
execute: function(args, text) {
let currentOptions,
files,
report,
engine,
tooManyWarnings;
let currentOptions;
try {
currentOptions = options.parse(args);
@ -139,7 +131,7 @@ let cli = {
return 1;
}
files = currentOptions._;
const files = currentOptions._;
if (currentOptions.version) { // version from package.json
@ -159,7 +151,8 @@ let cli = {
return 1;
}
engine = new CLIEngine(translateOptions(currentOptions));
const engine = new CLIEngine(translateOptions(currentOptions));
if (currentOptions.printConfig) {
if (files.length !== 1) {
log.error("The --print-config option requires a " +
@ -172,13 +165,14 @@ let cli = {
return 1;
}
let fileConfig = engine.getConfigForFile(files[0]);
const fileConfig = engine.getConfigForFile(files[0]);
log.info(JSON.stringify(fileConfig, null, " "));
return 0;
}
report = text ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files);
const report = text ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files);
if (currentOptions.fix) {
debug("Fix mode enabled - applying fixes");
CLIEngine.outputFixes(report);
@ -190,7 +184,7 @@ let cli = {
}
if (printResults(engine, report.results, currentOptions.format, currentOptions.outputFile)) {
tooManyWarnings = currentOptions.maxWarnings >= 0 && report.warningCount > currentOptions.maxWarnings;
const tooManyWarnings = currentOptions.maxWarnings >= 0 && report.warningCount > currentOptions.maxWarnings;
if (!report.errorCount && tooManyWarnings) {
log.error("ESLint found too many warnings (maximum: %s).", currentOptions.maxWarnings);

34
tools/eslint/lib/code-path-analysis/code-path-analyzer.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let assert = require("assert"),
const assert = require("assert"),
CodePath = require("./code-path"),
CodePathSegment = require("./code-path-segment"),
IdGenerator = require("./id-generator"),
@ -38,7 +38,7 @@ function isCaseNode(node) {
* @returns {boolean} `true` if the node is a test of a choice statement.
*/
function isForkingByTrueOrFalse(node) {
let parent = node.parent;
const parent = node.parent;
switch (parent.type) {
case "ConditionalExpression":
@ -83,7 +83,7 @@ function getBooleanValueIfSimpleConstant(node) {
* @returns {boolean} `true` if the node is a reference.
*/
function isIdentifierReference(node) {
let parent = node.parent;
const parent = node.parent;
switch (parent.type) {
case "LabeledStatement":
@ -135,11 +135,11 @@ function isIdentifierReference(node) {
* @returns {void}
*/
function forwardCurrentToHead(analyzer, node) {
let codePath = analyzer.codePath;
let state = CodePath.getState(codePath);
let currentSegments = state.currentSegments;
let headSegments = state.headSegments;
let end = Math.max(currentSegments.length, headSegments.length);
const codePath = analyzer.codePath;
const state = CodePath.getState(codePath);
const currentSegments = state.currentSegments;
const headSegments = state.headSegments;
const end = Math.max(currentSegments.length, headSegments.length);
let i, currentSegment, headSegment;
// Fires leaving events.
@ -191,11 +191,11 @@ function forwardCurrentToHead(analyzer, node) {
* @returns {void}
*/
function leaveFromCurrentSegment(analyzer, node) {
let state = CodePath.getState(analyzer.codePath);
let currentSegments = state.currentSegments;
const state = CodePath.getState(analyzer.codePath);
const currentSegments = state.currentSegments;
for (let i = 0; i < currentSegments.length; ++i) {
let currentSegment = currentSegments[i];
const currentSegment = currentSegments[i];
debug.dump("onCodePathSegmentEnd " + currentSegment.id);
if (currentSegment.reachable) {
@ -221,9 +221,9 @@ function leaveFromCurrentSegment(analyzer, node) {
* @returns {void}
*/
function preprocess(analyzer, node) {
let codePath = analyzer.codePath;
let state = CodePath.getState(codePath);
let parent = node.parent;
const codePath = analyzer.codePath;
const state = CodePath.getState(codePath);
const parent = node.parent;
switch (parent.type) {
case "LogicalExpression":
@ -330,7 +330,7 @@ function preprocess(analyzer, node) {
function processCodePathToEnter(analyzer, node) {
let codePath = analyzer.codePath;
let state = codePath && CodePath.getState(codePath);
let parent = node.parent;
const parent = node.parent;
switch (node.type) {
case "Program":
@ -419,8 +419,8 @@ function processCodePathToEnter(analyzer, node) {
* @returns {void}
*/
function processCodePathToExit(analyzer, node) {
let codePath = analyzer.codePath;
let state = CodePath.getState(codePath);
const codePath = analyzer.codePath;
const state = CodePath.getState(codePath);
let dontForward = false;
switch (node.type) {

14
tools/eslint/lib/code-path-analysis/code-path-segment.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let debug = require("./debug-helpers");
const debug = require("./debug-helpers");
//------------------------------------------------------------------------------
// Helpers
@ -22,11 +22,11 @@ let debug = require("./debug-helpers");
* @returns {CodePathSegment[]} The replaced array.
*/
function flattenUnusedSegments(segments) {
let done = Object.create(null);
let retv = [];
const done = Object.create(null);
const retv = [];
for (let i = 0; i < segments.length; ++i) {
let segment = segments[i];
const segment = segments[i];
// Ignores duplicated.
if (done[segment.id]) {
@ -36,7 +36,7 @@ function flattenUnusedSegments(segments) {
// Use previous segments if unused.
if (!segment.internal.used) {
for (let j = 0; j < segment.allPrevSegments.length; ++j) {
let prevSegment = segment.allPrevSegments[j];
const prevSegment = segment.allPrevSegments[j];
if (!done[prevSegment.id]) {
done[prevSegment.id] = true;
@ -175,7 +175,7 @@ CodePathSegment.newNext = function(id, allPrevSegments) {
* @returns {CodePathSegment} The created segment.
*/
CodePathSegment.newUnreachable = function(id, allPrevSegments) {
let segment = new CodePathSegment(id, flattenUnusedSegments(allPrevSegments), false);
const segment = new CodePathSegment(id, flattenUnusedSegments(allPrevSegments), false);
// In `if (a) return a; foo();` case, the unreachable segment preceded by
// the return statement is not used but must not be remove.
@ -215,7 +215,7 @@ CodePathSegment.markUsed = function(segment) {
if (segment.reachable) {
for (i = 0; i < segment.allPrevSegments.length; ++i) {
let prevSegment = segment.allPrevSegments[i];
const prevSegment = segment.allPrevSegments[i];
prevSegment.allNextSegments.push(segment);
prevSegment.nextSegments.push(segment);

200
tools/eslint/lib/code-path-analysis/code-path-state.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let CodePathSegment = require("./code-path-segment"),
const CodePathSegment = require("./code-path-segment"),
ForkContext = require("./fork-context");
//------------------------------------------------------------------------------
@ -31,7 +31,7 @@ let CodePathSegment = require("./code-path-segment"),
*/
function addToReturnedOrThrown(dest, others, all, segments) {
for (let i = 0; i < segments.length; ++i) {
let segment = segments[i];
const segment = segments[i];
dest.push(segment);
if (others.indexOf(segment) === -1) {
@ -150,8 +150,8 @@ function remove(xs, x) {
*/
function removeConnection(prevSegments, nextSegments) {
for (let i = 0; i < prevSegments.length; ++i) {
let prevSegment = prevSegments[i];
let nextSegment = nextSegments[i];
const prevSegment = prevSegments[i];
const nextSegment = nextSegments[i];
remove(prevSegment.nextSegments, nextSegment);
remove(prevSegment.allNextSegments, nextSegment);
@ -169,11 +169,11 @@ function removeConnection(prevSegments, nextSegments) {
* @returns {void}
*/
function makeLooped(state, fromSegments, toSegments) {
let end = Math.min(fromSegments.length, toSegments.length);
const end = Math.min(fromSegments.length, toSegments.length);
for (let i = 0; i < end; ++i) {
let fromSegment = fromSegments[i];
let toSegment = toSegments[i];
const fromSegment = fromSegments[i];
const toSegment = toSegments[i];
if (toSegment.reachable) {
fromSegment.nextSegments.push(toSegment);
@ -241,9 +241,9 @@ function CodePathState(idGenerator, onLooped) {
this.initialSegment = this.forkContext.head[0];
// returnedSegments and thrownSegments push elements into finalSegments also.
let final = this.finalSegments = [];
let returned = this.returnedForkContext = [];
let thrown = this.thrownForkContext = [];
const final = this.finalSegments = [];
const returned = this.returnedForkContext = [];
const thrown = this.thrownForkContext = [];
returned.add = addToReturnedOrThrown.bind(null, returned, thrown, final);
thrown.add = addToReturnedOrThrown.bind(null, thrown, returned, final);
@ -266,7 +266,7 @@ CodePathState.prototype = {
* @type {ForkContext}
*/
get parentForkContext() {
let current = this.forkContext;
const current = this.forkContext;
return current && current.upper;
},
@ -292,7 +292,7 @@ CodePathState.prototype = {
* @returns {ForkContext} The last context.
*/
popForkContext: function() {
let lastContext = this.forkContext;
const lastContext = this.forkContext;
this.forkContext = lastContext.upper;
this.forkContext.replaceHead(lastContext.makeNext(0, -1));
@ -370,12 +370,12 @@ CodePathState.prototype = {
* @returns {ChoiceContext} The popped context.
*/
popChoiceContext: function() {
let context = this.choiceContext;
const context = this.choiceContext;
this.choiceContext = context.upper;
let forkContext = this.forkContext;
let headSegments = forkContext.head;
const forkContext = this.forkContext;
const headSegments = forkContext.head;
switch (context.kind) {
case "&&":
@ -396,7 +396,7 @@ CodePathState.prototype = {
* test chunk.
*/
if (context.isForkingAsResult) {
let parentContext = this.choiceContext;
const parentContext = this.choiceContext;
parentContext.trueForkContext.addAll(context.trueForkContext);
parentContext.falseForkContext.addAll(context.falseForkContext);
@ -443,7 +443,7 @@ CodePathState.prototype = {
}
// Merges all paths.
let prevForkContext = context.trueForkContext;
const prevForkContext = context.trueForkContext;
prevForkContext.addAll(context.falseForkContext);
forkContext.replaceHead(prevForkContext.makeNext(0, -1));
@ -458,8 +458,8 @@ CodePathState.prototype = {
* @returns {void}
*/
makeLogicalRight: function() {
let context = this.choiceContext;
let forkContext = this.forkContext;
const context = this.choiceContext;
const forkContext = this.forkContext;
if (context.processed) {
@ -467,7 +467,7 @@ CodePathState.prototype = {
* This got segments already from the child choice context.
* Creates the next path from own true/false fork context.
*/
let prevForkContext =
const prevForkContext =
context.kind === "&&" ? context.trueForkContext :
/* kind === "||" */ context.falseForkContext;
@ -502,8 +502,8 @@ CodePathState.prototype = {
* @returns {void}
*/
makeIfConsequent: function() {
let context = this.choiceContext;
let forkContext = this.forkContext;
const context = this.choiceContext;
const forkContext = this.forkContext;
/*
* If any result were not transferred from child contexts,
@ -529,8 +529,8 @@ CodePathState.prototype = {
* @returns {void}
*/
makeIfAlternate: function() {
let context = this.choiceContext;
let forkContext = this.forkContext;
const context = this.choiceContext;
const forkContext = this.forkContext;
/*
* The head segments are the path of the `if` block.
@ -583,12 +583,12 @@ CodePathState.prototype = {
* @returns {void}
*/
popSwitchContext: function() {
let context = this.switchContext;
const context = this.switchContext;
this.switchContext = context.upper;
let forkContext = this.forkContext;
let brokenForkContext = this.popBreakContext().brokenForkContext;
const forkContext = this.forkContext;
const brokenForkContext = this.popBreakContext().brokenForkContext;
if (context.countForks === 0) {
@ -605,10 +605,10 @@ CodePathState.prototype = {
return;
}
let lastSegments = forkContext.head;
const lastSegments = forkContext.head;
this.forkBypassPath();
let lastCaseSegments = forkContext.head;
const lastCaseSegments = forkContext.head;
/*
* `brokenForkContext` is used to make the next segment.
@ -659,7 +659,7 @@ CodePathState.prototype = {
* @returns {void}
*/
makeSwitchCaseBody: function(isEmpty, isDefault) {
let context = this.switchContext;
const context = this.switchContext;
if (!context.hasCase) {
return;
@ -670,8 +670,8 @@ CodePathState.prototype = {
* The parent fork context has two segments.
* Those are from the current case and the body of the previous case.
*/
let parentForkContext = this.forkContext;
let forkContext = this.pushForkContext();
const parentForkContext = this.forkContext;
const forkContext = this.pushForkContext();
forkContext.add(parentForkContext.makeNext(0, -1));
@ -731,7 +731,7 @@ CodePathState.prototype = {
* @returns {void}
*/
popTryContext: function() {
let context = this.tryContext;
const context = this.tryContext;
this.tryContext = context.upper;
@ -747,19 +747,19 @@ CodePathState.prototype = {
* block.
*/
let returned = context.returnedForkContext;
let thrown = context.thrownForkContext;
const returned = context.returnedForkContext;
const thrown = context.thrownForkContext;
if (returned.empty && thrown.empty) {
return;
}
// Separate head to normal paths and leaving paths.
let headSegments = this.forkContext.head;
const headSegments = this.forkContext.head;
this.forkContext = this.forkContext.upper;
let normalSegments = headSegments.slice(0, headSegments.length / 2 | 0);
let leavingSegments = headSegments.slice(headSegments.length / 2 | 0);
const normalSegments = headSegments.slice(0, headSegments.length / 2 | 0);
const leavingSegments = headSegments.slice(headSegments.length / 2 | 0);
// Forwards the leaving path to upper contexts.
if (!returned.empty) {
@ -785,9 +785,9 @@ CodePathState.prototype = {
* @returns {void}
*/
makeCatchBlock: function() {
let context = this.tryContext;
let forkContext = this.forkContext;
let thrown = context.thrownForkContext;
const context = this.tryContext;
const forkContext = this.forkContext;
const thrown = context.thrownForkContext;
// Update state.
context.position = "catch";
@ -796,7 +796,7 @@ CodePathState.prototype = {
// Merge thrown paths.
thrown.add(forkContext.head);
let thrownSegments = thrown.makeNext(0, -1);
const thrownSegments = thrown.makeNext(0, -1);
// Fork to a bypass and the merged thrown path.
this.pushForkContext();
@ -814,11 +814,11 @@ CodePathState.prototype = {
* @returns {void}
*/
makeFinallyBlock: function() {
let context = this.tryContext;
const context = this.tryContext;
let forkContext = this.forkContext;
let returned = context.returnedForkContext;
let thrown = context.thrownForkContext;
let headOfLeavingSegments = forkContext.head;
const returned = context.returnedForkContext;
const thrown = context.thrownForkContext;
const headOfLeavingSegments = forkContext.head;
// Update state.
if (context.position === "catch") {
@ -843,11 +843,11 @@ CodePathState.prototype = {
* Create a parallel segment from merging returned and thrown.
* This segment will leave at the end of this finally block.
*/
let segments = forkContext.makeNext(-1, -1);
const segments = forkContext.makeNext(-1, -1);
let j;
for (let i = 0; i < forkContext.count; ++i) {
let prevSegsOfLeavingSegment = [headOfLeavingSegments[i]];
const prevSegsOfLeavingSegment = [headOfLeavingSegments[i]];
for (j = 0; j < returned.segmentsList.length; ++j) {
prevSegsOfLeavingSegment.push(returned.segmentsList[j][i]);
@ -872,13 +872,13 @@ CodePathState.prototype = {
* @returns {void}
*/
makeFirstThrowablePathInTryBlock: function() {
let forkContext = this.forkContext;
const forkContext = this.forkContext;
if (!forkContext.reachable) {
return;
}
let context = getThrowContext(this);
const context = getThrowContext(this);
if (context === this ||
context.position !== "try" ||
@ -905,8 +905,8 @@ CodePathState.prototype = {
* @returns {void}
*/
pushLoopContext: function(type, label) {
let forkContext = this.forkContext;
let breakContext = this.pushBreakContext(true, label);
const forkContext = this.forkContext;
const breakContext = this.pushBreakContext(true, label);
switch (type) {
case "WhileStatement":
@ -977,12 +977,12 @@ CodePathState.prototype = {
* @returns {void}
*/
popLoopContext: function() {
let context = this.loopContext;
const context = this.loopContext;
this.loopContext = context.upper;
let forkContext = this.forkContext;
let brokenForkContext = this.popBreakContext().brokenForkContext;
const forkContext = this.forkContext;
const brokenForkContext = this.popBreakContext().brokenForkContext;
let choiceContext;
// Creates a looped path.
@ -1048,9 +1048,9 @@ CodePathState.prototype = {
* @returns {void}
*/
makeWhileTest: function(test) {
let context = this.loopContext;
let forkContext = this.forkContext;
let testSegments = forkContext.makeNext(0, -1);
const context = this.loopContext;
const forkContext = this.forkContext;
const testSegments = forkContext.makeNext(0, -1);
// Update state.
context.test = test;
@ -1064,9 +1064,9 @@ CodePathState.prototype = {
* @returns {void}
*/
makeWhileBody: function() {
let context = this.loopContext;
let choiceContext = this.choiceContext;
let forkContext = this.forkContext;
const context = this.loopContext;
const choiceContext = this.choiceContext;
const forkContext = this.forkContext;
if (!choiceContext.processed) {
choiceContext.trueForkContext.add(forkContext.head);
@ -1086,9 +1086,9 @@ CodePathState.prototype = {
* @returns {void}
*/
makeDoWhileBody: function() {
let context = this.loopContext;
let forkContext = this.forkContext;
let bodySegments = forkContext.makeNext(-1, -1);
const context = this.loopContext;
const forkContext = this.forkContext;
const bodySegments = forkContext.makeNext(-1, -1);
// Update state.
context.entrySegments = bodySegments;
@ -1102,15 +1102,15 @@ CodePathState.prototype = {
* @returns {void}
*/
makeDoWhileTest: function(test) {
let context = this.loopContext;
let forkContext = this.forkContext;
const context = this.loopContext;
const forkContext = this.forkContext;
context.test = test;
// Creates paths of `continue` statements.
if (!context.continueForkContext.empty) {
context.continueForkContext.add(forkContext.head);
let testSegments = context.continueForkContext.makeNext(0, -1);
const testSegments = context.continueForkContext.makeNext(0, -1);
forkContext.replaceHead(testSegments);
}
@ -1123,10 +1123,10 @@ CodePathState.prototype = {
* @returns {void}
*/
makeForTest: function(test) {
let context = this.loopContext;
let forkContext = this.forkContext;
let endOfInitSegments = forkContext.head;
let testSegments = forkContext.makeNext(-1, -1);
const context = this.loopContext;
const forkContext = this.forkContext;
const endOfInitSegments = forkContext.head;
const testSegments = forkContext.makeNext(-1, -1);
// Update state.
context.test = test;
@ -1141,9 +1141,9 @@ CodePathState.prototype = {
* @returns {void}
*/
makeForUpdate: function() {
let context = this.loopContext;
let choiceContext = this.choiceContext;
let forkContext = this.forkContext;
const context = this.loopContext;
const choiceContext = this.choiceContext;
const forkContext = this.forkContext;
// Make the next paths of the test.
if (context.testSegments) {
@ -1156,7 +1156,7 @@ CodePathState.prototype = {
}
// Update state.
let updateSegments = forkContext.makeDisconnected(-1, -1);
const updateSegments = forkContext.makeDisconnected(-1, -1);
context.continueDestSegments = context.updateSegments = updateSegments;
forkContext.replaceHead(updateSegments);
@ -1168,9 +1168,9 @@ CodePathState.prototype = {
* @returns {void}
*/
makeForBody: function() {
let context = this.loopContext;
let choiceContext = this.choiceContext;
let forkContext = this.forkContext;
const context = this.loopContext;
const choiceContext = this.choiceContext;
const forkContext = this.forkContext;
// Update state.
if (context.updateSegments) {
@ -1200,7 +1200,7 @@ CodePathState.prototype = {
* If there is not the `test` part, the `body` path comes from the
* `init` part and the `update` part.
*/
let prevForkContext = ForkContext.newEmpty(forkContext);
const prevForkContext = ForkContext.newEmpty(forkContext);
prevForkContext.add(context.endOfInitSegments);
if (context.endOfUpdateSegments) {
@ -1220,9 +1220,9 @@ CodePathState.prototype = {
* @returns {void}
*/
makeForInOfLeft: function() {
let context = this.loopContext;
let forkContext = this.forkContext;
let leftSegments = forkContext.makeDisconnected(-1, -1);
const context = this.loopContext;
const forkContext = this.forkContext;
const leftSegments = forkContext.makeDisconnected(-1, -1);
// Update state.
context.prevSegments = forkContext.head;
@ -1237,12 +1237,12 @@ CodePathState.prototype = {
* @returns {void}
*/
makeForInOfRight: function() {
let context = this.loopContext;
let forkContext = this.forkContext;
let temp = ForkContext.newEmpty(forkContext);
const context = this.loopContext;
const forkContext = this.forkContext;
const temp = ForkContext.newEmpty(forkContext);
temp.add(context.prevSegments);
let rightSegments = temp.makeNext(-1, -1);
const rightSegments = temp.makeNext(-1, -1);
// Update state.
context.endOfLeftSegments = forkContext.head;
@ -1256,12 +1256,12 @@ CodePathState.prototype = {
* @returns {void}
*/
makeForInOfBody: function() {
let context = this.loopContext;
let forkContext = this.forkContext;
let temp = ForkContext.newEmpty(forkContext);
const context = this.loopContext;
const forkContext = this.forkContext;
const temp = ForkContext.newEmpty(forkContext);
temp.add(context.endOfLeftSegments);
let bodySegments = temp.makeNext(-1, -1);
const bodySegments = temp.makeNext(-1, -1);
// Make a path: `right` -> `left`.
makeLooped(this, forkContext.head, context.leftSegments);
@ -1299,14 +1299,14 @@ CodePathState.prototype = {
* @returns {Object} The removed context.
*/
popBreakContext: function() {
let context = this.breakContext;
let forkContext = this.forkContext;
const context = this.breakContext;
const forkContext = this.forkContext;
this.breakContext = context.upper;
// Process this context here for other than switches and loops.
if (!context.breakable) {
let brokenForkContext = context.brokenForkContext;
const brokenForkContext = context.brokenForkContext;
if (!brokenForkContext.empty) {
brokenForkContext.add(forkContext.head);
@ -1327,13 +1327,13 @@ CodePathState.prototype = {
* @returns {void}
*/
makeBreak: function(label) {
let forkContext = this.forkContext;
const forkContext = this.forkContext;
if (!forkContext.reachable) {
return;
}
let context = getBreakContext(this, label);
const context = getBreakContext(this, label);
/* istanbul ignore else: foolproof (syntax error) */
if (context) {
@ -1353,13 +1353,13 @@ CodePathState.prototype = {
* @returns {void}
*/
makeContinue: function(label) {
let forkContext = this.forkContext;
const forkContext = this.forkContext;
if (!forkContext.reachable) {
return;
}
let context = getContinueContext(this, label);
const context = getContinueContext(this, label);
/* istanbul ignore else: foolproof (syntax error) */
if (context) {
@ -1388,7 +1388,7 @@ CodePathState.prototype = {
* @returns {void}
*/
makeReturn: function() {
let forkContext = this.forkContext;
const forkContext = this.forkContext;
if (forkContext.reachable) {
getReturnContext(this).returnedForkContext.add(forkContext.head);
@ -1405,7 +1405,7 @@ CodePathState.prototype = {
* @returns {void}
*/
makeThrow: function() {
let forkContext = this.forkContext;
const forkContext = this.forkContext;
if (forkContext.reachable) {
getThrowContext(this).thrownForkContext.add(forkContext.head);
@ -1418,7 +1418,7 @@ CodePathState.prototype = {
* @returns {void}
*/
makeFinal: function() {
let segments = this.currentSegments;
const segments = this.currentSegments;
if (segments.length > 0 && segments[0].reachable) {
this.returnedForkContext.add(segments);

14
tools/eslint/lib/code-path-analysis/code-path.js

@ -9,8 +9,8 @@
// Requirements
//------------------------------------------------------------------------------
let CodePathState = require("./code-path-state");
let IdGenerator = require("./id-generator");
const CodePathState = require("./code-path-state");
const IdGenerator = require("./id-generator");
//------------------------------------------------------------------------------
// Public Interface
@ -130,18 +130,18 @@ CodePath.prototype = {
}
options = options || {};
let startSegment = options.first || this.internal.initialSegment;
let lastSegment = options.last;
const startSegment = options.first || this.internal.initialSegment;
const lastSegment = options.last;
let item = null;
let index = 0;
let end = 0;
let segment = null;
let visited = Object.create(null);
let stack = [[startSegment, 0]];
const visited = Object.create(null);
const stack = [[startSegment, 0]];
let skippedSegment = null;
let broken = false;
let controller = {
const controller = {
skip: function() {
if (stack.length <= 1) {
broken = true;

24
tools/eslint/lib/code-path-analysis/debug-helpers.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let debug = require("debug")("eslint:code-path");
const debug = require("debug")("eslint:code-path");
//------------------------------------------------------------------------------
// Helpers
@ -55,7 +55,7 @@ module.exports = {
*/
dumpState: !debug.enabled ? debug : /* istanbul ignore next */ function(node, state, leaving) {
for (let i = 0; i < state.currentSegments.length; ++i) {
let segInternal = state.currentSegments[i].internal;
const segInternal = state.currentSegments[i].internal;
if (leaving) {
segInternal.exitNodes.push(node);
@ -93,11 +93,11 @@ module.exports = {
text += "thrown[label=\"✘\",shape=circle,width=0.3,height=0.3,fixedsize];\n";
}
let traceMap = Object.create(null);
let arrows = this.makeDotArrows(codePath, traceMap);
const traceMap = Object.create(null);
const arrows = this.makeDotArrows(codePath, traceMap);
for (let id in traceMap) { // eslint-disable-line guard-for-in
let segment = traceMap[id];
for (const id in traceMap) { // eslint-disable-line guard-for-in
const segment = traceMap[id];
text += id + "[";
@ -144,22 +144,22 @@ module.exports = {
* @returns {string} A DOT code of the code path.
*/
makeDotArrows: function(codePath, traceMap) {
let stack = [[codePath.initialSegment, 0]];
let done = traceMap || Object.create(null);
const stack = [[codePath.initialSegment, 0]];
const done = traceMap || Object.create(null);
let lastId = codePath.initialSegment.id;
let text = "initial->" + codePath.initialSegment.id;
while (stack.length > 0) {
let item = stack.pop();
let segment = item[0];
let index = item[1];
const item = stack.pop();
const segment = item[0];
const index = item[1];
if (done[segment.id] && index === 0) {
continue;
}
done[segment.id] = segment;
let nextSegment = segment.allNextSegments[index];
const nextSegment = segment.allNextSegments[index];
if (!nextSegment) {
continue;

18
tools/eslint/lib/code-path-analysis/fork-context.js

@ -13,7 +13,7 @@
// Requirements
//------------------------------------------------------------------------------
let assert = require("assert"),
const assert = require("assert"),
CodePathSegment = require("./code-path-segment");
//------------------------------------------------------------------------------
@ -44,7 +44,7 @@ function isReachable(segment) {
* @returns {CodePathSegment[]} New segments.
*/
function makeSegments(context, begin, end, create) {
let list = context.segmentsList;
const list = context.segmentsList;
if (begin < 0) {
begin = list.length + begin;
@ -53,10 +53,10 @@ function makeSegments(context, begin, end, create) {
end = list.length + end;
}
let segments = [];
const segments = [];
for (let i = 0; i < context.count; ++i) {
let allPrevSegments = [];
const allPrevSegments = [];
for (let j = begin; j <= end; ++j) {
allPrevSegments.push(list[j][i]);
@ -80,7 +80,7 @@ function makeSegments(context, begin, end, create) {
*/
function mergeExtraSegments(context, segments) {
while (segments.length > context.count) {
let merged = [];
const merged = [];
for (let i = 0, length = segments.length / 2 | 0; i < length; ++i) {
merged.push(CodePathSegment.newNext(
@ -120,7 +120,7 @@ ForkContext.prototype = {
* @type {CodePathSegment[]}
*/
get head() {
let list = this.segmentsList;
const list = this.segmentsList;
return list.length === 0 ? [] : list[list.length - 1];
},
@ -138,7 +138,7 @@ ForkContext.prototype = {
* @type {boolean}
*/
get reachable() {
let segments = this.head;
const segments = this.head;
return segments.length > 0 && segments.some(isReachable);
},
@ -214,7 +214,7 @@ ForkContext.prototype = {
addAll: function(context) {
assert(context.count === this.count);
let source = context.segmentsList;
const source = context.segmentsList;
for (let i = 0; i < source.length; ++i) {
this.segmentsList.push(source[i]);
@ -238,7 +238,7 @@ ForkContext.prototype = {
* @returns {ForkContext} New fork context.
*/
ForkContext.newRoot = function(idGenerator) {
let context = new ForkContext(idGenerator, null, 1);
const context = new ForkContext(idGenerator, null, 1);
context.add([CodePathSegment.newRoot(idGenerator.next())]);

47
tools/eslint/lib/config.js

@ -9,28 +9,27 @@
// Requirements
//------------------------------------------------------------------------------
let path = require("path"),
const path = require("path"),
ConfigOps = require("./config/config-ops"),
ConfigFile = require("./config/config-file"),
Plugins = require("./config/plugins"),
FileFinder = require("./file-finder"),
debug = require("debug"),
userHome = require("user-home"),
isResolvable = require("is-resolvable"),
pathIsInside = require("path-is-inside");
const debug = require("debug")("eslint:config");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
let PERSONAL_CONFIG_DIR = userHome || null;
const PERSONAL_CONFIG_DIR = userHome || null;
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
debug = debug("eslint:config");
/**
* Check if item is an javascript object
* @param {*} item object to check for
@ -75,11 +74,10 @@ function loadConfig(configToLoad) {
* @private
*/
function getPersonalConfig() {
let config,
filename;
let config;
if (PERSONAL_CONFIG_DIR) {
filename = ConfigFile.getFilenameForDirectory(PERSONAL_CONFIG_DIR);
const filename = ConfigFile.getFilenameForDirectory(PERSONAL_CONFIG_DIR);
if (filename) {
debug("Using personal config");
@ -106,20 +104,16 @@ function hasRules(options) {
* @returns {Object} The local config object, or an empty object if there is no local config.
*/
function getLocalConfig(thisConfig, directory) {
const localConfigFiles = thisConfig.findLocalConfigFiles(directory),
numFiles = localConfigFiles.length,
projectConfigPath = ConfigFile.getFilenameForDirectory(thisConfig.options.cwd);
let found,
i,
localConfig,
localConfigFile,
config = {},
localConfigFiles = thisConfig.findLocalConfigFiles(directory),
numFiles = localConfigFiles.length,
rootPath,
projectConfigPath = ConfigFile.getFilenameForDirectory(thisConfig.options.cwd),
personalConfig;
rootPath;
for (i = 0; i < numFiles; i++) {
for (let i = 0; i < numFiles; i++) {
localConfigFile = localConfigFiles[i];
const localConfigFile = localConfigFiles[i];
// Don't consider the personal config file in the home directory,
// except if the home directory is the same as the current working directory
@ -133,7 +127,7 @@ function getLocalConfig(thisConfig, directory) {
}
debug("Loading " + localConfigFile);
localConfig = loadConfig(localConfigFile);
const localConfig = loadConfig(localConfigFile);
// Don't consider a local config file found if the config is null
if (!localConfig) {
@ -158,14 +152,14 @@ function getLocalConfig(thisConfig, directory) {
* - Otherwise, if no rules were manually passed in, throw and error.
* - Note: This function is not called if useEslintrc is false.
*/
personalConfig = getPersonalConfig();
const personalConfig = getPersonalConfig();
if (personalConfig) {
config = ConfigOps.merge(config, personalConfig);
} else if (!hasRules(thisConfig.options) && !thisConfig.options.baseConfig) {
// No config file, no manual configuration, and no rules, so error.
let noConfigError = new Error("No ESLint configuration found.");
const noConfigError = new Error("No ESLint configuration found.");
noConfigError.messageTemplate = "no-config-found";
noConfigError.messageData = {
@ -191,8 +185,6 @@ function getLocalConfig(thisConfig, directory) {
* @param {Object} options Options to be passed in
*/
function Config(options) {
let useConfig;
options = options || {};
this.ignore = options.ignore;
@ -217,14 +209,15 @@ function Config(options) {
* If user declares "foo", convert to "foo:false".
*/
this.globals = (options.globals || []).reduce(function(globals, def) {
let parts = def.split(":");
const parts = def.split(":");
globals[parts[0]] = (parts.length > 1 && parts[1] === "true");
return globals;
}, {});
useConfig = options.configFile;
const useConfig = options.configFile;
this.options = options;
if (useConfig) {
@ -244,9 +237,9 @@ function Config(options) {
* @returns {Object} config object
*/
Config.prototype.getConfig = function(filePath) {
const directory = filePath ? path.dirname(filePath) : this.options.cwd;
let config,
userConfig,
directory = filePath ? path.dirname(filePath) : this.options.cwd;
userConfig;
debug("Constructing config for " + (filePath ? filePath : "text"));

62
tools/eslint/lib/config/autoconfig.js

@ -9,26 +9,25 @@
// Requirements
//------------------------------------------------------------------------------
let lodash = require("lodash"),
debug = require("debug"),
const lodash = require("lodash"),
eslint = require("../eslint"),
configRule = require("./config-rule"),
ConfigOps = require("./config-ops"),
recConfig = require("../../conf/eslint.json");
const debug = require("debug")("eslint:autoconfig");
//------------------------------------------------------------------------------
// Data
//------------------------------------------------------------------------------
let MAX_CONFIG_COMBINATIONS = 17, // 16 combinations + 1 for severity only
const MAX_CONFIG_COMBINATIONS = 17, // 16 combinations + 1 for severity only
RECOMMENDED_CONFIG_NAME = "eslint:recommended";
//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------
debug = debug("eslint:autoconfig");
/**
* Information about a rule configuration, in the context of a Registry.
*
@ -89,7 +88,7 @@ Registry.prototype = {
* @returns {void}
*/
populateFromCoreRules: function() {
let rulesConfig = configRule.createCoreRuleConfigs();
const rulesConfig = configRule.createCoreRuleConfigs();
this.rules = makeRegistryItems(rulesConfig);
},
@ -109,8 +108,8 @@ Registry.prototype = {
* @returns {Object[]} "rules" configurations to use for linting
*/
buildRuleSets: function() {
let idx = 0,
ruleIds = Object.keys(this.rules),
let idx = 0;
const ruleIds = Object.keys(this.rules),
ruleSets = [];
/**
@ -122,7 +121,7 @@ Registry.prototype = {
* @param {string} rule The ruleId to add.
* @returns {void}
*/
let addRuleToRuleSet = function(rule) {
const addRuleToRuleSet = function(rule) {
/*
* This check ensures that there is a rule configuration and that
@ -130,7 +129,7 @@ Registry.prototype = {
* If it has too many configs, we will only use the most basic of
* the possible configurations.
*/
let hasFewCombos = (this.rules[rule].length <= MAX_CONFIG_COMBINATIONS);
const hasFewCombos = (this.rules[rule].length <= MAX_CONFIG_COMBINATIONS);
if (this.rules[rule][idx] && (hasFewCombos || this.rules[rule][idx].specificity <= 2)) {
@ -170,12 +169,12 @@ Registry.prototype = {
* @returns {void}
*/
stripFailingConfigs: function() {
let ruleIds = Object.keys(this.rules),
const ruleIds = Object.keys(this.rules),
newRegistry = new Registry();
newRegistry.rules = lodash.assign({}, this.rules);
newRegistry.rules = Object.assign({}, this.rules);
ruleIds.forEach(function(ruleId) {
let errorFreeItems = newRegistry.rules[ruleId].filter(function(registryItem) {
const errorFreeItems = newRegistry.rules[ruleId].filter(function(registryItem) {
return (registryItem.errorCount === 0);
});
@ -195,10 +194,10 @@ Registry.prototype = {
* @returns {void}
*/
stripExtraConfigs: function() {
let ruleIds = Object.keys(this.rules),
const ruleIds = Object.keys(this.rules),
newRegistry = new Registry();
newRegistry.rules = lodash.assign({}, this.rules);
newRegistry.rules = Object.assign({}, this.rules);
ruleIds.forEach(function(ruleId) {
newRegistry.rules[ruleId] = newRegistry.rules[ruleId].filter(function(registryItem) {
return (typeof registryItem.errorCount !== "undefined");
@ -216,11 +215,11 @@ Registry.prototype = {
* @returns {Registry} A registry of failing rules.
*/
getFailingRulesRegistry: function() {
let ruleIds = Object.keys(this.rules),
const ruleIds = Object.keys(this.rules),
failingRegistry = new Registry();
ruleIds.forEach(function(ruleId) {
let failingConfigs = this.rules[ruleId].filter(function(registryItem) {
const failingConfigs = this.rules[ruleId].filter(function(registryItem) {
return (registryItem.errorCount > 0);
});
@ -239,7 +238,7 @@ Registry.prototype = {
* @returns {Object} An eslint config with rules section populated
*/
createConfig: function() {
let ruleIds = Object.keys(this.rules),
const ruleIds = Object.keys(this.rules),
config = {rules: {}};
ruleIds.forEach(function(ruleId) {
@ -258,10 +257,10 @@ Registry.prototype = {
* @returns {Registry} A registry of rules
*/
filterBySpecificity: function(specificity) {
let ruleIds = Object.keys(this.rules),
const ruleIds = Object.keys(this.rules),
newRegistry = new Registry();
newRegistry.rules = lodash.assign({}, this.rules);
newRegistry.rules = Object.assign({}, this.rules);
ruleIds.forEach(function(ruleId) {
newRegistry.rules[ruleId] = this.rules[ruleId].filter(function(registryItem) {
return (registryItem.specificity === specificity);
@ -280,25 +279,20 @@ Registry.prototype = {
* @returns {Registry} New registry with errorCount populated
*/
lintSourceCode: function(sourceCodes, config, cb) {
let totalFilesLinting,
lintConfig,
ruleSets,
ruleSetIdx,
filenames,
let ruleSetIdx,
lintedRegistry;
lintedRegistry = new Registry();
lintedRegistry.rules = lodash.assign({}, this.rules);
lintedRegistry.rules = Object.assign({}, this.rules);
ruleSets = lintedRegistry.buildRuleSets();
const ruleSets = lintedRegistry.buildRuleSets();
lintedRegistry = lintedRegistry.stripExtraConfigs();
debug("Linting with all possible rule combinations");
filenames = Object.keys(sourceCodes);
totalFilesLinting = filenames.length * ruleSets.length;
const filenames = Object.keys(sourceCodes);
const totalFilesLinting = filenames.length * ruleSets.length;
filenames.forEach(function(filename) {
debug("Linting file: " + filename);
@ -306,8 +300,8 @@ Registry.prototype = {
ruleSetIdx = 0;
ruleSets.forEach(function(ruleSet) {
lintConfig = lodash.assign({}, config, {rules: ruleSet});
let lintResults = eslint.verify(sourceCodes[filename], lintConfig);
const lintConfig = Object.assign({}, config, {rules: ruleSet});
const lintResults = eslint.verify(sourceCodes[filename], lintConfig);
lintResults.forEach(function(result) {
@ -344,11 +338,11 @@ Registry.prototype = {
* @returns {Object} config object using `"extends": "eslint:recommended"`
*/
function extendFromRecommended(config) {
let newConfig = lodash.assign({}, config);
const newConfig = Object.assign({}, config);
ConfigOps.normalizeToStrings(newConfig);
let recRules = Object.keys(recConfig.rules).filter(function(ruleId) {
const recRules = Object.keys(recConfig.rules).filter(function(ruleId) {
return ConfigOps.isErrorSeverity(recConfig.rules[ruleId]);
});

51
tools/eslint/lib/config/config-file.js

@ -11,9 +11,9 @@
// Requirements
//------------------------------------------------------------------------------
let debug = require("debug"),
fs = require("fs"),
const fs = require("fs"),
path = require("path"),
shell = require("shelljs"),
ConfigOps = require("./config-ops"),
validator = require("./config-validator"),
Plugins = require("./plugins"),
@ -26,6 +26,7 @@ let debug = require("debug"),
defaultOptions = require("../../conf/eslint.json"),
requireUncached = require("require-uncached");
const debug = require("debug")("eslint:config-file");
//------------------------------------------------------------------------------
// Helpers
@ -48,7 +49,7 @@ function sortByKey(a, b) {
// Private
//------------------------------------------------------------------------------
let CONFIG_FILES = [
const CONFIG_FILES = [
".eslintrc.js",
".eslintrc.yaml",
".eslintrc.yml",
@ -57,9 +58,7 @@ let CONFIG_FILES = [
"package.json"
];
let resolver = new ModuleResolver();
debug = debug("eslint:config-file");
const resolver = new ModuleResolver();
/**
* Convenience wrapper for synchronously reading file contents.
@ -94,7 +93,7 @@ function loadYAMLConfigFile(filePath) {
debug("Loading YAML config file: " + filePath);
// lazy load YAML to improve performance when not used
let yaml = require("js-yaml");
const yaml = require("js-yaml");
try {
@ -137,7 +136,7 @@ function loadLegacyConfigFile(filePath) {
debug("Loading config file: " + filePath);
// lazy load YAML to improve performance when not used
let yaml = require("js-yaml");
const yaml = require("js-yaml");
try {
return yaml.safeLoad(stripComments(readFile(filePath))) || /* istanbul ignore next */ {};
@ -192,8 +191,8 @@ function loadPackageJSONConfigFile(filePath) {
* @private
*/
function loadConfigFile(file) {
let config,
filePath = file.filePath;
const filePath = file.filePath;
let config;
switch (path.extname(filePath)) {
case ".js":
@ -236,7 +235,7 @@ function loadConfigFile(file) {
function writeJSONConfigFile(config, filePath) {
debug("Writing JSON config file: " + filePath);
let content = stringify(config, {cmp: sortByKey, space: 4});
const content = stringify(config, {cmp: sortByKey, space: 4});
fs.writeFileSync(filePath, content, "utf8");
}
@ -252,9 +251,9 @@ function writeYAMLConfigFile(config, filePath) {
debug("Writing YAML config file: " + filePath);
// lazy load YAML to improve performance when not used
let yaml = require("js-yaml");
const yaml = require("js-yaml");
let content = yaml.safeDump(config, {sortKeys: true});
const content = yaml.safeDump(config, {sortKeys: true});
fs.writeFileSync(filePath, content, "utf8");
}
@ -269,7 +268,7 @@ function writeYAMLConfigFile(config, filePath) {
function writeJSConfigFile(config, filePath) {
debug("Writing JS config file: " + filePath);
let content = "module.exports = " + stringify(config, {cmp: sortByKey, space: 4}) + ";";
const content = "module.exports = " + stringify(config, {cmp: sortByKey, space: 4}) + ";";
fs.writeFileSync(filePath, content, "utf8");
}
@ -313,7 +312,7 @@ function write(config, filePath) {
function getBaseDir(configFilePath) {
// calculates the path of the project including ESLint as dependency
let projectPath = path.resolve(__dirname, "../../../");
const projectPath = path.resolve(__dirname, "../../../");
if (configFilePath && pathIsInside(configFilePath, projectPath)) {
@ -336,7 +335,7 @@ function getBaseDir(configFilePath) {
* @private
*/
function getLookupPath(configFilePath) {
let basedir = getBaseDir(configFilePath);
const basedir = getBaseDir(configFilePath);
return path.join(basedir, "node_modules");
}
@ -431,7 +430,7 @@ function normalizePackageName(name, prefix) {
* it's a scoped package
* package name is "eslint-config", or just a username
*/
let scopedPackageShortcutRegex = new RegExp("^(@[^\/]+)(?:\/(?:" + prefix + ")?)?$"),
const scopedPackageShortcutRegex = new RegExp("^(@[^\/]+)(?:\/(?:" + prefix + ")?)?$"),
scopedPackageNameRegex = new RegExp("^" + prefix + "(-|$)");
if (scopedPackageShortcutRegex.test(name)) {
@ -466,8 +465,8 @@ function resolve(filePath, relativeTo) {
let normalizedPackageName;
if (filePath.indexOf("plugin:") === 0) {
let packagePath = filePath.substr(7, filePath.lastIndexOf("/") - 7);
let configName = filePath.substr(filePath.lastIndexOf("/") + 1, filePath.length - filePath.lastIndexOf("/") - 1);
const packagePath = filePath.substr(7, filePath.lastIndexOf("/") - 7);
const configName = filePath.substr(filePath.lastIndexOf("/") + 1, filePath.length - filePath.lastIndexOf("/") - 1);
normalizedPackageName = normalizePackageName(packagePath, "eslint-plugin");
debug("Attempting to resolve " + normalizedPackageName);
@ -493,10 +492,10 @@ function resolve(filePath, relativeTo) {
* @private
*/
function load(filePath, applyEnvironments, relativeTo) {
let resolvedPath = resolve(filePath, relativeTo),
const resolvedPath = resolve(filePath, relativeTo),
dirname = path.dirname(resolvedPath.filePath),
lookupPath = getLookupPath(dirname),
config = loadConfigFile(resolvedPath);
lookupPath = getLookupPath(dirname);
let config = loadConfigFile(resolvedPath);
if (config) {
@ -564,12 +563,10 @@ module.exports = {
* or null if there is no configuration file in the directory.
*/
getFilenameForDirectory: function(directory) {
let filename;
for (let i = 0, len = CONFIG_FILES.length; i < len; i++) {
filename = path.join(directory, CONFIG_FILES[i]);
if (fs.existsSync(filename)) {
const filename = path.join(directory, CONFIG_FILES[i]);
if (shell.test("-f", filename)) {
return filename;
}
}

78
tools/eslint/lib/config/config-initializer.js

@ -9,9 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let util = require("util"),
debug = require("debug"),
lodash = require("lodash"),
const util = require("util"),
inquirer = require("inquirer"),
ProgressBar = require("progress"),
autoconfig = require("./autoconfig.js"),
@ -22,7 +20,7 @@ let util = require("util"),
recConfig = require("../../conf/eslint.json"),
log = require("../logging");
debug = debug("eslint:config-initializer");
const debug = require("debug")("eslint:config-initializer");
//------------------------------------------------------------------------------
// Private
@ -60,9 +58,7 @@ function writeFile(config, format) {
* @returns {void}
*/
function installModules(config) {
let modules = [],
installStatus,
modulesToInstall;
let modules = [];
// Create a list of modules which should be installed based on config
if (config.plugins) {
@ -82,11 +78,11 @@ function installModules(config) {
// Add eslint to list in case user does not have it installed locally
modules.unshift("eslint");
installStatus = npmUtil.checkDevDeps(modules);
const installStatus = npmUtil.checkDevDeps(modules);
// Install packages which aren't already installed
modulesToInstall = Object.keys(installStatus).filter(function(module) {
let notInstalled = installStatus[module] === false;
const modulesToInstall = Object.keys(installStatus).filter(function(module) {
const notInstalled = installStatus[module] === false;
if (module === "eslint" && notInstalled) {
log.info("Local ESLint installation not found.");
@ -113,31 +109,24 @@ function installModules(config) {
* @returns {Object} config object with configured rules
*/
function configureRules(answers, config) {
let BAR_TOTAL = 20,
BAR_SOURCE_CODE_TOTAL = 4;
let newConfig = lodash.assign({}, config),
bar,
patterns,
sourceCodes,
fileQty,
registry,
failingRegistry,
disabledConfigs = {},
singleConfigs,
specTwoConfigs,
specThreeConfigs,
defaultConfigs;
const BAR_TOTAL = 20,
BAR_SOURCE_CODE_TOTAL = 4,
newConfig = Object.assign({}, config),
disabledConfigs = {};
let sourceCodes,
registry;
// Set up a progress bar, as this process can take a long time
bar = new ProgressBar("Determining Config: :percent [:bar] :elapseds elapsed, eta :etas ", {
const bar = new ProgressBar("Determining Config: :percent [:bar] :elapseds elapsed, eta :etas ", {
width: 30,
total: BAR_TOTAL
});
bar.tick(0); // Shows the progress bar
// Get the SourceCode of all chosen files
patterns = answers.patterns.split(/[\s]+/);
const patterns = answers.patterns.split(/[\s]+/);
try {
sourceCodes = getSourceCodeOfFiles(patterns, { baseConfig: newConfig, useEslintrc: false }, function(total) {
bar.tick((BAR_SOURCE_CODE_TOTAL / total));
@ -146,7 +135,8 @@ function configureRules(answers, config) {
log.info("\n");
throw e;
}
fileQty = Object.keys(sourceCodes).length;
const fileQty = Object.keys(sourceCodes).length;
if (fileQty === 0) {
log.info("\n");
throw new Error("Automatic Configuration failed. No files were able to be parsed.");
@ -163,12 +153,12 @@ function configureRules(answers, config) {
debug("\nRegistry: " + util.inspect(registry.rules, {depth: null}));
// Create a list of recommended rules, because we don't want to disable them
let recRules = Object.keys(recConfig.rules).filter(function(ruleId) {
const recRules = Object.keys(recConfig.rules).filter(function(ruleId) {
return ConfigOps.isErrorSeverity(recConfig.rules[ruleId]);
});
// Find and disable rules which had no error-free configuration
failingRegistry = registry.getFailingRulesRegistry();
const failingRegistry = registry.getFailingRulesRegistry();
Object.keys(failingRegistry.rules).forEach(function(ruleId) {
@ -181,33 +171,33 @@ function configureRules(answers, config) {
// If there is only one config that results in no errors for a rule, we should use it.
// createConfig will only add rules that have one configuration in the registry.
singleConfigs = registry.createConfig().rules;
const singleConfigs = registry.createConfig().rules;
// The "sweet spot" for number of options in a config seems to be two (severity plus one option).
// Very often, a third option (usually an object) is available to address
// edge cases, exceptions, or unique situations. We will prefer to use a config with
// specificity of two.
specTwoConfigs = registry.filterBySpecificity(2).createConfig().rules;
const specTwoConfigs = registry.filterBySpecificity(2).createConfig().rules;
// Maybe a specific combination using all three options works
specThreeConfigs = registry.filterBySpecificity(3).createConfig().rules;
const specThreeConfigs = registry.filterBySpecificity(3).createConfig().rules;
// If all else fails, try to use the default (severity only)
defaultConfigs = registry.filterBySpecificity(1).createConfig().rules;
const defaultConfigs = registry.filterBySpecificity(1).createConfig().rules;
// Combine configs in reverse priority order (later take precedence)
newConfig.rules = lodash.assign({}, disabledConfigs, defaultConfigs, specThreeConfigs, specTwoConfigs, singleConfigs);
newConfig.rules = Object.assign({}, disabledConfigs, defaultConfigs, specThreeConfigs, specTwoConfigs, singleConfigs);
// Make sure progress bar has finished (floating point rounding)
bar.update(BAR_TOTAL);
// Log out some stats to let the user know what happened
let finalRuleIds = Object.keys(newConfig.rules),
totalRules = finalRuleIds.length;
let enabledRules = finalRuleIds.filter(function(ruleId) {
const finalRuleIds = Object.keys(newConfig.rules);
const totalRules = finalRuleIds.length;
const enabledRules = finalRuleIds.filter(function(ruleId) {
return (newConfig.rules[ruleId] !== 0);
}).length;
let resultMessage = [
const resultMessage = [
"\nEnabled " + enabledRules + " out of " + totalRules,
"rules based on " + fileQty,
"file" + ((fileQty === 1) ? "." : "s.")
@ -275,9 +265,9 @@ function processAnswers(answers) {
* @returns {Object} config object
*/
function getConfigForStyleGuide(guide) {
let guides = {
const guides = {
google: {extends: "google"},
airbnb: {extends: "airbnb", plugins: ["react"]},
airbnb: {extends: "airbnb", plugins: ["react", "jsx-a11y", "import"]},
standard: {extends: "standard", plugins: ["standard", "promise"]}
};
@ -419,7 +409,7 @@ function promptUser(callback) {
// early exit if you are using automatic style generation
if (earlyAnswers.source === "auto") {
try {
let combinedAnswers = lodash.assign({}, earlyAnswers, secondAnswers);
const combinedAnswers = Object.assign({}, earlyAnswers, secondAnswers);
config = processAnswers(combinedAnswers);
installModules(config);
@ -469,7 +459,7 @@ function promptUser(callback) {
}
], function(answers) {
try {
let totalAnswers = lodash.assign({}, earlyAnswers, secondAnswers, answers);
const totalAnswers = Object.assign({}, earlyAnswers, secondAnswers, answers);
config = processAnswers(totalAnswers);
installModules(config);
@ -488,7 +478,7 @@ function promptUser(callback) {
// Public Interface
//------------------------------------------------------------------------------
let init = {
const init = {
getConfigForStyleGuide: getConfigForStyleGuide,
processAnswers: processAnswers,
initializeConfig: /* istanbul ignore next */ function(callback) {

24
tools/eslint/lib/config/config-ops.js

@ -9,17 +9,15 @@
// Requirements
//------------------------------------------------------------------------------
let lodash = require("lodash"),
debug = require("debug"),
Environments = require("./environments");
const Environments = require("./environments");
const debug = require("debug")("eslint:config-ops");
//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------
debug = debug("eslint:config-ops");
let RULE_SEVERITY_STRINGS = ["off", "warn", "error"],
const RULE_SEVERITY_STRINGS = ["off", "warn", "error"],
RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce(function(map, value, index) {
map[value] = index;
return map;
@ -53,7 +51,7 @@ module.exports = {
*/
createEnvironmentConfig: function(env) {
let envConfig = this.createEmptyConfig();
const envConfig = this.createEmptyConfig();
if (env) {
@ -62,16 +60,16 @@ module.exports = {
Object.keys(env).filter(function(name) {
return env[name];
}).forEach(function(name) {
let environment = Environments.get(name);
const environment = Environments.get(name);
if (environment) {
debug("Creating config for environment " + name);
if (environment.globals) {
lodash.assign(envConfig.globals, environment.globals);
Object.assign(envConfig.globals, environment.globals);
}
if (environment.parserOptions) {
lodash.assign(envConfig.parserOptions, environment.parserOptions);
Object.assign(envConfig.parserOptions, environment.parserOptions);
}
}
});
@ -134,7 +132,7 @@ module.exports = {
* (https://github.com/KyleAMathews/deepmerge)
* and modified to meet our needs.
*/
let array = Array.isArray(src) || Array.isArray(target);
const array = Array.isArray(src) || Array.isArray(target);
let dst = array && [] || {};
combine = !!combine;
@ -202,7 +200,7 @@ module.exports = {
if (config.rules) {
Object.keys(config.rules).forEach(function(ruleId) {
let ruleConfig = config.rules[ruleId];
const ruleConfig = config.rules[ruleId];
if (typeof ruleConfig === "string") {
config.rules[ruleId] = RULE_SEVERITY[ruleConfig.toLowerCase()] || 0;
@ -224,7 +222,7 @@ module.exports = {
if (config.rules) {
Object.keys(config.rules).forEach(function(ruleId) {
let ruleConfig = config.rules[ruleId];
const ruleConfig = config.rules[ruleId];
if (typeof ruleConfig === "number") {
config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];

31
tools/eslint/lib/config/config-rule.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let rules = require("../rules"),
const rules = require("../rules"),
loadRules = require("../load-rules");
@ -41,7 +41,7 @@ function explodeArray(xs) {
* @returns {array} A mixture of the elements of the first and second arrays.
*/
function combineArrays(arr1, arr2) {
let res = [];
const res = [];
if (arr1.length === 0) {
return explodeArray(arr2);
@ -78,8 +78,8 @@ function combineArrays(arr1, arr2) {
* @returns {Array[]} Array of arrays of objects grouped by property
*/
function groupByProperty(objects) {
let groupedObj = objects.reduce(function(accumulator, obj) {
let prop = Object.keys(obj)[0];
const groupedObj = objects.reduce(function(accumulator, obj) {
const prop = Object.keys(obj)[0];
accumulator[prop] = accumulator[prop] ? accumulator[prop].concat(obj) : [obj];
return accumulator;
@ -144,7 +144,7 @@ function groupByProperty(objects) {
* @returns {Object[]} Combined objects for each combination of input properties and values
*/
function combinePropertyObjects(objArr1, objArr2) {
let res = [];
const res = [];
if (objArr1.length === 0) {
return objArr2;
@ -154,9 +154,9 @@ function combinePropertyObjects(objArr1, objArr2) {
}
objArr1.forEach(function(obj1) {
objArr2.forEach(function(obj2) {
let combinedObj = {};
let obj1Props = Object.keys(obj1);
let obj2Props = Object.keys(obj2);
const combinedObj = {};
const obj1Props = Object.keys(obj1);
const obj2Props = Object.keys(obj2);
obj1Props.forEach(function(prop1) {
combinedObj[prop1] = obj1[prop1];
@ -229,13 +229,12 @@ RuleConfigSet.prototype = {
* @returns {void}
*/
addObject: function(obj) {
let objectConfigSet = {
const objectConfigSet = {
objectConfigs: [],
add: function(property, values) {
let optionObj;
for (let idx = 0; idx < values.length; idx++) {
optionObj = {};
const optionObj = {};
optionObj[property] = values[idx];
this.objectConfigs.push(optionObj);
}
@ -274,7 +273,7 @@ RuleConfigSet.prototype = {
* @returns {array[]} Valid rule configurations
*/
function generateConfigsFromSchema(schema) {
let configSet = new RuleConfigSet();
const configSet = new RuleConfigSet();
if (Array.isArray(schema)) {
schema.forEach(function(opt) {
@ -301,11 +300,11 @@ function generateConfigsFromSchema(schema) {
* @returns {rulesConfig} Hash of rule names and arrays of possible configurations
*/
function createCoreRuleConfigs() {
let ruleList = loadRules();
const ruleList = loadRules();
return Object.keys(ruleList).reduce(function(accumulator, id) {
let rule = rules.get(id);
let schema = (typeof rule === "function") ? rule.schema : rule.meta.schema;
const rule = rules.get(id);
const schema = (typeof rule === "function") ? rule.schema : rule.meta.schema;
accumulator[id] = generateConfigsFromSchema(schema);
return accumulator;

13
tools/eslint/lib/config/config-validator.js

@ -9,12 +9,12 @@
// Requirements
//------------------------------------------------------------------------------
let rules = require("../rules"),
const rules = require("../rules"),
Environments = require("./environments"),
schemaValidator = require("is-my-json-valid"),
util = require("util");
let validators = {
const validators = {
rules: Object.create(null)
};
@ -28,7 +28,7 @@ let validators = {
* @returns {Object} JSON Schema for the rule's options.
*/
function getRuleOptionsSchema(id) {
let rule = rules.get(id),
const rule = rules.get(id),
schema = rule && rule.schema || rule && rule.meta && rule.meta.schema;
// Given a tuple of schemas, insert warning level at the beginning
@ -61,11 +61,10 @@ function getRuleOptionsSchema(id) {
* @returns {void}
*/
function validateRuleOptions(id, options, source) {
const schema = getRuleOptionsSchema(id);
let validateRule = validators.rules[id],
message,
severity,
localOptions,
schema = getRuleOptionsSchema(id),
validSeverity = true;
if (!validateRule && schema) {
@ -92,7 +91,7 @@ function validateRuleOptions(id, options, source) {
}
if ((validateRule && validateRule.errors) || !validSeverity) {
message = [
const message = [
source, ":\n",
"\tConfiguration for rule \"", id, "\" is invalid:\n"
];
@ -137,7 +136,7 @@ function validateEnvironment(environment, source) {
if (typeof environment === "object") {
Object.keys(environment).forEach(function(env) {
if (!Environments.get(env)) {
let message = [
const message = [
source, ":\n",
"\tEnvironment key \"", env, "\" is unknown\n"
];

2
tools/eslint/lib/config/environments.js

@ -8,7 +8,7 @@
// Requirements
//------------------------------------------------------------------------------
let envs = require("../../conf/environments");
const envs = require("../../conf/environments");
//------------------------------------------------------------------------------
// Private

17
tools/eslint/lib/config/plugins.js

@ -8,19 +8,18 @@
// Requirements
//------------------------------------------------------------------------------
let debug = require("debug"),
Environments = require("./environments"),
const Environments = require("./environments"),
rules = require("../rules");
const debug = require("debug")("eslint:plugins");
//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------
debug = debug("eslint:plugins");
let plugins = Object.create(null);
let PLUGIN_NAME_PREFIX = "eslint-plugin-",
const PLUGIN_NAME_PREFIX = "eslint-plugin-",
NAMESPACE_REGEX = /^@.*\//i;
/**
@ -67,7 +66,7 @@ module.exports = {
* @returns {void}
*/
define: function(pluginName, plugin) {
let pluginNameWithoutNamespace = removeNamespace(pluginName),
const pluginNameWithoutNamespace = removeNamespace(pluginName),
pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace);
plugins[pluginNameWithoutPrefix] = plugin;
@ -104,10 +103,10 @@ module.exports = {
* @throws {Error} If the plugin cannot be loaded.
*/
load: function(pluginName) {
let pluginNamespace = getNamespace(pluginName),
const pluginNamespace = getNamespace(pluginName),
pluginNameWithoutNamespace = removeNamespace(pluginName),
pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace),
plugin = null;
pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace);
let plugin = null;
if (!plugins[pluginNameWithoutPrefix]) {
try {

140
tools/eslint/lib/eslint.js

@ -9,11 +9,10 @@
// Requirements
//------------------------------------------------------------------------------
let assert = require("assert"),
const assert = require("assert"),
EventEmitter = require("events").EventEmitter,
escope = require("escope"),
levn = require("levn"),
lodash = require("lodash"),
blankScriptAST = require("../conf/blank-script.json"),
DEFAULT_PARSER = require("../conf/eslint.json").parser,
replacements = require("../conf/replacements.json"),
@ -41,7 +40,7 @@ let assert = require("assert"),
* @returns {Object} Result map object of names and boolean values
*/
function parseBooleanConfig(string, comment) {
let items = {};
const items = {};
// Collapse whitespace around `:` and `,` to make parsing easier
string = string.replace(/\s*([:,])\s*/g, "$1");
@ -50,8 +49,8 @@ function parseBooleanConfig(string, comment) {
if (!name) {
return;
}
let pos = name.indexOf(":"),
value;
const pos = name.indexOf(":");
let value;
if (pos !== -1) {
value = name.substring(pos + 1, name.length);
@ -122,7 +121,7 @@ function parseJsonConfig(string, location, messages) {
* @returns {Object} Result map of values and true values
*/
function parseListConfig(string) {
let items = {};
const items = {};
// Collapse whitespace around ,
string = string.replace(/\s*,\s*/g, ",");
@ -147,27 +146,27 @@ function parseListConfig(string) {
* @returns {void}
*/
function addDeclaredGlobals(program, globalScope, config) {
let declaredGlobals = {},
const declaredGlobals = {},
exportedGlobals = {},
explicitGlobals = {},
builtin = Environments.get("builtin");
lodash.assign(declaredGlobals, builtin);
Object.assign(declaredGlobals, builtin);
Object.keys(config.env).forEach(function(name) {
if (config.env[name]) {
let env = Environments.get(name),
const env = Environments.get(name),
environmentGlobals = env && env.globals;
if (environmentGlobals) {
lodash.assign(declaredGlobals, environmentGlobals);
Object.assign(declaredGlobals, environmentGlobals);
}
}
});
lodash.assign(exportedGlobals, config.exported);
lodash.assign(declaredGlobals, config.globals);
lodash.assign(explicitGlobals, config.astGlobals);
Object.assign(exportedGlobals, config.exported);
Object.assign(declaredGlobals, config.globals);
Object.assign(explicitGlobals, config.astGlobals);
Object.keys(declaredGlobals).forEach(function(name) {
let variable = globalScope.set.get(name);
@ -196,7 +195,7 @@ function addDeclaredGlobals(program, globalScope, config) {
// mark all exported variables as such
Object.keys(exportedGlobals).forEach(function(name) {
let variable = globalScope.set.get(name);
const variable = globalScope.set.get(name);
if (variable) {
variable.eslintUsed = true;
@ -209,8 +208,8 @@ function addDeclaredGlobals(program, globalScope, config) {
* references and remove the ones that were added by configuration.
*/
globalScope.through = globalScope.through.filter(function(reference) {
let name = reference.identifier.name;
let variable = globalScope.set.get(name);
const name = reference.identifier.name;
const variable = globalScope.set.get(name);
if (variable) {
@ -312,12 +311,12 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
rules: {},
env: {}
};
let commentRules = {};
const commentRules = {};
ast.comments.forEach(function(comment) {
let value = comment.value.trim();
let match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(value);
const match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(value);
if (match) {
value = value.substring(match.index + match[1].length);
@ -325,16 +324,16 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
if (comment.type === "Block") {
switch (match[1]) {
case "exported":
lodash.assign(commentConfig.exported, parseBooleanConfig(value, comment));
Object.assign(commentConfig.exported, parseBooleanConfig(value, comment));
break;
case "globals":
case "global":
lodash.assign(commentConfig.astGlobals, parseBooleanConfig(value, comment));
Object.assign(commentConfig.astGlobals, parseBooleanConfig(value, comment));
break;
case "eslint-env":
lodash.assign(commentConfig.env, parseListConfig(value));
Object.assign(commentConfig.env, parseListConfig(value));
break;
case "eslint-disable":
@ -349,7 +348,7 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
const items = parseJsonConfig(value, comment.loc, messages);
Object.keys(items).forEach(function(name) {
let ruleValue = items[name];
const ruleValue = items[name];
validator.validateRuleOptions(name, ruleValue, filename + " line " + comment.loc.start.line);
commentRules[name] = ruleValue;
@ -373,13 +372,13 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
// apply environment configs
Object.keys(commentConfig.env).forEach(function(name) {
let env = Environments.get(name);
const env = Environments.get(name);
if (env) {
commentConfig = ConfigOps.merge(commentConfig, env);
}
});
lodash.assign(commentConfig.rules, commentRules);
Object.assign(commentConfig.rules, commentRules);
return ConfigOps.merge(config, commentConfig);
}
@ -395,7 +394,7 @@ function isDisabledByReportingConfig(reportingConfig, ruleId, location) {
for (let i = 0, c = reportingConfig.length; i < c; i++) {
let ignore = reportingConfig[i];
const ignore = reportingConfig[i];
if ((!ignore.rule || ignore.rule === ruleId) &&
(location.line > ignore.start.line || (location.line === ignore.start.line && location.column >= ignore.start.column)) &&
@ -417,13 +416,12 @@ function prepareConfig(config) {
config.globals = config.globals || config.global || {};
delete config.global;
let copiedRules = {},
parserOptions = {},
preparedConfig;
const copiedRules = {};
let parserOptions = {};
if (typeof config.rules === "object") {
Object.keys(config.rules).forEach(function(k) {
let rule = config.rules[k];
const rule = config.rules[k];
if (rule === null) {
throw new Error("Invalid config for rule '" + k + "'\.");
@ -439,7 +437,7 @@ function prepareConfig(config) {
// merge in environment parserOptions
if (typeof config.env === "object") {
Object.keys(config.env).forEach(function(envName) {
let env = Environments.get(envName);
const env = Environments.get(envName);
if (config.env[envName] && env && env.parserOptions) {
parserOptions = ConfigOps.merge(parserOptions, env.parserOptions);
@ -447,7 +445,7 @@ function prepareConfig(config) {
});
}
preparedConfig = {
const preparedConfig = {
rules: copiedRules,
parser: config.parser || DEFAULT_PARSER,
globals: ConfigOps.merge({}, config.globals),
@ -507,7 +505,7 @@ function createStubRule(message) {
*/
function getRuleReplacementMessage(ruleId) {
if (ruleId in replacements.rules) {
let newRules = replacements.rules[ruleId];
const newRules = replacements.rules[ruleId];
return "Rule \'" + ruleId + "\' was removed and replaced by: " + newRules.join(", ");
}
@ -515,7 +513,7 @@ function getRuleReplacementMessage(ruleId) {
return null;
}
let eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g;
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g;
/**
* Checks whether or not there is a comment which has "eslint-env *" in a given text.
@ -528,7 +526,7 @@ function findEslintEnv(text) {
eslintEnvPattern.lastIndex = 0;
while ((match = eslintEnvPattern.exec(text))) {
retv = lodash.assign(retv || {}, parseListConfig(match[1]));
retv = Object.assign(retv || {}, parseListConfig(match[1]));
}
return retv;
@ -563,8 +561,8 @@ function stripUnicodeBOM(text) {
*/
module.exports = (function() {
let api = Object.create(new EventEmitter()),
messages = [],
const api = Object.create(new EventEmitter());
let messages = [],
currentConfig = null,
currentScopes = null,
scopeMap = null,
@ -613,7 +611,7 @@ module.exports = (function() {
// merge in any additional parser options
if (config.parserOptions) {
parserOptions = lodash.assign({}, config.parserOptions, parserOptions);
parserOptions = Object.assign({}, config.parserOptions, parserOptions);
}
/*
@ -627,8 +625,8 @@ module.exports = (function() {
} catch (ex) {
// If the message includes a leading line number, strip it:
let message = ex.message.replace(/^line \d+:/i, "").trim();
let source = (ex.lineNumber) ? SourceCode.splitLines(text)[ex.lineNumber - 1] : null;
const message = ex.message.replace(/^line \d+:/i, "").trim();
const source = (ex.lineNumber) ? SourceCode.splitLines(text)[ex.lineNumber - 1] : null;
messages.push({
ruleId: null,
@ -718,13 +716,10 @@ module.exports = (function() {
* @returns {Object[]} The results as an array of messages or null if no messages.
*/
api.verify = function(textOrSourceCode, config, filenameOrOptions, saveState) {
const text = (typeof textOrSourceCode === "string") ? textOrSourceCode : null;
let ast,
shebang,
ecmaFeatures,
ecmaVersion,
allowInlineConfig,
text = (typeof textOrSourceCode === "string") ? textOrSourceCode : null;
allowInlineConfig;
// evaluate arguments
if (typeof filenameOrOptions === "object") {
@ -740,14 +735,14 @@ module.exports = (function() {
}
// search and apply "eslint-env *".
let envInFile = findEslintEnv(text || textOrSourceCode.text);
const envInFile = findEslintEnv(text || textOrSourceCode.text);
if (envInFile) {
if (!config || !config.env) {
config = lodash.assign({}, config || {}, {env: envInFile});
config = Object.assign({}, config || {}, {env: envInFile});
} else {
config = lodash.assign({}, config);
config.env = lodash.assign({}, config.env, envInFile);
config = Object.assign({}, config);
config.env = Object.assign({}, config.env, envInFile);
}
}
@ -795,15 +790,12 @@ module.exports = (function() {
Object.keys(config.rules).filter(function(key) {
return getRuleSeverity(config.rules[key]) > 0;
}).forEach(function(key) {
let ruleCreator,
severity,
options,
rule;
let ruleCreator;
ruleCreator = rules.get(key);
if (!ruleCreator) {
let replacementMsg = getRuleReplacementMessage(key);
const replacementMsg = getRuleReplacementMessage(key);
if (replacementMsg) {
ruleCreator = createStubRule(replacementMsg);
@ -813,15 +805,15 @@ module.exports = (function() {
rules.define(key, ruleCreator);
}
severity = getRuleSeverity(config.rules[key]);
options = getRuleOptions(config.rules[key]);
const severity = getRuleSeverity(config.rules[key]);
const options = getRuleOptions(config.rules[key]);
try {
let ruleContext = new RuleContext(
const ruleContext = new RuleContext(
key, api, severity, options,
config.settings, config.parserOptions, config.parser, ruleCreator.meta);
rule = ruleCreator.create ? ruleCreator.create(ruleContext) :
const rule = ruleCreator.create ? ruleCreator.create(ruleContext) :
ruleCreator(ruleContext);
// add all the node types as listeners
@ -841,8 +833,8 @@ module.exports = (function() {
currentConfig = config;
traverser = new Traverser();
ecmaFeatures = currentConfig.parserOptions.ecmaFeatures || {};
ecmaVersion = currentConfig.parserOptions.ecmaVersion || 5;
const ecmaFeatures = currentConfig.parserOptions.ecmaFeatures || {};
const ecmaVersion = currentConfig.parserOptions.ecmaVersion || 5;
// gather scope data that may be needed by the rules
scopeManager = escope.analyze(ast, {
@ -863,7 +855,7 @@ module.exports = (function() {
scopeMap = [];
currentScopes.forEach(function(scope, index) {
let range = scope.block.range[0];
const range = scope.block.range[0];
/*
* Sometimes two scopes are returned for a given node. This is
@ -910,7 +902,7 @@ module.exports = (function() {
// sort by line and column
messages.sort(function(a, b) {
let lineDiff = a.line - b.line;
const lineDiff = a.line - b.line;
if (lineDiff === 0) {
return a.column - b.column;
@ -953,7 +945,7 @@ module.exports = (function() {
}
// Store end location.
let endLocation = location.end;
const endLocation = location.end;
location = location.start || location;
@ -972,7 +964,7 @@ module.exports = (function() {
});
}
let problem = {
const problem = {
ruleId: ruleId,
severity: severity,
message: message,
@ -1011,7 +1003,7 @@ module.exports = (function() {
};
// methods that exist on SourceCode object
let externalMethods = {
const externalMethods = {
getSource: "getText",
getSourceLines: "getLines",
getAllComments: "getAllComments",
@ -1033,7 +1025,7 @@ module.exports = (function() {
// copy over methods
Object.keys(externalMethods).forEach(function(methodName) {
let exMethodName = externalMethods[methodName];
const exMethodName = externalMethods[methodName];
// All functions expected to have less arguments than 5.
api[methodName] = function(a, b, c, d, e) {
@ -1057,14 +1049,13 @@ module.exports = (function() {
* @returns {Object} An object representing the current node's scope.
*/
api.getScope = function() {
let parents = traverser.parents(),
scope = currentScopes[0];
const parents = traverser.parents();
// Don't do this for Program nodes - they have no parents
if (parents.length) {
// if current node introduces a scope, add it to the list
let current = traverser.current();
const current = traverser.current();
if (currentConfig.parserOptions.ecmaVersion >= 6) {
if (["BlockStatement", "SwitchStatement", "CatchClause", "FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"].indexOf(current.type) >= 0) {
@ -1080,7 +1071,8 @@ module.exports = (function() {
for (let i = parents.length - 1; i >= 0; --i) {
// Get the innermost scope
scope = scopeManager.acquire(parents[i], true);
const scope = scopeManager.acquire(parents[i], true);
if (scope) {
if (scope.type === "function-expression-name") {
return scope.childScopes[0];
@ -1103,10 +1095,9 @@ module.exports = (function() {
* false if not.
*/
api.markVariableAsUsed = function(name) {
const hasGlobalReturn = currentConfig.parserOptions.ecmaFeatures && currentConfig.parserOptions.ecmaFeatures.globalReturn,
specialScope = hasGlobalReturn || currentConfig.parserOptions.sourceType === "module";
let scope = this.getScope(),
hasGlobalReturn = currentConfig.parserOptions.ecmaFeatures && currentConfig.parserOptions.ecmaFeatures.globalReturn,
specialScope = hasGlobalReturn || currentConfig.parserOptions.sourceType === "module",
variables,
i,
len;
@ -1116,7 +1107,8 @@ module.exports = (function() {
}
do {
variables = scope.variables;
const variables = scope.variables;
for (i = 0, len = variables.length; i < len; i++) {
if (variables[i].name === name) {
variables[i].eslintUsed = true;
@ -1147,7 +1139,7 @@ module.exports = (function() {
* @param {Function} ruleModule Function from context to object mapping AST node types to event handlers
* @returns {void}
*/
let defineRule = api.defineRule = function(ruleId, ruleModule) {
const defineRule = api.defineRule = function(ruleId, ruleModule) {
rules.define(ruleId, ruleModule);
};

31
tools/eslint/lib/file-finder.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let fs = require("fs"),
const fs = require("fs"),
path = require("path");
//------------------------------------------------------------------------------
@ -55,11 +55,11 @@ function FileFinder(files, cwd) {
* @returns {Object} Hashmap of filenames
*/
function normalizeDirectoryEntries(entries, directory, supportedConfigs) {
let fileHash = {};
const fileHash = {};
entries.forEach(function(entry) {
if (supportedConfigs.indexOf(entry) >= 0) {
let resolvedEntry = path.resolve(directory, entry);
const resolvedEntry = path.resolve(directory, entry);
if (fs.statSync(resolvedEntry).isFile()) {
fileHash[entry] = resolvedEntry;
@ -79,14 +79,7 @@ function normalizeDirectoryEntries(entries, directory, supportedConfigs) {
* @returns {string[]} The file paths found.
*/
FileFinder.prototype.findAllInDirectoryAndParents = function(directory) {
let cache = this.cache,
child,
dirs,
fileNames,
filePath,
i,
j,
searched;
const cache = this.cache;
if (directory) {
directory = path.resolve(this.cwd, directory);
@ -98,24 +91,24 @@ FileFinder.prototype.findAllInDirectoryAndParents = function(directory) {
return cache[directory];
}
dirs = [];
searched = 0;
fileNames = this.fileNames;
const dirs = [];
const fileNames = this.fileNames;
let searched = 0;
do {
dirs[searched++] = directory;
cache[directory] = [];
let filesMap = normalizeDirectoryEntries(getDirectoryEntries(directory), directory, fileNames);
const filesMap = normalizeDirectoryEntries(getDirectoryEntries(directory), directory, fileNames);
if (Object.keys(filesMap).length) {
for (let k = 0; k < fileNames.length; k++) {
if (filesMap[fileNames[k]]) {
filePath = filesMap[fileNames[k]];
const filePath = filesMap[fileNames[k]];
// Add the file path to the cache of each directory searched.
for (j = 0; j < searched; j++) {
for (let j = 0; j < searched; j++) {
cache[dirs[j]].push(filePath);
}
@ -123,7 +116,7 @@ FileFinder.prototype.findAllInDirectoryAndParents = function(directory) {
}
}
}
child = directory;
const child = directory;
// Assign parent directory to directory.
directory = path.dirname(directory);
@ -134,7 +127,7 @@ FileFinder.prototype.findAllInDirectoryAndParents = function(directory) {
} while (!cache.hasOwnProperty(directory));
// Add what has been cached previously to the cache of each directory searched.
for (i = 0; i < searched; i++) {
for (let i = 0; i < searched; i++) {
dirs.push.apply(cache[dirs[i]], cache[directory]);
}

4
tools/eslint/lib/formatters/checkstyle.js

@ -4,7 +4,7 @@
*/
"use strict";
let xmlEscape = require("../util/xml-escape");
const xmlEscape = require("../util/xml-escape");
//------------------------------------------------------------------------------
// Helper Functions
@ -36,7 +36,7 @@ module.exports = function(results) {
output += "<checkstyle version=\"4.3\">";
results.forEach(function(result) {
let messages = result.messages;
const messages = result.messages;
output += "<file name=\"" + xmlEscape(result.filePath) + "\">";

2
tools/eslint/lib/formatters/compact.js

@ -34,7 +34,7 @@ module.exports = function(results) {
results.forEach(function(result) {
let messages = result.messages;
const messages = result.messages;
total += messages.length;

21
tools/eslint/lib/formatters/html.js

@ -4,17 +4,17 @@
*/
"use strict";
let lodash = require("lodash");
let fs = require("fs");
let path = require("path");
const lodash = require("lodash");
const fs = require("fs");
const path = require("path");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
let pageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-page.html"), "utf-8"));
let messageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-message.html"), "utf-8"));
let resultTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-result.html"), "utf-8"));
const pageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-page.html"), "utf-8"));
const messageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-message.html"), "utf-8"));
const resultTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-result.html"), "utf-8"));
/**
* Given a word and a count, append an s if count is not one.
@ -33,7 +33,7 @@ function pluralize(word, count) {
* @returns {string} The formatted string, pluralized where necessary
*/
function renderSummary(totalErrors, totalWarnings) {
let totalProblems = totalErrors + totalWarnings;
const totalProblems = totalErrors + totalWarnings;
let renderedText = totalProblems + " " + pluralize("problem", totalProblems);
if (totalProblems !== 0) {
@ -71,11 +71,8 @@ function renderMessages(messages, parentIndex) {
* @returns {string} HTML (table row) describing a message.
*/
return lodash.map(messages, function(message) {
let lineNumber,
columnNumber;
lineNumber = message.line || 0;
columnNumber = message.column || 0;
const lineNumber = message.line || 0;
const columnNumber = message.column || 0;
return messageTemplate({
parentIndex: parentIndex,

4
tools/eslint/lib/formatters/jslint-xml.js

@ -4,7 +4,7 @@
*/
"use strict";
let xmlEscape = require("../util/xml-escape");
const xmlEscape = require("../util/xml-escape");
//------------------------------------------------------------------------------
// Public Interface
@ -18,7 +18,7 @@ module.exports = function(results) {
output += "<jslint>";
results.forEach(function(result) {
let messages = result.messages;
const messages = result.messages;
output += "<file name=\"" + result.filePath + "\">";

6
tools/eslint/lib/formatters/junit.js

@ -4,7 +4,7 @@
*/
"use strict";
let xmlEscape = require("../util/xml-escape");
const xmlEscape = require("../util/xml-escape");
//------------------------------------------------------------------------------
// Helper Functions
@ -37,14 +37,14 @@ module.exports = function(results) {
results.forEach(function(result) {
let messages = result.messages;
const messages = result.messages;
if (messages.length) {
output += "<testsuite package=\"org.eslint\" time=\"0\" tests=\"" + messages.length + "\" errors=\"" + messages.length + "\" name=\"" + result.filePath + "\">\n";
}
messages.forEach(function(message) {
let type = message.fatal ? "error" : "failure";
const type = message.fatal ? "error" : "failure";
output += "<testcase time=\"0\" name=\"org.eslint." + (message.ruleId || "unknown") + "\">";
output += "<" + type + " message=\"" + xmlEscape(message.message || "") + "\">";

4
tools/eslint/lib/formatters/stylish.js

@ -4,7 +4,7 @@
*/
"use strict";
let chalk = require("chalk"),
const chalk = require("chalk"),
table = require("text-table");
//------------------------------------------------------------------------------
@ -34,7 +34,7 @@ module.exports = function(results) {
summaryColor = "yellow";
results.forEach(function(result) {
let messages = result.messages;
const messages = result.messages;
if (messages.length === 0) {
return;

12
tools/eslint/lib/formatters/table.js

@ -8,12 +8,8 @@
// Requirements
//------------------------------------------------------------------------------
let chalk,
table,
pluralize;
chalk = require("chalk");
table = require("table").default;
const chalk = require("chalk"),
table = require("table").default,
pluralize = require("pluralize");
//------------------------------------------------------------------------------
@ -26,9 +22,7 @@ pluralize = require("pluralize");
* @returns {string} A text table.
*/
function drawTable(messages) {
let rows;
rows = [];
const rows = [];
if (messages.length === 0) {
return "";

8
tools/eslint/lib/formatters/tap.js

@ -4,7 +4,7 @@
*/
"use strict";
let yaml = require("js-yaml");
const yaml = require("js-yaml");
//------------------------------------------------------------------------------
// Helper Functions
@ -29,7 +29,7 @@ function getMessageType(message) {
* @returns {string} diagnostics string with YAML embedded - TAP version 13 compliant
*/
function outputDiagnostics(diagnostic) {
let prefix = " ";
const prefix = " ";
let output = prefix + "---\n";
output += prefix + yaml.safeDump(diagnostic).split("\n").join("\n" + prefix);
@ -45,7 +45,7 @@ module.exports = function(results) {
let output = "TAP version 13\n1.." + results.length + "\n";
results.forEach(function(result, id) {
let messages = result.messages;
const messages = result.messages;
let testResult = "ok";
let diagnostics = {};
@ -53,7 +53,7 @@ module.exports = function(results) {
testResult = "not ok";
messages.forEach(function(message) {
let diagnostic = {
const diagnostic = {
message: message.message,
severity: getMessageType(message),
data: {

2
tools/eslint/lib/formatters/unix.js

@ -33,7 +33,7 @@ module.exports = function(results) {
results.forEach(function(result) {
let messages = result.messages;
const messages = result.messages;
total += messages.length;

2
tools/eslint/lib/formatters/visualstudio.js

@ -35,7 +35,7 @@ module.exports = function(results) {
results.forEach(function(result) {
let messages = result.messages;
const messages = result.messages;
total += messages.length;

25
tools/eslint/lib/ignored-paths.js

@ -9,26 +9,25 @@
// Requirements
//------------------------------------------------------------------------------
let lodash = require("lodash"),
fs = require("fs"),
const fs = require("fs"),
path = require("path"),
debug = require("debug"),
ignore = require("ignore"),
shell = require("shelljs"),
pathUtil = require("./util/path-util");
debug = debug("eslint:ignored-paths");
const debug = require("debug")("eslint:ignored-paths");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
let ESLINT_IGNORE_FILENAME = ".eslintignore";
let DEFAULT_IGNORE_DIRS = [
const ESLINT_IGNORE_FILENAME = ".eslintignore";
const DEFAULT_IGNORE_DIRS = [
"node_modules/",
"bower_components/"
];
let DEFAULT_OPTIONS = {
const DEFAULT_OPTIONS = {
dotfiles: false,
cwd: process.cwd()
};
@ -47,9 +46,9 @@ let DEFAULT_OPTIONS = {
function findIgnoreFile(cwd) {
cwd = cwd || DEFAULT_OPTIONS.cwd;
let ignoreFilePath = path.resolve(cwd, ESLINT_IGNORE_FILENAME);
const ignoreFilePath = path.resolve(cwd, ESLINT_IGNORE_FILENAME);
return fs.existsSync(ignoreFilePath) ? ignoreFilePath : "";
return shell.test("-f", ignoreFilePath) ? ignoreFilePath : "";
}
/**
@ -59,7 +58,7 @@ function findIgnoreFile(cwd) {
*/
function mergeDefaultOptions(options) {
options = (options || {});
return lodash.assign({}, DEFAULT_OPTIONS, options);
return Object.assign({}, DEFAULT_OPTIONS, options);
}
//------------------------------------------------------------------------------
@ -175,8 +174,8 @@ function IgnoredPaths(options) {
IgnoredPaths.prototype.contains = function(filepath, category) {
let result = false;
let absolutePath = path.resolve(this.options.cwd, filepath);
let relativePath = pathUtil.getRelativePath(absolutePath, this.options.cwd);
const absolutePath = path.resolve(this.options.cwd, filepath);
const relativePath = pathUtil.getRelativePath(absolutePath, this.options.cwd);
if ((typeof category === "undefined") || (category === "default")) {
result = result || (this.ig.default.filter([relativePath]).length === 0);
@ -201,7 +200,7 @@ IgnoredPaths.prototype.getIgnoredFoldersGlobPatterns = function() {
/* eslint-disable no-underscore-dangle */
let patterns = this.ig.custom._rules.filter(function(rule) {
const patterns = this.ig.custom._rules.filter(function(rule) {
return rule.negative;
}).map(function(rule) {
return rule.origin;

31
tools/eslint/lib/internal-rules/internal-no-invalid-meta.js

@ -17,7 +17,7 @@
* @returns {ASTNode} The Property node or null if not found.
*/
function getPropertyFromObject(property, node) {
let properties = node.properties;
const properties = node.properties;
for (let i = 0; i < properties.length; i++) {
if (properties[i].key.name === property) {
@ -55,7 +55,7 @@ function hasMetaDocs(metaPropertyNode) {
* @returns {boolean} `true` if a `docs.description` property exists.
*/
function hasMetaDocsDescription(metaPropertyNode) {
let metaDocs = getPropertyFromObject("docs", metaPropertyNode.value);
const metaDocs = getPropertyFromObject("docs", metaPropertyNode.value);
return metaDocs && getPropertyFromObject("description", metaDocs.value);
}
@ -67,7 +67,7 @@ function hasMetaDocsDescription(metaPropertyNode) {
* @returns {boolean} `true` if a `docs.category` property exists.
*/
function hasMetaDocsCategory(metaPropertyNode) {
let metaDocs = getPropertyFromObject("docs", metaPropertyNode.value);
const metaDocs = getPropertyFromObject("docs", metaPropertyNode.value);
return metaDocs && getPropertyFromObject("category", metaDocs.value);
}
@ -79,7 +79,7 @@ function hasMetaDocsCategory(metaPropertyNode) {
* @returns {boolean} `true` if a `docs.recommended` property exists.
*/
function hasMetaDocsRecommended(metaPropertyNode) {
let metaDocs = getPropertyFromObject("docs", metaPropertyNode.value);
const metaDocs = getPropertyFromObject("docs", metaPropertyNode.value);
return metaDocs && getPropertyFromObject("recommended", metaDocs.value);
}
@ -113,7 +113,7 @@ function hasMetaFixable(metaPropertyNode) {
* @returns {void}
*/
function checkMetaValidity(context, exportsNode, ruleIsFixable) {
let metaProperty = getMetaPropertyFromExportsNode(exportsNode);
const metaProperty = getMetaPropertyFromExportsNode(exportsNode);
if (!metaProperty) {
context.report(exportsNode, "Rule is missing a meta property.");
@ -151,6 +151,16 @@ function checkMetaValidity(context, exportsNode, ruleIsFixable) {
}
}
/**
* Whether this node is the correct format for a rule definition or not.
*
* @param {ASTNode} node node that the rule exports.
* @returns {boolean} `true` if the exported node is the correct format for a rule definition
*/
function isCorrectExportsFormat(node) {
return node.type === "ObjectExpression";
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@ -167,7 +177,7 @@ module.exports = {
},
create: function(context) {
let metaExportsValue;
let exportsNode;
let ruleIsFixable = false;
return {
@ -178,7 +188,7 @@ module.exports = {
node.left.object.name === "module" &&
node.left.property.name === "exports") {
metaExportsValue = node.right;
exportsNode = node.right;
}
},
@ -205,7 +215,12 @@ module.exports = {
},
"Program:exit": function() {
checkMetaValidity(context, metaExportsValue, ruleIsFixable);
if (!isCorrectExportsFormat(exportsNode)) {
context.report(exportsNode, "Rule does not export an Object. Make sure the rule follows the new rule format.");
return;
}
checkMetaValidity(context, exportsNode, ruleIsFixable);
}
};
}

4
tools/eslint/lib/load-rules.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let fs = require("fs"),
const fs = require("fs"),
path = require("path");
//------------------------------------------------------------------------------
@ -29,7 +29,7 @@ module.exports = function(rulesDir, cwd) {
rulesDir = path.resolve(cwd, rulesDir);
}
let rules = Object.create(null);
const rules = Object.create(null);
fs.readdirSync(rulesDir).forEach(function(file) {
if (path.extname(file) !== ".js") {

2
tools/eslint/lib/options.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let optionator = require("optionator");
const optionator = require("optionator");
//------------------------------------------------------------------------------
// Initialization and Public Interface

9
tools/eslint/lib/rule-context.js

@ -8,13 +8,13 @@
// Requirements
//------------------------------------------------------------------------------
let RuleFixer = require("./util/rule-fixer");
const RuleFixer = require("./util/rule-fixer");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
let PASSTHROUGHS = [
const PASSTHROUGHS = [
"getAncestors",
"getDeclaredVariables",
"getFilename",
@ -111,12 +111,11 @@ RuleContext.prototype = {
* @returns {void}
*/
report: function(nodeOrDescriptor, location, message, opts) {
let descriptor,
fix = null;
// check to see if it's a new style call
if (arguments.length === 1) {
descriptor = nodeOrDescriptor;
const descriptor = nodeOrDescriptor;
let fix = null;
// if there's a fix specified, get it
if (typeof descriptor.fix === "function") {

6
tools/eslint/lib/rules.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let loadRules = require("./load-rules");
const loadRules = require("./load-rules");
//------------------------------------------------------------------------------
// Privates
@ -38,7 +38,7 @@ function define(ruleId, ruleModule) {
* @returns {void}
*/
function load(rulesDir, cwd) {
let newRules = loadRules(rulesDir, cwd);
const newRules = loadRules(rulesDir, cwd);
Object.keys(newRules).forEach(function(ruleId) {
define(ruleId, newRules[ruleId]);
@ -53,7 +53,7 @@ function load(rulesDir, cwd) {
*/
function importPlugin(pluginRules, pluginName) {
Object.keys(pluginRules).forEach(function(ruleId) {
let qualifiedRuleId = pluginName + "/" + ruleId,
const qualifiedRuleId = pluginName + "/" + ruleId,
rule = pluginRules[ruleId];
define(qualifiedRuleId, rule);

12
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) {
let parent = node.parent;
const parent = node.parent;
return (
parent.type === "CallExpression" &&
@ -91,9 +91,9 @@ module.exports = {
}]
},
create: function(context) {
let config = context.options[0] || {};
let checkGetWithoutSet = config.getWithoutSet === true;
let checkSetWithoutGet = config.setWithoutGet !== false;
const config = context.options[0] || {};
const checkGetWithoutSet = config.getWithoutSet === true;
const checkSetWithoutGet = config.setWithoutGet !== false;
/**
* Checks a object expression to see if it has setter and getter both present or none.
@ -104,10 +104,10 @@ module.exports = {
function checkLonelySetGet(node) {
let isSetPresent = false;
let isGetPresent = false;
let isDescriptor = isPropertyDescriptor(node);
const isDescriptor = isPropertyDescriptor(node);
for (let i = 0, end = node.properties.length; i < end; i++) {
let property = node.properties[i];
const property = node.properties[i];
let propToCheck = "";

16
tools/eslint/lib/rules/array-bracket-spacing.js

@ -4,7 +4,7 @@
*/
"use strict";
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -40,7 +40,7 @@ module.exports = {
]
},
create: function(context) {
let spaced = context.options[0] === "always",
const spaced = context.options[0] === "always",
sourceCode = context.getSourceCode();
/**
@ -54,7 +54,7 @@ module.exports = {
return context.options[1] ? context.options[1][option] === !spaced : false;
}
let options = {
const options = {
spaced: spaced,
singleElementException: isOptionSet("singleValue"),
objectsInArraysException: isOptionSet("objectsInArrays"),
@ -77,7 +77,7 @@ module.exports = {
loc: token.loc.start,
message: "There should be no space after '" + token.value + "'.",
fix: function(fixer) {
let nextToken = sourceCode.getTokenAfter(token);
const nextToken = sourceCode.getTokenAfter(token);
return fixer.removeRange([token.range[1], nextToken.range[0]]);
}
@ -96,7 +96,7 @@ module.exports = {
loc: token.loc.start,
message: "There should be no space before '" + token.value + "'.",
fix: function(fixer) {
let previousToken = sourceCode.getTokenBefore(token);
const previousToken = sourceCode.getTokenBefore(token);
return fixer.removeRange([previousToken.range[1], token.range[0]]);
}
@ -165,20 +165,20 @@ module.exports = {
return;
}
let first = sourceCode.getFirstToken(node),
const 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];
let openingBracketMustBeSpaced =
const openingBracketMustBeSpaced =
options.objectsInArraysException && isObjectType(firstElement) ||
options.arraysInArraysException && isArrayType(firstElement) ||
options.singleElementException && node.elements.length === 1
? !options.spaced : options.spaced;
let closingBracketMustBeSpaced =
const closingBracketMustBeSpaced =
options.objectsInArraysException && isObjectType(lastElement) ||
options.arraysInArraysException && isArrayType(lastElement) ||
options.singleElementException && node.elements.length === 1

44
tools/eslint/lib/rules/array-callback-return.js

@ -9,14 +9,14 @@
// Requirements
//------------------------------------------------------------------------------
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
let TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/;
let TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/;
const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/;
const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/;
/**
* Checks a given code path segment is reachable.
@ -45,38 +45,6 @@ function getLocation(node, sourceCode) {
return node.id || node;
}
/**
* Gets the name of a given node if the node is a Identifier node.
*
* @param {ASTNode} node - A node to get.
* @returns {string} The name of the node, or an empty string.
*/
function getIdentifierName(node) {
return node.type === "Identifier" ? node.name : "";
}
/**
* Gets the value of a given node if the node is a Literal node or a
* TemplateLiteral node.
*
* @param {ASTNode} node - A node to get.
* @returns {string} The value of the node, or an empty string.
*/
function getConstantStringValue(node) {
switch (node.type) {
case "Literal":
return String(node.value);
case "TemplateLiteral":
return node.expressions.length === 0
? node.quasis[0].value.cooked
: "";
default:
return "";
}
}
/**
* Checks a given node is a MemberExpression node which has the specified name's
* property.
@ -88,9 +56,7 @@ function getConstantStringValue(node) {
function isTargetMethod(node) {
return (
node.type === "MemberExpression" &&
TARGET_METHODS.test(
(node.computed ? getConstantStringValue : getIdentifierName)(node.property)
)
TARGET_METHODS.test(astUtils.getStaticPropertyName(node) || "")
);
}
@ -104,7 +70,7 @@ function isTargetMethod(node) {
*/
function isCallbackOfArrayMethod(node) {
while (node) {
let parent = node.parent;
const parent = node.parent;
switch (parent.type) {

14
tools/eslint/lib/rules/arrow-body-style.js

@ -50,11 +50,11 @@ module.exports = {
},
create: function(context) {
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;
const options = context.options;
const always = options[0] === "always";
const asNeeded = !options[0] || options[0] === "as-needed";
const never = options[0] === "never";
const 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) {
let arrowBody = node.body;
const arrowBody = node.body;
if (arrowBody.type === "BlockStatement") {
if (never) {
@ -72,7 +72,7 @@ module.exports = {
message: "Unexpected block statement surrounding arrow body."
});
} else {
let blockBody = arrowBody.body;
const blockBody = arrowBody.body;
if (blockBody.length !== 1) {
return;

72
tools/eslint/lib/rules/arrow-parens.js

@ -21,16 +21,29 @@ module.exports = {
schema: [
{
enum: ["always", "as-needed"]
},
{
type: "object",
properties: {
requireForBlockBody: {
type: "boolean"
}
},
additionalProperties: false
}
]
},
create: function(context) {
let message = "Expected parentheses around arrow function argument.";
let asNeededMessage = "Unexpected parentheses around single function argument.";
let asNeeded = context.options[0] === "as-needed";
const message = "Expected parentheses around arrow function argument.";
const asNeededMessage = "Unexpected parentheses around single function argument.";
const asNeeded = context.options[0] === "as-needed";
const requireForBlockBodyMessage = "Unexpected parentheses around single function argument having a body with no curly braces";
const requireForBlockBodyNoParensMessage = "Expected parentheses around arrow function argument having a body with curly braces.";
const requireForBlockBody = asNeeded && context.options[1] && context.options[1].requireForBlockBody === true;
const sourceCode = context.getSourceCode();
let sourceCode = context.getSourceCode();
/**
* Determines whether a arrow function argument end with `)`
@ -38,17 +51,58 @@ module.exports = {
* @returns {void}
*/
function parens(node) {
let token = sourceCode.getFirstToken(node);
const token = sourceCode.getFirstToken(node);
// "as-needed", { "requireForBlockBody": true }: x => x
if (
requireForBlockBody &&
node.params.length === 1 &&
node.params[0].type === "Identifier" &&
node.body.type !== "BlockStatement"
) {
if (token.type === "Punctuator" && token.value === "(") {
context.report({
node: node,
message: requireForBlockBodyMessage,
fix: function(fixer) {
const paramToken = context.getTokenAfter(token);
const closingParenToken = context.getTokenAfter(paramToken);
return fixer.replaceTextRange([
token.range[0],
closingParenToken.range[1]
], paramToken.value);
}
});
}
return;
}
if (
requireForBlockBody &&
node.body.type === "BlockStatement"
) {
if (token.type !== "Punctuator" || token.value !== "(") {
context.report({
node: node,
message: requireForBlockBodyNoParensMessage,
fix: function(fixer) {
return fixer.replaceText(token, "(" + token.value + ")");
}
});
}
return;
}
// as-needed: x => x
// "as-needed": x => x
if (asNeeded && node.params.length === 1 && node.params[0].type === "Identifier") {
if (token.type === "Punctuator" && token.value === "(") {
context.report({
node: node,
message: asNeededMessage,
fix: function(fixer) {
let paramToken = context.getTokenAfter(token);
let closingParenToken = context.getTokenAfter(paramToken);
const paramToken = context.getTokenAfter(token);
const closingParenToken = context.getTokenAfter(paramToken);
return fixer.replaceTextRange([
token.range[0],
@ -61,7 +115,7 @@ module.exports = {
}
if (token.type === "Identifier") {
let after = sourceCode.getTokenAfter(token);
const after = sourceCode.getTokenAfter(token);
// (x) => x
if (after.value !== ")") {

14
tools/eslint/lib/rules/arrow-spacing.js

@ -37,13 +37,13 @@ module.exports = {
create: function(context) {
// merge rules with default
let rule = { before: true, after: true },
const rule = { before: true, after: true },
option = context.options[0] || {};
rule.before = option.before !== false;
rule.after = option.after !== false;
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
/**
* Get tokens of arrow(`=>`) and before/after arrow.
@ -58,7 +58,7 @@ module.exports = {
before = t;
t = sourceCode.getTokenAfter(t);
}
let after = sourceCode.getTokenAfter(t);
const 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) {
let before = tokens.arrow.range[0] - tokens.before.range[1];
let after = tokens.after.range[0] - tokens.arrow.range[1];
const before = tokens.arrow.range[0] - tokens.before.range[1];
const 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) {
let tokens = getTokens(node);
let countSpace = countSpaces(tokens);
const tokens = getTokens(node);
const countSpace = countSpaces(tokens);
if (rule.before) {

8
tools/eslint/lib/rules/block-scoped-var.js

@ -45,7 +45,7 @@ module.exports = {
* @returns {void}
*/
function report(reference) {
let identifier = reference.identifier;
const 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.
let scopeRange = stack[stack.length - 1];
const scopeRange = stack[stack.length - 1];
/**
* Check if a reference is out of scope
@ -73,13 +73,13 @@ module.exports = {
* @private
*/
function isOutsideOfScope(reference) {
let idRange = reference.identifier.range;
const idRange = reference.identifier.range;
return idRange[0] < scopeRange[0] || idRange[1] > scopeRange[1];
}
// Gets declared variables, and checks its references.
let variables = context.getDeclaredVariables(node);
const variables = context.getDeclaredVariables(node);
for (let i = 0; i < variables.length; ++i) {

12
tools/eslint/lib/rules/block-spacing.js

@ -5,7 +5,7 @@
"use strict";
let util = require("../ast-utils");
const util = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -27,7 +27,7 @@ module.exports = {
},
create: function(context) {
let always = (context.options[0] !== "never"),
const 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.
let openBrace = getOpenBrace(node);
let closeBrace = sourceCode.getLastToken(node);
let firstToken = sourceCode.getTokenOrCommentAfter(openBrace);
let lastToken = sourceCode.getTokenOrCommentBefore(closeBrace);
const openBrace = getOpenBrace(node);
const closeBrace = sourceCode.getLastToken(node);
const firstToken = sourceCode.getTokenOrCommentAfter(openBrace);
const lastToken = sourceCode.getTokenOrCommentBefore(closeBrace);
// Skip if the node is invalid or empty.
if (openBrace.type !== "Punctuator" ||

31
tools/eslint/lib/rules/brace-style.js

@ -34,11 +34,11 @@ module.exports = {
},
create: function(context) {
let style = context.options[0] || "1tbs",
const style = context.options[0] || "1tbs",
params = context.options[1] || {},
sourceCode = context.getSourceCode();
let OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.",
const 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.",
@ -78,24 +78,20 @@ module.exports = {
* @private
*/
function checkBlock() {
let blockProperties = arguments;
const blockProperties = arguments;
return function(node) {
Array.prototype.forEach.call(blockProperties, function(blockProp) {
let block = node[blockProp],
previousToken,
curlyToken,
curlyTokenEnd,
allOnSameLine;
const block = node[blockProp];
if (!isBlock(block)) {
return;
}
previousToken = sourceCode.getTokenBefore(block);
curlyToken = sourceCode.getFirstToken(block);
curlyTokenEnd = sourceCode.getLastToken(block);
allOnSameLine = previousToken.loc.start.line === curlyTokenEnd.loc.start.line;
const previousToken = sourceCode.getTokenBefore(block);
const curlyToken = sourceCode.getFirstToken(block);
const curlyTokenEnd = sourceCode.getLastToken(block);
const allOnSameLine = previousToken.loc.start.line === curlyTokenEnd.loc.start.line;
if (allOnSameLine && params.allowSingleLine) {
return;
@ -129,13 +125,11 @@ module.exports = {
* @private
*/
function checkIfStatement(node) {
let tokens;
checkBlock("consequent", "alternate")(node);
if (node.alternate) {
tokens = sourceCode.getTokensBefore(node.alternate, 2);
const tokens = sourceCode.getTokensBefore(node.alternate, 2);
if (style === "1tbs") {
if (tokens[0].loc.start.line !== tokens[1].loc.start.line &&
@ -157,12 +151,11 @@ module.exports = {
* @private
*/
function checkTryStatement(node) {
let tokens;
checkBlock("block", "finalizer")(node);
if (isBlock(node.finalizer)) {
tokens = sourceCode.getTokensBefore(node.finalizer, 2);
const tokens = sourceCode.getTokensBefore(node.finalizer, 2);
if (style === "1tbs") {
if (tokens[0].loc.start.line !== tokens[1].loc.start.line) {
context.report(node.finalizer, CLOSE_MESSAGE);
@ -180,7 +173,7 @@ module.exports = {
* @private
*/
function checkCatchClause(node) {
let previousToken = sourceCode.getTokenBefore(node),
const previousToken = sourceCode.getTokenBefore(node),
firstToken = sourceCode.getFirstToken(node);
checkBlock("body")(node);

9
tools/eslint/lib/rules/callback-return.js

@ -24,7 +24,7 @@ module.exports = {
create: function(context) {
let callbacks = context.options[0] || ["callback", "cb", "next"],
const callbacks = context.options[0] || ["callback", "cb", "next"],
sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
@ -118,8 +118,7 @@ module.exports = {
}
// find the closest block, return or loop
let closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {},
lastItem, parentType;
const closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {};
// if our parent is a return we know we're ok
if (closestBlock.type === "ReturnStatement") {
@ -135,12 +134,12 @@ module.exports = {
if (closestBlock.type === "BlockStatement") {
// find the last item in the block
lastItem = closestBlock.body[closestBlock.body.length - 1];
const lastItem = closestBlock.body[closestBlock.body.length - 1];
// if the callback is the last thing in a block that might be ok
if (isCallbackExpression(node, lastItem)) {
parentType = closestBlock.parent.type;
const parentType = closestBlock.parent.type;
// but only if the block is part of a function
if (parentType === "FunctionExpression" ||

16
tools/eslint/lib/rules/camelcase.js

@ -37,7 +37,7 @@ module.exports = {
//--------------------------------------------------------------------------
// contains reported nodes to avoid reporting twice on destructuring with shorthand notation
let reported = [];
const reported = [];
/**
* Checks if a string contains an underscore and isn't all upper-case
@ -64,8 +64,8 @@ module.exports = {
}
}
let options = context.options[0] || {},
properties = options.properties || "";
const options = context.options[0] || {};
let properties = options.properties || "";
if (properties !== "always" && properties !== "never") {
properties = "always";
@ -79,7 +79,7 @@ module.exports = {
* Leading and trailing underscores are commonly used to flag
* private/protected identifiers, strip them
*/
let name = node.name.replace(/^_+|_+$/g, ""),
const name = node.name.replace(/^_+|_+$/g, ""),
effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
// MemberExpressions get special rules
@ -122,6 +122,14 @@ module.exports = {
report(node);
}
// Check if it's an import specifier
} else if (["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"].indexOf(node.parent.type) >= 0) {
// Report only if the local imported identifier is underscored
if (node.parent.local && node.parent.local.name === node.name && isUnderscored(name)) {
report(node);
}
// Report anything that is underscored that isn't a CallExpression
} else if (isUnderscored(name) && effectiveParent.type !== "CallExpression") {
report(node);

26
tools/eslint/lib/rules/comma-dangle.js

@ -9,7 +9,7 @@
// Requirements
//------------------------------------------------------------------------------
let lodash = require("lodash");
const 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) {
let mode = context.options[0];
let UNEXPECTED_MESSAGE = "Unexpected trailing comma.";
let MISSING_MESSAGE = "Missing trailing comma.";
const mode = context.options[0];
const UNEXPECTED_MESSAGE = "Unexpected trailing comma.";
const MISSING_MESSAGE = "Missing trailing comma.";
/**
* Checks whether or not a given node is multiline.
@ -58,14 +58,14 @@ module.exports = {
* @returns {boolean} `true` if the node is multiline.
*/
function isMultiline(node) {
let lastItem = lodash.last(node.properties || node.elements || node.specifiers);
const lastItem = lodash.last(node.properties || node.elements || node.specifiers);
if (!lastItem) {
return false;
}
let sourceCode = context.getSourceCode(),
penultimateToken = sourceCode.getLastToken(lastItem),
const sourceCode = context.getSourceCode();
let penultimateToken = sourceCode.getLastToken(lastItem),
lastToken = sourceCode.getTokenAfter(penultimateToken);
// parentheses are a pain
@ -91,14 +91,14 @@ module.exports = {
* @returns {void}
*/
function forbidTrailingComma(node) {
let lastItem = lodash.last(node.properties || node.elements || node.specifiers);
const lastItem = lodash.last(node.properties || node.elements || node.specifiers);
if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) {
return;
}
let sourceCode = context.getSourceCode(),
trailingToken;
const sourceCode = context.getSourceCode();
let trailingToken;
// last item can be surrounded by parentheses for object and array literals
if (node.type === "ObjectExpression" || node.type === "ArrayExpression") {
@ -132,7 +132,7 @@ module.exports = {
* @returns {void}
*/
function forceTrailingComma(node) {
let lastItem = lodash.last(node.properties || node.elements || node.specifiers);
const lastItem = lodash.last(node.properties || node.elements || node.specifiers);
if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) {
return;
@ -142,8 +142,8 @@ module.exports = {
return;
}
let sourceCode = context.getSourceCode(),
penultimateToken = lastItem,
const sourceCode = context.getSourceCode();
let penultimateToken = lastItem,
trailingToken = sourceCode.getTokenAfter(lastItem);
// Skip close parentheses.

20
tools/eslint/lib/rules/comma-spacing.js

@ -4,7 +4,7 @@
*/
"use strict";
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -38,10 +38,10 @@ module.exports = {
create: function(context) {
let sourceCode = context.getSourceCode();
let tokensAndComments = sourceCode.tokensAndComments;
const sourceCode = context.getSourceCode();
const tokensAndComments = sourceCode.tokensAndComments;
let options = {
const 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
let commaTokensToIgnore = [];
const commaTokensToIgnore = [];
/**
* Determines if a given token is a comma operator.
@ -83,7 +83,7 @@ module.exports = {
}
} else {
let start, end;
let newText = "";
const newText = "";
if (dir === "before") {
start = otherNode.range[1];
@ -161,10 +161,6 @@ module.exports = {
return {
"Program:exit": function() {
let previousToken,
nextToken;
tokensAndComments.forEach(function(token, i) {
if (!isComma(token)) {
@ -175,8 +171,8 @@ module.exports = {
return;
}
previousToken = tokensAndComments[i - 1];
nextToken = tokensAndComments[i + 1];
const previousToken = tokensAndComments[i - 1];
const nextToken = tokensAndComments[i + 1];
validateCommaItemSpacing({
comma: token,

19
tools/eslint/lib/rules/comma-style.js

@ -5,7 +5,7 @@
"use strict";
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -39,9 +39,9 @@ module.exports = {
},
create: function(context) {
let style = context.options[0] || "last",
exceptions = {},
const style = context.options[0] || "last",
sourceCode = context.getSourceCode();
let exceptions = {};
if (context.options.length === 2 && context.options[1].hasOwnProperty("exceptions")) {
exceptions = context.options[1].exceptions;
@ -108,17 +108,16 @@ module.exports = {
* @returns {void}
*/
function validateComma(node, property) {
let items = node[property],
arrayLiteral = (node.type === "ArrayExpression"),
previousItemToken;
const items = node[property],
arrayLiteral = (node.type === "ArrayExpression");
if (items.length > 1 || arrayLiteral) {
// seed as opening [
previousItemToken = sourceCode.getFirstToken(node);
let previousItemToken = sourceCode.getFirstToken(node);
items.forEach(function(item) {
let commaToken = item ? sourceCode.getTokenBefore(item) : previousItemToken,
const commaToken = item ? sourceCode.getTokenBefore(item) : previousItemToken,
currentItemToken = item ? sourceCode.getFirstToken(item) : sourceCode.getTokenAfter(commaToken),
reportItem = item || currentItemToken,
tokenBeforeComma = sourceCode.getTokenBefore(commaToken);
@ -158,7 +157,7 @@ module.exports = {
*/
if (arrayLiteral) {
let lastToken = sourceCode.getLastToken(node),
const lastToken = sourceCode.getLastToken(node),
nextToLastToken = sourceCode.getTokenBefore(lastToken);
if (isComma(nextToLastToken)) {
@ -177,7 +176,7 @@ module.exports = {
// Public
//--------------------------------------------------------------------------
let nodes = {};
const nodes = {};
if (!exceptions.VariableDeclaration) {
nodes.VariableDeclaration = function(node) {

10
tools/eslint/lib/rules/complexity.js

@ -45,8 +45,8 @@ module.exports = {
},
create: function(context) {
let option = context.options[0],
THRESHOLD = 20;
const option = context.options[0];
let THRESHOLD = 20;
if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") {
THRESHOLD = option.maximum;
@ -63,7 +63,7 @@ module.exports = {
//--------------------------------------------------------------------------
// Using a stack to store complexity (handling nested functions)
let fns = [];
const fns = [];
/**
* When parsing a new function, store it in our function stack
@ -81,8 +81,8 @@ module.exports = {
* @private
*/
function endFunction(node) {
let complexity = fns.pop(),
name = "anonymous";
const complexity = fns.pop();
let name = "anonymous";
if (node.id) {
name = node.id.name;

10
tools/eslint/lib/rules/computed-property-spacing.js

@ -4,7 +4,7 @@
*/
"use strict";
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -28,8 +28,8 @@ module.exports = {
},
create: function(context) {
let sourceCode = context.getSourceCode();
let propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never"
const sourceCode = context.getSourceCode();
const propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never"
//--------------------------------------------------------------------------
// Helpers
@ -117,9 +117,9 @@ module.exports = {
return;
}
let property = node[propertyName];
const property = node[propertyName];
let before = sourceCode.getTokenBefore(property),
const before = sourceCode.getTokenBefore(property),
first = sourceCode.getFirstToken(property),
last = sourceCode.getLastToken(property),
after = sourceCode.getTokenAfter(property);

8
tools/eslint/lib/rules/consistent-return.js

@ -8,7 +8,7 @@
// Requirements
//------------------------------------------------------------------------------
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Helpers
@ -57,8 +57,8 @@ module.exports = {
},
create: function(context) {
let options = context.options[0] || {};
let treatUndefinedAsUnspecified = options.treatUndefinedAsUnspecified === true;
const options = context.options[0] || {};
const treatUndefinedAsUnspecified = options.treatUndefinedAsUnspecified === true;
let funcInfo = null;
/**
@ -135,7 +135,7 @@ module.exports = {
// Reports a given return statement if it's inconsistent.
ReturnStatement: function(node) {
let argument = node.argument;
const argument = node.argument;
let hasReturnValue = Boolean(argument);
if (treatUndefinedAsUnspecified && hasReturnValue) {

12
tools/eslint/lib/rules/consistent-this.js

@ -57,7 +57,7 @@ module.exports = {
* @returns {void}
*/
function checkAssignment(node, name, value) {
let isThis = value.type === "ThisExpression";
const isThis = value.type === "ThisExpression";
if (aliases.indexOf(name) !== -1) {
if (!isThis || node.operator && node.operator !== "=") {
@ -78,7 +78,7 @@ module.exports = {
* @returns {void}
*/
function checkWasAssigned(alias, scope) {
let variable = scope.set.get(alias);
const 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) {
let write = reference.writeExpr;
const write = reference.writeExpr;
return (
reference.from === scope &&
@ -115,7 +115,7 @@ module.exports = {
* @returns {void}
*/
function ensureWasAssigned() {
let scope = context.getScope();
const scope = context.getScope();
aliases.forEach(function(alias) {
checkWasAssigned(alias, scope);
@ -128,8 +128,8 @@ module.exports = {
"FunctionDeclaration:exit": ensureWasAssigned,
VariableDeclarator: function(node) {
let id = node.id;
let isDestructuring =
const id = node.id;
const isDestructuring =
id.type === "ArrayPattern" || id.type === "ObjectPattern";
if (node.init !== null && !isDestructuring) {

36
tools/eslint/lib/rules/constructor-super.js

@ -164,8 +164,8 @@ module.exports = {
if (isConstructorFunction(node)) {
// Class > ClassBody > MethodDefinition > FunctionExpression
let classNode = node.parent.parent.parent;
let superClass = classNode.superClass;
const classNode = node.parent.parent.parent;
const superClass = classNode.superClass;
funcInfo = {
upper: funcInfo,
@ -193,7 +193,7 @@ module.exports = {
* @returns {void}
*/
onCodePathEnd: function(codePath, node) {
let hasExtends = funcInfo.hasExtends;
const hasExtends = funcInfo.hasExtends;
// Pop.
funcInfo = funcInfo.upper;
@ -203,9 +203,9 @@ module.exports = {
}
// Reports if `super()` lacked.
let segments = codePath.returnedSegments;
let calledInEveryPaths = segments.every(isCalledInEveryPath);
let calledInSomePaths = segments.some(isCalledInSomePath);
const segments = codePath.returnedSegments;
const calledInEveryPaths = segments.every(isCalledInEveryPath);
const calledInSomePaths = segments.some(isCalledInSomePath);
if (!calledInEveryPaths) {
context.report({
@ -228,14 +228,14 @@ module.exports = {
}
// Initialize info.
let info = segInfoMap[segment.id] = {
const info = segInfoMap[segment.id] = {
calledInSomePaths: false,
calledInEveryPaths: false,
validNodes: []
};
// When there are previous segments, aggregates these.
let prevSegments = segment.prevSegments;
const prevSegments = segment.prevSegments;
if (prevSegments.length > 0) {
info.calledInSomePaths = prevSegments.some(isCalledInSomePath);
@ -258,13 +258,13 @@ module.exports = {
}
// Update information inside of the loop.
let isRealLoop = toSegment.prevSegments.length >= 2;
const isRealLoop = toSegment.prevSegments.length >= 2;
funcInfo.codePath.traverseSegments(
{first: toSegment, last: fromSegment},
function(segment) {
let info = segInfoMap[segment.id];
let prevSegments = segment.prevSegments;
const info = segInfoMap[segment.id];
const prevSegments = segment.prevSegments;
// Updates flags.
info.calledInSomePaths = prevSegments.some(isCalledInSomePath);
@ -272,12 +272,12 @@ module.exports = {
// If flags become true anew, reports the valid nodes.
if (info.calledInSomePaths || isRealLoop) {
let nodes = info.validNodes;
const nodes = info.validNodes;
info.validNodes = [];
for (let i = 0; i < nodes.length; ++i) {
let node = nodes[i];
const node = nodes[i];
context.report({
message: "Unexpected duplicate 'super()'.",
@ -306,12 +306,12 @@ module.exports = {
// Reports if needed.
if (funcInfo.hasExtends) {
let segments = funcInfo.codePath.currentSegments;
const segments = funcInfo.codePath.currentSegments;
let duplicate = false;
let info = null;
for (let i = 0; i < segments.length; ++i) {
let segment = segments[i];
const segment = segments[i];
if (segment.reachable) {
info = segInfoMap[segment.id];
@ -360,13 +360,13 @@ module.exports = {
}
// Returning argument is a substitute of 'super()'.
let segments = funcInfo.codePath.currentSegments;
const segments = funcInfo.codePath.currentSegments;
for (let i = 0; i < segments.length; ++i) {
let segment = segments[i];
const segment = segments[i];
if (segment.reachable) {
let info = segInfoMap[segment.id];
const info = segInfoMap[segment.id];
info.calledInSomePaths = info.calledInEveryPaths = true;
}

22
tools/eslint/lib/rules/curly.js

@ -8,7 +8,7 @@
// Requirements
//------------------------------------------------------------------------------
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -53,12 +53,12 @@ module.exports = {
create: function(context) {
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");
const multiOnly = (context.options[0] === "multi");
const multiLine = (context.options[0] === "multi-line");
const multiOrNest = (context.options[0] === "multi-or-nest");
const consistent = (context.options[1] === "consistent");
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
// Helpers
@ -71,7 +71,7 @@ module.exports = {
* @private
*/
function isCollapsedOneLiner(node) {
let before = sourceCode.getTokenBefore(node),
const 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) {
let first = sourceCode.getFirstToken(node),
const first = sourceCode.getFirstToken(node),
last = sourceCode.getLastToken(node);
return first.loc.start.line === last.loc.end.line;
@ -189,7 +189,7 @@ module.exports = {
* properties.
*/
function prepareCheck(node, body, name, suffix) {
let hasBlock = (body.type === "BlockStatement");
const hasBlock = (body.type === "BlockStatement");
let expected = null;
if (node.type === "IfStatement" && node.consequent === body && requiresBraceOfConsequent(node)) {
@ -234,7 +234,7 @@ module.exports = {
* information.
*/
function prepareIfChecks(node) {
let preparedChecks = [];
const 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.
*/
let expected = preparedChecks.some(function(preparedCheck) {
const expected = preparedChecks.some(function(preparedCheck) {
if (preparedCheck.expected !== null) {
return preparedCheck.expected;
}

16
tools/eslint/lib/rules/default-case.js

@ -4,7 +4,7 @@
*/
"use strict";
let DEFAULT_COMMENT_PATTERN = /^no default$/;
const DEFAULT_COMMENT_PATTERN = /^no default$/;
//------------------------------------------------------------------------------
// Rule Definition
@ -30,12 +30,12 @@ module.exports = {
},
create: function(context) {
let options = context.options[0] || {};
let commentPattern = options.commentPattern ?
const options = context.options[0] || {};
const commentPattern = options.commentPattern ?
new RegExp(options.commentPattern) :
DEFAULT_COMMENT_PATTERN;
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
// Helpers
@ -67,18 +67,16 @@ module.exports = {
return;
}
let hasDefault = node.cases.some(function(v) {
const hasDefault = node.cases.some(function(v) {
return v.test === null;
});
if (!hasDefault) {
let comment;
let comments;
let lastCase = last(node.cases);
comments = sourceCode.getComments(lastCase).trailing;
const lastCase = last(node.cases);
const comments = sourceCode.getComments(lastCase).trailing;
if (comments.length) {
comment = last(comments);

10
tools/eslint/lib/rules/dot-location.js

@ -5,7 +5,7 @@
"use strict";
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -28,12 +28,12 @@ module.exports = {
create: function(context) {
let config = context.options[0];
const config = context.options[0];
// default to onObject if no preference is passed
let onObject = config === "object" || !config;
const onObject = config === "object" || !config;
let sourceCode = context.getSourceCode();
const 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) {
let dot = sourceCode.getTokenBefore(prop);
const dot = sourceCode.getTokenBefore(prop);
if (dot.type === "Punctuator" && dot.value === ".") {
if (onObject) {

8
tools/eslint/lib/rules/dot-notation.js

@ -8,8 +8,8 @@
// Rule Definition
//------------------------------------------------------------------------------
let validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
let keywords = require("../util/keywords");
const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
const keywords = require("../util/keywords");
module.exports = {
meta: {
@ -36,8 +36,8 @@ module.exports = {
},
create: function(context) {
let options = context.options[0] || {};
let allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords;
const options = context.options[0] || {};
const allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords;
let allowPattern;

2
tools/eslint/lib/rules/eol-last.js

@ -35,7 +35,7 @@ module.exports = {
Program: function checkBadEOF(node) {
let sourceCode = context.getSourceCode(),
const sourceCode = context.getSourceCode(),
src = sourceCode.getText(),
location = {column: 1},
linebreakStyle = context.options[0] || "unix",

77
tools/eslint/lib/rules/eqeqeq.js

@ -17,15 +17,49 @@ module.exports = {
recommended: false
},
schema: [
schema: {
anyOf: [
{
enum: ["always", "smart", "allow-null"]
type: "array",
items: [
{
enum: ["always"]
},
{
type: "object",
properties: {
null: {
enum: ["always", "never", "ignore"]
}
},
additionalProperties: false
}
],
additionalItems: false
},
{
type: "array",
items: [
{
enum: ["smart", "allow-null"]
}
],
additionalItems: false
}
]
}
},
create: function(context) {
let sourceCode = context.getSourceCode();
const config = context.options[0] || "always";
const options = context.options[1] || {};
const sourceCode = context.getSourceCode();
const nullOption = (config === "always") ?
options.null || "always" :
"ignore";
const enforceRuleForNull = (nullOption === "always");
const enforceInverseRuleForNull = (nullOption === "never");
/**
* Checks if an expression is a typeof expression
@ -76,33 +110,48 @@ module.exports = {
* @private
*/
function getOperatorLocation(node) {
let opToken = sourceCode.getTokenAfter(node.left);
const opToken = sourceCode.getTokenAfter(node.left);
return {line: opToken.loc.start.line, column: opToken.loc.start.column};
}
/**
* Reports a message for this rule.
* @param {ASTNode} node The binary expression node that was checked
* @param {string} message The message to report
* @returns {void}
* @private
*/
function report(node, message) {
context.report({
node: node,
loc: getOperatorLocation(node),
message: message,
data: { op: node.operator.charAt(0) }
});
}
return {
BinaryExpression: function(node) {
const isNull = isNullCheck(node);
if (node.operator !== "==" && node.operator !== "!=") {
if (enforceInverseRuleForNull && isNull) {
report(node, "Expected '{{op}}=' and instead saw '{{op}}=='.");
}
return;
}
if (context.options[0] === "smart" && (isTypeOfBinary(node) ||
areLiteralsAndSameType(node) || isNullCheck(node))) {
if (config === "smart" && (isTypeOfBinary(node) ||
areLiteralsAndSameType(node) || isNull)) {
return;
}
if (context.options[0] === "allow-null" && isNullCheck(node)) {
if (!enforceRuleForNull && isNull) {
return;
}
context.report({
node: node,
loc: getOperatorLocation(node),
message: "Expected '{{op}}=' and instead saw '{{op}}'.",
data: { op: node.operator }
});
report(node, "Expected '{{op}}==' and instead saw '{{op}}='.");
}
};

153
tools/eslint/lib/rules/func-call-spacing.js

@ -0,0 +1,153 @@
/**
* @fileoverview Rule to control spacing within function calls
* @author Matt DuVall <http://www.mattduvall.com>
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
docs: {
description: "require or disallow spacing between `function` identifiers and their invocations",
category: "Stylistic Issues",
recommended: false
},
fixable: "whitespace",
schema: {
anyOf: [
{
type: "array",
items: [
{
enum: ["never"]
}
],
minItems: 0,
maxItems: 1
},
{
type: "array",
items: [
{
enum: ["always"]
},
{
type: "object",
properties: {
allowNewlines: {
type: "boolean"
}
},
additionalProperties: false
}
],
minItems: 0,
maxItems: 2
}
]
}
},
create: function(context) {
const never = context.options[0] !== "always";
const allowNewlines = !never && context.options[1] && context.options[1].allowNewlines;
const sourceCode = context.getSourceCode();
const text = sourceCode.getText();
/**
* Check if open space is present in a function name
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkSpacing(node) {
const lastCalleeToken = sourceCode.getLastToken(node.callee);
let prevToken = lastCalleeToken;
let parenToken = sourceCode.getTokenAfter(lastCalleeToken);
// advances to an open parenthesis.
while (
parenToken &&
parenToken.range[1] < node.range[1] &&
parenToken.value !== "("
) {
prevToken = parenToken;
parenToken = sourceCode.getTokenAfter(parenToken);
}
// Parens in NewExpression are optional
if (!(parenToken && parenToken.range[1] < node.range[1])) {
return;
}
const hasWhitespace = sourceCode.isSpaceBetweenTokens(prevToken, parenToken);
const hasNewline = hasWhitespace &&
/\n/.test(text.slice(prevToken.range[1], parenToken.range[0]).replace(/\/\*.*?\*\//g, ""));
/*
* never allowNewlines hasWhitespace hasNewline message
* F F F F Missing space between function name and paren.
* F F F T (Invalid `!hasWhitespace && hasNewline`)
* F F T T Unexpected newline between function name and paren.
* F F T F (OK)
* F T T F (OK)
* F T T T (OK)
* F T F T (Invalid `!hasWhitespace && hasNewline`)
* F T F F Missing space between function name and paren.
* T T F F (Invalid `never && allowNewlines`)
* T T F T (Invalid `!hasWhitespace && hasNewline`)
* T T T T (Invalid `never && allowNewlines`)
* T T T F (Invalid `never && allowNewlines`)
* T F T F Unexpected space between function name and paren.
* T F T T Unexpected space between function name and paren.
* T F F T (Invalid `!hasWhitespace && hasNewline`)
* T F F F (OK)
*
* T T Unexpected space between function name and paren.
* F F Missing space between function name and paren.
* F F T Unexpected newline between function name and paren.
*/
if (never && hasWhitespace) {
context.report({
node: node,
loc: lastCalleeToken.loc.start,
message: "Unexpected space between function name and paren.",
fix: function(fixer) {
return fixer.removeRange([prevToken.range[1], parenToken.range[0]]);
}
});
} else if (!never && !hasWhitespace) {
context.report({
node: node,
loc: lastCalleeToken.loc.start,
message: "Missing space between function name and paren.",
fix: function(fixer) {
return fixer.insertTextBefore(parenToken, " ");
}
});
} else if (!never && !allowNewlines && hasNewline) {
context.report({
node: node,
loc: lastCalleeToken.loc.start,
message: "Unexpected newline between function name and paren.",
fix: function(fixer) {
return fixer.replaceTextRange([prevToken.range[1], parenToken.range[0]], " ");
}
});
}
}
return {
CallExpression: checkSpacing,
NewExpression: checkSpacing
};
}
};

8
tools/eslint/lib/rules/func-names.js

@ -34,7 +34,7 @@ module.exports = {
},
create: function(context) {
let never = context.options[0] === "never";
const never = context.options[0] === "never";
/**
* Determines whether the current FunctionExpression node is a get, set, or
@ -42,7 +42,7 @@ module.exports = {
* @returns {boolean} True if the node is a get, set, or shorthand method.
*/
function isObjectOrClassMethod() {
let parent = context.getAncestors().pop();
const parent = context.getAncestors().pop();
return (parent.type === "MethodDefinition" || (
parent.type === "Property" && (
@ -57,13 +57,13 @@ module.exports = {
"FunctionExpression:exit": function(node) {
// Skip recursive functions.
let nameVar = context.getDeclaredVariables(node)[0];
const nameVar = context.getDeclaredVariables(node)[0];
if (isFunctionName(nameVar) && nameVar.references.length > 0) {
return;
}
let name = node.id && node.id.name;
const name = node.id && node.id.name;
if (never) {
if (name) {

10
tools/eslint/lib/rules/func-style.js

@ -34,16 +34,12 @@ module.exports = {
create: function(context) {
let style = context.options[0],
const style = context.options[0],
allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions === true,
enforceDeclarations = (style === "declaration"),
stack = [];
let nodesToCheck = {
Program: function() {
stack = [];
},
const nodesToCheck = {
FunctionDeclaration: function(node) {
stack.push(false);
@ -79,7 +75,7 @@ module.exports = {
};
nodesToCheck["ArrowFunctionExpression:exit"] = function(node) {
let hasThisExpr = stack.pop();
const hasThisExpr = stack.pop();
if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") {
context.report(node.parent, "Expected a function declaration.");

22
tools/eslint/lib/rules/generator-star-spacing.js

@ -40,7 +40,7 @@ module.exports = {
create: function(context) {
let mode = (function(option) {
const 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]));
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
/**
* Gets `*` token from a given node.
@ -83,11 +83,11 @@ module.exports = {
*/
function checkSpacing(side, leftToken, rightToken) {
if (!!(rightToken.range[0] - leftToken.range[1]) !== mode[side]) {
let after = leftToken.value === "*";
let spaceRequired = mode[side];
let node = after ? leftToken : rightToken;
let type = spaceRequired ? "Missing" : "Unexpected";
let message = type + " space " + side + " *.";
const after = leftToken.value === "*";
const spaceRequired = mode[side];
const node = after ? leftToken : rightToken;
const type = spaceRequired ? "Missing" : "Unexpected";
const message = type + " space " + side + " *.";
context.report({
node: node,
@ -111,7 +111,7 @@ module.exports = {
* @returns {void}
*/
function checkFunction(node) {
let prevToken, starToken, nextToken;
let starToken;
if (!node.generator) {
return;
@ -124,12 +124,14 @@ module.exports = {
}
// Only check before when preceded by `function`|`static` keyword
prevToken = sourceCode.getTokenBefore(starToken);
const prevToken = sourceCode.getTokenBefore(starToken);
if (prevToken.value === "function" || prevToken.value === "static") {
checkSpacing("before", prevToken, starToken);
}
nextToken = sourceCode.getTokenAfter(starToken);
const nextToken = sourceCode.getTokenAfter(starToken);
checkSpacing("after", starToken, nextToken);
}

12
tools/eslint/lib/rules/global-require.js

@ -5,7 +5,7 @@
"use strict";
let ACCEPTABLE_PARENTS = [
const ACCEPTABLE_PARENTS = [
"AssignmentExpression",
"VariableDeclarator",
"MemberExpression",
@ -23,7 +23,7 @@ let ACCEPTABLE_PARENTS = [
* @returns {Reference|null} Returns the found reference or null if none were found.
*/
function findReference(scope, node) {
let references = scope.references.filter(function(reference) {
const 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) {
let reference = findReference(scope, node);
const reference = findReference(scope, node);
return reference && reference.resolved && reference.resolved.defs.length > 0;
}
@ -62,13 +62,13 @@ module.exports = {
create: function(context) {
return {
CallExpression: function(node) {
let currentScope = context.getScope(),
isGoodRequire;
const currentScope = context.getScope();
if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) {
isGoodRequire = context.getAncestors().every(function(parent) {
const isGoodRequire = context.getAncestors().every(function(parent) {
return ACCEPTABLE_PARENTS.indexOf(parent.type) > -1;
});
if (!isGoodRequire) {
context.report(node, "Unexpected require().");
}

2
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.
*/
let body = node.body.type === "BlockStatement" ? node.body.body[0] : node.body;
const 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.");

8
tools/eslint/lib/rules/handle-callback-err.js

@ -26,7 +26,7 @@ module.exports = {
create: function(context) {
let errorArgument = context.options[0] || "err";
const 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) {
let firstChar = stringToCheck[0];
const firstChar = stringToCheck[0];
return firstChar === "^";
}
@ -46,7 +46,7 @@ module.exports = {
*/
function matchesConfiguredErrorName(name) {
if (isPattern(errorArgument)) {
let regexp = new RegExp(errorArgument);
const regexp = new RegExp(errorArgument);
return regexp.test(name);
}
@ -70,7 +70,7 @@ module.exports = {
* @returns {void}
*/
function checkForError(node) {
let scope = context.getScope(),
const scope = context.getScope(),
parameters = getParameters(scope),
firstParameter = parameters[0];

4
tools/eslint/lib/rules/id-blacklist.js

@ -34,7 +34,7 @@ module.exports = {
// Helpers
//--------------------------------------------------------------------------
let blacklist = context.options;
const blacklist = context.options;
/**
@ -75,7 +75,7 @@ module.exports = {
return {
Identifier: function(node) {
let name = node.name,
const name = node.name,
effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
// MemberExpressions get special rules

22
tools/eslint/lib/rules/id-length.js

@ -45,18 +45,18 @@ module.exports = {
},
create: function(context) {
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 : [])
const options = context.options[0] || {};
const minLength = typeof options.min !== "undefined" ? options.min : 2;
const maxLength = typeof options.max !== "undefined" ? options.max : Infinity;
const properties = options.properties !== "never";
const exceptions = (options.exceptions ? options.exceptions : [])
.reduce(function(obj, item) {
obj[item] = true;
return obj;
}, {});
let SUPPORTED_EXPRESSIONS = {
const SUPPORTED_EXPRESSIONS = {
MemberExpression: properties && function(parent) {
return !parent.computed && (
@ -87,17 +87,17 @@ module.exports = {
return {
Identifier: function(node) {
let name = node.name;
let parent = node.parent;
const name = node.name;
const parent = node.parent;
let isShort = name.length < minLength;
let isLong = name.length > maxLength;
const isShort = name.length < minLength;
const isLong = name.length > maxLength;
if (!(isShort || isLong) || exceptions[name]) {
return; // Nothing to report
}
let isValidExpression = SUPPORTED_EXPRESSIONS[parent.type];
const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type];
if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) {
context.report(

8
tools/eslint/lib/rules/id-match.js

@ -38,10 +38,10 @@ module.exports = {
// Helpers
//--------------------------------------------------------------------------
let pattern = context.options[0] || "^.+$",
const pattern = context.options[0] || "^.+$",
regexp = new RegExp(pattern);
let options = context.options[1] || {},
const options = context.options[1] || {},
properties = !!options.properties,
onlyDeclarations = !!options.onlyDeclarations;
@ -84,7 +84,7 @@ module.exports = {
return {
Identifier: function(node) {
let name = node.name,
const name = node.name,
parent = node.parent,
effectiveParent = (parent.type === "MemberExpression") ? parent.parent : parent;
@ -122,7 +122,7 @@ module.exports = {
}
} else {
let isDeclaration = effectiveParent.type === "FunctionDeclaration" || effectiveParent.type === "VariableDeclarator";
const isDeclaration = effectiveParent.type === "FunctionDeclaration" || effectiveParent.type === "VariableDeclarator";
if (onlyDeclarations && !isDeclaration) {
return;

92
tools/eslint/lib/rules/indent.js

@ -11,8 +11,6 @@
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
let util = require("util");
let lodash = require("lodash");
module.exports = {
meta: {
@ -84,12 +82,12 @@ module.exports = {
create: function(context) {
let MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}.";
let DEFAULT_VARIABLE_INDENT = 1;
const MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}.";
const DEFAULT_VARIABLE_INDENT = 1;
let indentType = "space";
let indentSize = 4;
let options = {
const options = {
SwitchCase: 0,
VariableDeclarator: {
var: DEFAULT_VARIABLE_INDENT,
@ -99,7 +97,7 @@ module.exports = {
outerIIFEBody: null
};
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
if (context.options.length) {
if (context.options[0] === "tab") {
@ -111,10 +109,10 @@ module.exports = {
}
if (context.options[1]) {
let opts = context.options[1];
const opts = context.options[1];
options.SwitchCase = opts.SwitchCase || 0;
let variableDeclaratorRules = opts.VariableDeclarator;
const variableDeclaratorRules = opts.VariableDeclarator;
if (typeof variableDeclaratorRules === "number") {
options.VariableDeclarator = {
@ -123,7 +121,7 @@ module.exports = {
const: variableDeclaratorRules
};
} else if (typeof variableDeclaratorRules === "object") {
lodash.assign(options.VariableDeclarator, variableDeclaratorRules);
Object.assign(options.VariableDeclarator, variableDeclaratorRules);
}
if (typeof opts.outerIIFEBody === "number") {
@ -136,12 +134,12 @@ module.exports = {
}
}
let indentPattern = {
const indentPattern = {
normal: indentType === "space" ? /^ +/ : /^\t+/,
excludeCommas: indentType === "space" ? /^[ ,]+/ : /^[\t,]+/
};
let caseIndentStore = {};
const caseIndentStore = {};
/**
* Reports a given indent violation and properly pluralizes the message
@ -153,13 +151,13 @@ module.exports = {
* @returns {void}
*/
function report(node, needed, gotten, loc, isLastNodeCheck) {
let msgContext = {
const msgContext = {
needed: needed,
type: indentType,
characters: needed === 1 ? "character" : "characters",
gotten: gotten
};
let indentChar = indentType === "space" ? " " : "\t";
const indentChar = indentType === "space" ? " " : "\t";
/**
* Responsible for fixing the indentation issue fix
@ -170,7 +168,7 @@ module.exports = {
let rangeToFix = [];
if (needed > gotten) {
let spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future
const spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future
if (isLastNodeCheck === true) {
rangeToFix = [
@ -232,10 +230,10 @@ module.exports = {
* @returns {int} Indent
*/
function getNodeIndent(node, byLastLine, excludeCommas) {
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);
const token = byLastLine ? sourceCode.getLastToken(node) : sourceCode.getFirstToken(node);
const src = sourceCode.getText(token, token.loc.start.column);
const regExp = excludeCommas ? indentPattern.excludeCommas : indentPattern.normal;
const indent = regExp.exec(src);
return indent ? indent[0].length : 0;
}
@ -247,7 +245,7 @@ module.exports = {
* @returns {boolean} true if its the first in the its start line
*/
function isNodeFirstInLine(node, byEndLocation) {
let firstToken = byEndLocation === true ? sourceCode.getLastToken(node, 1) : sourceCode.getTokenBefore(node),
const 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;
@ -262,7 +260,7 @@ module.exports = {
* @returns {void}
*/
function checkNodeIndent(node, indent, excludeCommas) {
let nodeIndent = getNodeIndent(node, false, excludeCommas);
const nodeIndent = getNodeIndent(node, false, excludeCommas);
if (
node.type !== "ArrayExpression" && node.type !== "ObjectExpression" &&
@ -282,7 +280,7 @@ module.exports = {
function checkNodesIndent(nodes, indent, excludeCommas) {
nodes.forEach(function(node) {
if (node.type === "IfStatement" && node.alternate) {
let elseToken = sourceCode.getTokenBefore(node.alternate);
const elseToken = sourceCode.getTokenBefore(node.alternate);
checkNodeIndent(elseToken, indent, excludeCommas);
}
@ -297,8 +295,8 @@ module.exports = {
* @returns {void}
*/
function checkLastNodeLineIndent(node, lastLineIndent) {
let lastToken = sourceCode.getLastToken(node);
let endIndent = getNodeIndent(lastToken, true);
const lastToken = sourceCode.getLastToken(node);
const endIndent = getNodeIndent(lastToken, true);
if (endIndent !== lastLineIndent && isNodeFirstInLine(node, true)) {
report(
@ -318,7 +316,7 @@ module.exports = {
* @returns {void}
*/
function checkFirstNodeLineIndent(node, firstLineIndent) {
let startIndent = getNodeIndent(node, false);
const startIndent = getNodeIndent(node, false);
if (startIndent !== firstLineIndent && isNodeFirstInLine(node)) {
report(
@ -387,7 +385,7 @@ module.exports = {
* @returns {boolean} True if arguments are multi-line
*/
function isArgBeforeCalleeNodeMultiline(node) {
let parent = node.parent;
const 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;
@ -402,7 +400,7 @@ module.exports = {
* @returns {boolean} True if the node is the outer IIFE
*/
function isOuterIIFE(node) {
let parent = node.parent;
const parent = node.parent;
let stmt = parent.parent;
/*
@ -459,7 +457,7 @@ module.exports = {
*
* Looks for 'Models'
*/
let calleeNode = node.parent; // FunctionExpression
const calleeNode = node.parent; // FunctionExpression
let indent;
if (calleeNode.parent &&
@ -475,7 +473,7 @@ module.exports = {
}
if (calleeNode.parent.type === "CallExpression") {
let calleeParent = calleeNode.parent;
const calleeParent = calleeNode.parent;
if (calleeNode.type !== "FunctionExpression" && calleeNode.type !== "ArrowFunctionExpression") {
if (calleeParent && calleeParent.loc.start.line < node.loc.start.line) {
@ -500,7 +498,7 @@ module.exports = {
indent += functionOffset;
// check if the node is inside a variable
let parentVarNode = getVariableDeclaratorNode(node);
const parentVarNode = getVariableDeclaratorNode(node);
if (parentVarNode && isNodeInVarOnTop(node, parentVarNode)) {
indent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind];
@ -520,7 +518,7 @@ module.exports = {
* @returns {boolean} Whether or not the block starts and ends on the same line.
*/
function isSingleLineNode(node) {
let lastToken = sourceCode.getLastToken(node),
const lastToken = sourceCode.getLastToken(node),
startLine = node.loc.start.line,
endLine = lastToken.loc.end.line;
@ -567,11 +565,11 @@ module.exports = {
let nodeIndent;
let elementsIndent;
let parentVarNode = getVariableDeclaratorNode(node);
const parentVarNode = getVariableDeclaratorNode(node);
// TODO - come up with a better strategy in future
if (isNodeFirstInLine(node)) {
let parent = node.parent;
const parent = node.parent;
let effectiveParent = parent;
if (parent.type === "MemberExpression") {
@ -668,7 +666,7 @@ module.exports = {
* For this statements we should check indent from statement beginning,
* not from the beginning of the block.
*/
let statementsWithProperties = [
const statementsWithProperties = [
"IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration"
];
@ -680,7 +678,7 @@ module.exports = {
if (node.type === "IfStatement" && node.consequent.type !== "BlockStatement") {
nodesToCheck = [node.consequent];
} else if (util.isArray(node.body)) {
} else if (Array.isArray(node.body)) {
nodesToCheck = node.body;
} else {
nodesToCheck = [node.body];
@ -703,7 +701,7 @@ module.exports = {
*/
function filterOutSameLineVars(node) {
return node.declarations.reduce(function(finalCollection, elem) {
let lastElem = finalCollection[finalCollection.length - 1];
const lastElem = finalCollection[finalCollection.length - 1];
if ((elem.loc.start.line !== node.loc.start.line && !lastElem) ||
(lastElem && lastElem.loc.start.line !== elem.loc.start.line)) {
@ -720,11 +718,11 @@ module.exports = {
* @returns {void}
*/
function checkIndentInVariableDeclarations(node) {
let elements = filterOutSameLineVars(node);
let nodeIndent = getNodeIndent(node);
let lastElement = elements[elements.length - 1];
const elements = filterOutSameLineVars(node);
const nodeIndent = getNodeIndent(node);
const lastElement = elements[elements.length - 1];
let elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind];
const elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind];
// Comma can be placed before declaration
checkNodesIndent(elements, elementsIndent, true);
@ -734,7 +732,7 @@ module.exports = {
return;
}
let tokenBeforeLastElement = sourceCode.getTokenBefore(lastElement);
const tokenBeforeLastElement = sourceCode.getTokenBefore(lastElement);
if (tokenBeforeLastElement.value === ",") {
@ -764,7 +762,7 @@ module.exports = {
* @returns {int} indent size
*/
function expectedCaseIndent(node, switchIndent) {
let switchNode = (node.type === "SwitchStatement") ? node : node.parent;
const switchNode = (node.type === "SwitchStatement") ? node : node.parent;
let caseIndent;
if (caseIndentStore[switchNode.loc.start.line]) {
@ -849,11 +847,11 @@ module.exports = {
return;
}
let propertyIndent = getNodeIndent(node) + indentSize * options.MemberExpression;
const propertyIndent = getNodeIndent(node) + indentSize * options.MemberExpression;
let checkNodes = [node.property];
const checkNodes = [node.property];
let dot = context.getTokenBefore(node.property);
const dot = context.getTokenBefore(node.property);
if (dot.type === "Punctuator" && dot.value === ".") {
checkNodes.push(dot);
@ -865,8 +863,8 @@ module.exports = {
SwitchStatement: function(node) {
// Switch is not a 'BlockStatement'
let switchIndent = getNodeIndent(node);
let caseIndent = expectedCaseIndent(node, switchIndent);
const switchIndent = getNodeIndent(node);
const caseIndent = expectedCaseIndent(node, switchIndent);
checkNodesIndent(node.cases, caseIndent);
@ -880,7 +878,7 @@ module.exports = {
if (isSingleLineNode(node)) {
return;
}
let caseIndent = expectedCaseIndent(node);
const caseIndent = expectedCaseIndent(node);
checkNodesIndent(node.consequent, caseIndent + indentSize);
}

14
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) {
let declaration = node.parent;
let block = declaration.parent;
const declaration = node.parent;
const block = declaration.parent;
if (isForLoop(block)) {
if (block.type === "ForStatement") {
@ -87,11 +87,11 @@ module.exports = {
create: function(context) {
let MODE_ALWAYS = "always",
const MODE_ALWAYS = "always",
MODE_NEVER = "never";
let mode = context.options[0] || MODE_ALWAYS;
let params = context.options[1] || {};
const mode = context.options[0] || MODE_ALWAYS;
const params = context.options[1] || {};
//--------------------------------------------------------------------------
// Public API
@ -100,11 +100,11 @@ module.exports = {
return {
"VariableDeclaration:exit": function(node) {
let kind = node.kind,
const kind = node.kind,
declarations = node.declarations;
for (let i = 0; i < declarations.length; ++i) {
let declaration = declarations[i],
const declaration = declarations[i],
id = declaration.id,
initialized = isInitialized(declaration),
isIgnoredForLoop = params.ignoreForLoopInit && isForLoop(node.parent);

8
tools/eslint/lib/rules/jsx-quotes.js

@ -9,13 +9,13 @@
// Requirements
//------------------------------------------------------------------------------
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
let QUOTE_SETTINGS = {
const QUOTE_SETTINGS = {
"prefer-double": {
quote: "\"",
description: "singlequote",
@ -54,7 +54,7 @@ module.exports = {
},
create: function(context) {
let quoteOption = context.options[0] || "prefer-double",
const quoteOption = context.options[0] || "prefer-double",
setting = QUOTE_SETTINGS[quoteOption];
/**
@ -69,7 +69,7 @@ module.exports = {
return {
JSXAttribute: function(node) {
let attributeValue = node.value;
const attributeValue = node.value;
if (attributeValue && astUtils.isStringLiteral(attributeValue) && !usesExpectedQuotes(attributeValue)) {
context.report({

56
tools/eslint/lib/rules/key-spacing.js

@ -34,9 +34,8 @@ function last(arr) {
* @returns {boolean} True if the candidate property is part of the group.
*/
function continuesPropertyGroup(lastMember, candidate) {
let groupEndLine = lastMember.loc.start.line,
candidateStartLine = candidate.loc.start.line,
comments, i;
const groupEndLine = lastMember.loc.start.line,
candidateStartLine = candidate.loc.start.line;
if (candidateStartLine - groupEndLine <= 1) {
return true;
@ -45,13 +44,14 @@ function continuesPropertyGroup(lastMember, candidate) {
// Check that the first comment is adjacent to the end of the group, the
// last comment is adjacent to the candidate property, and that successive
// comments are adjacent to each other.
comments = candidate.leadingComments;
const comments = candidate.leadingComments;
if (
comments &&
comments[0].loc.start.line - groupEndLine <= 1 &&
candidateStartLine - last(comments).loc.end.line <= 1
) {
for (i = 1; i < comments.length; i++) {
for (let i = 1; i < comments.length; i++) {
if (comments[i].loc.start.line - comments[i - 1].loc.end.line > 1) {
return false;
}
@ -150,7 +150,7 @@ function initOptions(toOptions, fromOptions) {
// Rule Definition
//------------------------------------------------------------------------------
let messages = {
const messages = {
key: "{{error}} space after {{computed}}key '{{key}}'.",
value: "{{error}} space before value for {{computed}}key '{{key}}'."
};
@ -333,13 +333,13 @@ module.exports = {
* align: "colon" // Optional, or "value"
* }
*/
let options = context.options[0] || {},
const options = context.options[0] || {},
ruleOptions = initOptions({}, options),
multiLineOptions = ruleOptions.multiLine,
singleLineOptions = ruleOptions.singleLine,
alignmentOptions = ruleOptions.align || null;
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
/**
* Determines if the given property is key-value property.
@ -392,7 +392,7 @@ module.exports = {
* @returns {string} The property's key.
*/
function getKey(property) {
let key = property.key;
const key = property.key;
if (property.computed) {
return sourceCode.getText().slice(key.range[0], key.range[1]);
@ -412,7 +412,7 @@ module.exports = {
* @returns {void}
*/
function report(property, side, whitespace, expected, mode) {
let diff = whitespace.length - expected,
const diff = whitespace.length - expected,
nextColon = getNextColon(property.key),
tokenBeforeColon = sourceCode.getTokenBefore(nextColon),
tokenAfterColon = sourceCode.getTokenAfter(nextColon),
@ -420,9 +420,8 @@ module.exports = {
locStart = isKeySide ? tokenBeforeColon.loc.start : tokenAfterColon.loc.start,
isExtra = diff > 0,
diffAbs = Math.abs(diff),
spaces = Array(diffAbs + 1).join(" "),
fix,
range;
spaces = Array(diffAbs + 1).join(" ");
let fix;
if ((
diff && mode === "strict" ||
@ -431,6 +430,7 @@ module.exports = {
!(expected && containsLineTerminator(whitespace))
) {
if (isExtra) {
let range;
// Remove whitespace
if (isKeySide) {
@ -476,10 +476,8 @@ module.exports = {
* @returns {int} Width of the key.
*/
function getKeyWidth(property) {
let startToken, endToken;
startToken = sourceCode.getFirstToken(property);
endToken = getLastTokenBeforeColon(property.key);
const startToken = sourceCode.getFirstToken(property);
const endToken = getLastTokenBeforeColon(property.key);
return endToken.range[1] - startToken.range[0];
}
@ -490,7 +488,7 @@ module.exports = {
* @returns {Object} Whitespace before and after the property's colon.
*/
function getPropertyWhitespace(property) {
let whitespace = /(\s*):(\s*)/.exec(sourceCode.getText().slice(
const whitespace = /(\s*):(\s*)/.exec(sourceCode.getText().slice(
property.key.range[1], property.value.range[0]
));
@ -514,7 +512,7 @@ module.exports = {
}
return node.properties.reduce(function(groups, property) {
let currentGroup = last(groups),
const currentGroup = last(groups),
prev = last(currentGroup);
if (!prev || continuesPropertyGroup(prev, property)) {
@ -535,11 +533,10 @@ module.exports = {
* @returns {void}
*/
function verifyGroupAlignment(properties) {
let length = properties.length,
const 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 = alignmentOptions.on; // "value" or "colon"
let targetWidth = Math.max.apply(null, widths),
beforeColon, afterColon, mode;
if (alignmentOptions && length > 1) { // When aligning values within a group, use the alignment configuration.
@ -555,11 +552,12 @@ module.exports = {
// Conditionally include one space before or after colon
targetWidth += (align === "colon" ? beforeColon : afterColon);
for (i = 0; i < length; i++) {
property = properties[i];
whitespace = getPropertyWhitespace(property);
for (let i = 0; i < length; i++) {
const property = properties[i];
const whitespace = getPropertyWhitespace(property);
if (whitespace) { // Object literal getters/setters lack a colon
width = widths[i];
const width = widths[i];
if (align === "value") {
report(property, "key", whitespace.beforeColon, beforeColon, mode);
@ -590,7 +588,7 @@ module.exports = {
* @returns {void}
*/
function verifySpacing(node, lineOptions) {
let actual = getPropertyWhitespace(node);
const actual = getPropertyWhitespace(node);
if (actual) { // Object literal getters/setters lack colons
report(node, "key", actual.beforeColon, lineOptions.beforeColon, lineOptions.mode);
@ -604,7 +602,7 @@ module.exports = {
* @returns {void}
*/
function verifyListSpacing(properties) {
let length = properties.length;
const length = properties.length;
for (let i = 0; i < length; i++) {
verifySpacing(properties[i], singleLineOptions);

60
tools/eslint/lib/rules/keyword-spacing.js

@ -9,21 +9,21 @@
// Requirements
//------------------------------------------------------------------------------
let astUtils = require("../ast-utils"),
const astUtils = require("../ast-utils"),
keywords = require("../util/keywords");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
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"]);
const PREV_TOKEN = /^[\)\]\}>]$/;
const NEXT_TOKEN = /^(?:[\(\[\{<~!]|\+\+?|--?)$/;
const PREV_TOKEN_M = /^[\)\]\}>*]$/;
const NEXT_TOKEN_M = /^[\{*]$/;
const TEMPLATE_OPEN_PAREN = /\$\{$/;
const TEMPLATE_CLOSE_PAREN = /^\}/;
const CHECK_TYPE = /^(?:JSXElement|RegularExpression|String|Template)$/;
const KEYS = keywords.concat(["as", "await", "from", "get", "let", "of", "set", "yield"]);
// check duplications.
(function() {
@ -101,7 +101,7 @@ module.exports = {
},
create: function(context) {
let sourceCode = context.getSourceCode();
const 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;
let prevToken = sourceCode.getTokenBefore(token);
const 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;
let prevToken = sourceCode.getTokenBefore(token);
const 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;
let nextToken = sourceCode.getTokenAfter(token);
const 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;
let nextToken = sourceCode.getTokenAfter(token);
const nextToken = sourceCode.getTokenAfter(token);
if (nextToken &&
(CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) &&
@ -232,22 +232,22 @@ module.exports = {
* Values are instances of `{"before": function, "after": function}`.
*/
function parseOptions(options) {
let before = !options || options.before !== false;
let after = !options || options.after !== false;
let defaultValue = {
const before = !options || options.before !== false;
const after = !options || options.after !== false;
const defaultValue = {
before: before ? expectSpaceBefore : unexpectSpaceBefore,
after: after ? expectSpaceAfter : unexpectSpaceAfter
};
let overrides = (options && options.overrides) || {};
let retv = Object.create(null);
const overrides = (options && options.overrides) || {};
const retv = Object.create(null);
for (let i = 0; i < KEYS.length; ++i) {
let key = KEYS[i];
let override = overrides[key];
const key = KEYS[i];
const override = overrides[key];
if (override) {
let thisBefore = ("before" in override) ? override.before : before;
let thisAfter = ("after" in override) ? override.after : after;
const thisBefore = ("before" in override) ? override.before : before;
const thisAfter = ("after" in override) ? override.after : after;
retv[key] = {
before: thisBefore ? expectSpaceBefore : unexpectSpaceBefore,
@ -261,7 +261,7 @@ module.exports = {
return retv;
}
let checkMethodMap = parseOptions(context.options[0]);
const 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) {
let firstToken = node && sourceCode.getFirstToken(node);
const firstToken = node && sourceCode.getFirstToken(node);
if (firstToken && firstToken.type === "Keyword") {
checkSpacingAround(firstToken);
@ -326,7 +326,7 @@ module.exports = {
* @returns {void}
*/
function checkSpacingBeforeFirstToken(node) {
let firstToken = node && sourceCode.getFirstToken(node);
const firstToken = node && sourceCode.getFirstToken(node);
if (firstToken && firstToken.type === "Keyword") {
checkSpacingBefore(firstToken);
@ -445,13 +445,13 @@ module.exports = {
* @returns {void}
*/
function checkSpacingForModuleDeclaration(node) {
let firstToken = sourceCode.getFirstToken(node);
const firstToken = sourceCode.getFirstToken(node);
checkSpacingBefore(firstToken, PREV_TOKEN_M);
checkSpacingAfter(firstToken, NEXT_TOKEN_M);
if (node.source) {
let fromToken = sourceCode.getTokenBefore(node.source);
const 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) {
let asToken = sourceCode.getFirstToken(node, 1);
const 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") {
let token = sourceCode.getFirstToken(
const token = sourceCode.getFirstToken(
node,
node.static ? 1 : 0
);

17
tools/eslint/lib/rules/linebreak-style.js

@ -28,10 +28,10 @@ module.exports = {
create: function(context) {
let EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.",
const EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.",
EXPECTED_CRLF_MSG = "Expected linebreaks to be 'CRLF' but found 'LF'.";
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
// Helpers
@ -56,14 +56,12 @@ module.exports = {
return {
Program: function checkForlinebreakStyle(node) {
let linebreakStyle = context.options[0] || "unix",
const linebreakStyle = context.options[0] || "unix",
expectedLF = linebreakStyle === "unix",
expectedLFChars = expectedLF ? "\n" : "\r\n",
source = sourceCode.getText(),
pattern = /\r\n|\r|\n|\u2028|\u2029/g,
match,
index,
range;
pattern = /\r\n|\r|\n|\u2028|\u2029/g;
let match;
let i = 0;
@ -73,8 +71,9 @@ module.exports = {
continue;
}
index = match.index;
range = [index, index + match[0].length];
const index = match.index;
const range = [index, index + match[0].length];
context.report({
node: node,
loc: {

36
tools/eslint/lib/rules/lines-around-comment.js

@ -8,7 +8,7 @@
// Requirements
//------------------------------------------------------------------------------
let lodash = require("lodash"),
const lodash = require("lodash"),
astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
@ -21,7 +21,7 @@ let lodash = require("lodash"),
* @returns {Array} An array of line numbers.
*/
function getEmptyLineNums(lines) {
let emptyLines = lines.map(function(line, i) {
const 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) {
let lines = [];
const lines = [];
comments.forEach(function(token) {
let start = token.loc.start.line;
let end = token.loc.end.line;
const start = token.loc.start.line;
const end = token.loc.end.line;
lines.push(start, end);
});
@ -108,7 +108,7 @@ module.exports = {
create: function(context) {
let options = context.options[0] ? lodash.assign({}, context.options[0]) : {};
const options = context.options[0] ? Object.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;
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
let lines = sourceCode.lines,
const lines = sourceCode.lines,
numLines = lines.length + 1,
comments = sourceCode.getAllComments(),
commentLines = getCommentLineNums(comments),
@ -184,7 +184,7 @@ module.exports = {
* @returns {boolean} True if the comment is at parent start.
*/
function isCommentAtParentStart(node, nodeType) {
let ancestors = context.getAncestors();
const ancestors = context.getAncestors();
let parent;
if (ancestors.length) {
@ -202,7 +202,7 @@ module.exports = {
* @returns {boolean} True if the comment is at parent end.
*/
function isCommentAtParentEnd(node, nodeType) {
let ancestors = context.getAncestors();
const ancestors = context.getAncestors();
let parent;
if (ancestors.length) {
@ -279,19 +279,19 @@ module.exports = {
let after = opts.after,
before = opts.before;
let prevLineNum = node.loc.start.line - 1,
const prevLineNum = node.loc.start.line - 1,
nextLineNum = node.loc.end.line + 1,
commentIsNotAlone = codeAroundComment(node);
let blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(node),
const 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);
let exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed;
let exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed;
const exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed;
const exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed;
// ignore top of the file and bottom of the file
if (prevLineNum < 1) {
@ -306,14 +306,14 @@ module.exports = {
return;
}
let previousTokenOrComment = sourceCode.getTokenOrCommentBefore(node);
let nextTokenOrComment = sourceCode.getTokenOrCommentAfter(node);
const previousTokenOrComment = sourceCode.getTokenOrCommentBefore(node);
const nextTokenOrComment = sourceCode.getTokenOrCommentAfter(node);
// check for newline before
if (!exceptionStartAllowed && before && !lodash.includes(commentAndEmptyLines, prevLineNum) &&
!(isCommentNodeType(previousTokenOrComment) && astUtils.isTokenOnSameLine(previousTokenOrComment, node))) {
let lineStart = node.range[0] - node.loc.start.column;
let range = [lineStart, lineStart];
const lineStart = node.range[0] - node.loc.start.column;
const range = [lineStart, lineStart];
context.report({
node: node,

8
tools/eslint/lib/rules/max-depth.js

@ -49,9 +49,9 @@ module.exports = {
// Helpers
//--------------------------------------------------------------------------
let functionStack = [],
option = context.options[0],
maxDepth = 4;
const functionStack = [],
option = context.options[0];
let maxDepth = 4;
if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") {
maxDepth = option.maximum;
@ -88,7 +88,7 @@ module.exports = {
* @private
*/
function pushBlock(node) {
let len = ++functionStack[functionStack.length - 1];
const len = ++functionStack[functionStack.length - 1];
if (len > maxDepth) {
context.report(node, "Blocks are nested too deeply ({{depth}}).",

30
tools/eslint/lib/rules/max-len.js

@ -9,7 +9,7 @@
// Constants
//------------------------------------------------------------------------------
let OPTIONS_SCHEMA = {
const OPTIONS_SCHEMA = {
type: "object",
properties: {
code: {
@ -40,7 +40,7 @@ let OPTIONS_SCHEMA = {
additionalProperties: false
};
let OPTIONS_OR_INTEGER_SCHEMA = {
const 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
*/
let URL_REGEXP = /[^:/?#]:\/\/[^?#]/;
const URL_REGEXP = /[^:/?#]:\/\/[^?#]/;
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
/**
* Computes the length of a line that may contain tabs. The width of each
@ -95,7 +95,7 @@ module.exports = {
let extraCharacterCount = 0;
line.replace(/\t/g, function(match, offset) {
let totalOffset = offset + extraCharacterCount,
const 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…
let lastOption = context.options[context.options.length - 1];
let options = typeof lastOption === "object" ? Object.create(lastOption) : {};
const lastOption = context.options[context.options.length - 1];
const options = typeof lastOption === "object" ? Object.create(lastOption) : {};
// …but max code length…
if (typeof context.options[0] === "number") {
@ -118,13 +118,13 @@ module.exports = {
options.tabWidth = context.options[1];
}
let maxLength = options.code || 80,
const maxLength = options.code || 80,
tabWidth = options.tabWidth || 4,
ignorePattern = options.ignorePattern || null,
ignoreComments = options.ignoreComments || false,
ignoreTrailingComments = options.ignoreTrailingComments || options.ignoreComments || false,
ignoreUrls = options.ignoreUrls || false,
maxCommentLength = options.comments;
let ignorePattern = options.ignorePattern || null;
if (ignorePattern) {
ignorePattern = new RegExp(ignorePattern);
@ -156,7 +156,7 @@ module.exports = {
* @returns {boolean} If the comment covers the entire line
*/
function isFullLineComment(line, lineNumber, comment) {
let start = comment.loc.start,
const start = comment.loc.start,
end = comment.loc.end,
isFirstTokenOnLine = !line.slice(0, comment.loc.start.column).trim();
@ -188,18 +188,18 @@ module.exports = {
function checkProgramForMaxLength(node) {
// split (honors line-ending)
let lines = sourceCode.lines,
const lines = sourceCode.lines,
// list of comments to ignore
comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? sourceCode.getAllComments() : [],
comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? sourceCode.getAllComments() : [];
// we iterate over comments in parallel with the lines
commentsIndex = 0;
let commentsIndex = 0;
lines.forEach(function(line, i) {
// i is zero-indexed, line numbers are one-indexed
let lineNumber = i + 1;
const lineNumber = i + 1;
/*
* if we're checking comment length; we need to know whether this
@ -235,7 +235,7 @@ module.exports = {
return;
}
let lineLength = computeLineLength(line, tabWidth);
const lineLength = computeLineLength(line, tabWidth);
if (lineIsComment && ignoreComments) {
return;

24
tools/eslint/lib/rules/max-lines.js

@ -8,8 +8,8 @@
// Requirements
//------------------------------------------------------------------------------
let lodash = require("lodash");
let astUtils = require("../ast-utils");
const lodash = require("lodash");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -52,8 +52,8 @@ module.exports = {
},
create: function(context) {
let option = context.options[0],
max = 300;
const option = context.options[0];
let max = 300;
if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") {
max = option.max;
@ -63,10 +63,10 @@ module.exports = {
max = option;
}
let skipComments = option && option.skipComments;
let skipBlankLines = option && option.skipBlankLines;
const skipComments = option && option.skipComments;
const skipBlankLines = option && option.skipBlankLines;
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
/**
* Returns whether or not a token is a comment node type
@ -125,9 +125,9 @@ module.exports = {
}
if (skipComments) {
let comments = sourceCode.getAllComments();
const comments = sourceCode.getAllComments();
let commentLines = lodash.flatten(comments.map(function(comment) {
const commentLines = lodash.flatten(comments.map(function(comment) {
return getLinesWithoutCode(comment);
}));
@ -139,7 +139,11 @@ 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. It's {{actual}} lines long.",
data: {
max,
actual: lines.length,
}
});
}
}

10
tools/eslint/lib/rules/max-nested-callbacks.js

@ -48,8 +48,8 @@ module.exports = {
//--------------------------------------------------------------------------
// Constants
//--------------------------------------------------------------------------
let option = context.options[0],
THRESHOLD = 10;
const option = context.options[0];
let THRESHOLD = 10;
if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") {
THRESHOLD = option.maximum;
@ -65,7 +65,7 @@ module.exports = {
// Helpers
//--------------------------------------------------------------------------
let callbackStack = [];
const callbackStack = [];
/**
* Checks a given function node for too many callbacks.
@ -74,14 +74,14 @@ module.exports = {
* @private
*/
function checkFunction(node) {
let parent = node.parent;
const parent = node.parent;
if (parent.type === "CallExpression") {
callbackStack.push(node);
}
if (callbackStack.length > THRESHOLD) {
let opts = {num: callbackStack.length, max: THRESHOLD};
const opts = {num: callbackStack.length, max: THRESHOLD};
context.report(node, "Too many nested callbacks ({{num}}). Maximum allowed is {{max}}.", opts);
}

4
tools/eslint/lib/rules/max-params.js

@ -45,8 +45,8 @@ module.exports = {
create: function(context) {
let option = context.options[0],
numParams = 3;
const option = context.options[0];
let numParams = 3;
if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") {
numParams = option.maximum;

12
tools/eslint/lib/rules/max-statements-per-line.js

@ -32,18 +32,18 @@ module.exports = {
create: function(context) {
let sourceCode = context.getSourceCode(),
const sourceCode = context.getSourceCode(),
options = context.options[0] || {},
lastStatementLine = 0,
numberOfStatementsOnThisLine = 0,
maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1,
message = "This line has too many statements. Maximum allowed is " + maxStatementsPerLine + ".";
let lastStatementLine = 0,
numberOfStatementsOnThisLine = 0;
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
let SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/;
const SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/;
/**
* Gets the actual last token of a given node.
@ -68,7 +68,7 @@ module.exports = {
* @returns {void}
*/
function enterStatement(node) {
let line = node.loc.start.line;
const 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) {
let line = getActualLastToken(node).loc.end.line;
const line = getActualLastToken(node).loc.end.line;
// Update state.
if (line !== lastStatementLine) {

10
tools/eslint/lib/rules/max-statements.js

@ -58,11 +58,11 @@ module.exports = {
// Helpers
//--------------------------------------------------------------------------
let functionStack = [],
const functionStack = [],
option = context.options[0],
maxStatements = 10,
ignoreTopLevelFunctions = context.options[1] && context.options[1].ignoreTopLevelFunctions || false,
topLevelFunctions = [];
let maxStatements = 10;
if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") {
maxStatements = option.maximum;
@ -107,7 +107,7 @@ module.exports = {
* @private
*/
function endFunction(node) {
let count = functionStack.pop();
const count = functionStack.pop();
if (ignoreTopLevelFunctions && functionStack.length === 0) {
topLevelFunctions.push({ node: node, count: count});
@ -147,8 +147,8 @@ module.exports = {
}
topLevelFunctions.forEach(function(element) {
let count = element.count;
let node = element.node;
const count = element.count;
const node = element.node;
reportIfTooManyStatements(node, count, maxStatements);
});

6
tools/eslint/lib/rules/multiline-ternary.js

@ -5,7 +5,7 @@
"use strict";
let astUtils = require("../ast-utils");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -50,8 +50,8 @@ module.exports = {
return {
ConditionalExpression: function(node) {
let areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(node.test, node.consequent);
let areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(node.consequent, node.alternate);
const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(node.test, node.consequent);
const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(node.consequent, node.alternate);
if (areTestAndConsequentOnSameLine) {
reportError(node.test, node);

58
tools/eslint/lib/rules/new-cap.js

@ -9,13 +9,11 @@
// Requirements
//------------------------------------------------------------------------------
let lodash = require("lodash");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
let CAPS_ALLOWED = [
const CAPS_ALLOWED = [
"Array",
"Boolean",
"Date",
@ -98,12 +96,18 @@ module.exports = {
type: "string"
}
},
newIsCapExceptionPattern: {
type: "string"
},
capIsNewExceptions: {
type: "array",
items: {
type: "string"
}
},
capIsNewExceptionPattern: {
type: "string"
},
properties: {
type: "boolean"
}
@ -115,19 +119,21 @@ module.exports = {
create: function(context) {
let config = context.options[0] ? lodash.assign({}, context.options[0]) : {};
const config = context.options[0] ? Object.assign({}, context.options[0]) : {};
config.newIsCap = config.newIsCap !== false;
config.capIsNew = config.capIsNew !== false;
let skipProperties = config.properties === false;
const skipProperties = config.properties === false;
let newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {});
const newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {});
const newIsCapExceptionPattern = config.newIsCapExceptionPattern ? new RegExp(config.newIsCapExceptionPattern) : null;
let capIsNewExceptions = calculateCapIsNewExceptions(config);
const capIsNewExceptions = calculateCapIsNewExceptions(config);
const capIsNewExceptionPattern = config.capIsNewExceptionPattern ? new RegExp(config.capIsNewExceptionPattern) : null;
let listeners = {};
const listeners = {};
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
// Helpers
@ -140,11 +146,10 @@ module.exports = {
*/
function extractNameFromExpression(node) {
let name = "",
property;
let name = "";
if (node.callee.type === "MemberExpression") {
property = node.callee.property;
const property = node.callee.property;
if (property.type === "Literal" && (typeof property.value === "string")) {
name = property.value;
@ -164,10 +169,10 @@ module.exports = {
* @returns {string} capitalization state: "non-alpha", "lower", or "upper"
*/
function getCap(str) {
let firstChar = str.charAt(0);
const firstChar = str.charAt(0);
let firstCharLower = firstChar.toLowerCase();
let firstCharUpper = firstChar.toUpperCase();
const firstCharLower = firstChar.toLowerCase();
const firstCharUpper = firstChar.toUpperCase();
if (firstCharLower === firstCharUpper) {
@ -185,10 +190,17 @@ 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
* @param {Object} pattern RegExp object from options pattern
* @returns {boolean} Returns true if the callee may be capitalized
*/
function isCapAllowed(allowedMap, node, calleeName) {
if (allowedMap[calleeName] || allowedMap[sourceCode.getText(node.callee)]) {
function isCapAllowed(allowedMap, node, calleeName, pattern) {
const sourceText = sourceCode.getText(node.callee);
if (allowedMap[calleeName] || allowedMap[sourceText]) {
return true;
}
if (pattern && pattern.test(sourceText)) {
return true;
}
@ -225,11 +237,11 @@ module.exports = {
if (config.newIsCap) {
listeners.NewExpression = function(node) {
let constructorName = extractNameFromExpression(node);
const constructorName = extractNameFromExpression(node);
if (constructorName) {
let capitalization = getCap(constructorName);
let isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName);
const capitalization = getCap(constructorName);
const isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName, newIsCapExceptionPattern);
if (!isAllowed) {
report(node, "A constructor name should not start with a lowercase letter.");
@ -241,11 +253,11 @@ module.exports = {
if (config.capIsNew) {
listeners.CallExpression = function(node) {
let calleeName = extractNameFromExpression(node);
const calleeName = extractNameFromExpression(node);
if (calleeName) {
let capitalization = getCap(calleeName);
let isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName);
const capitalization = getCap(calleeName);
const isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName, capIsNewExceptionPattern);
if (!isAllowed) {
report(node, "A function with a name starting with an uppercase letter should only be used as a constructor.");

6
tools/eslint/lib/rules/new-parens.js

@ -21,13 +21,13 @@ module.exports = {
},
create: function(context) {
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
return {
NewExpression: function(node) {
let tokens = sourceCode.getTokens(node);
let prenticesTokens = tokens.filter(function(token) {
const tokens = sourceCode.getTokens(node);
const prenticesTokens = tokens.filter(function(token) {
return token.value === "(" || token.value === ")";
});

53
tools/eslint/lib/rules/newline-after-var.js

@ -26,16 +26,16 @@ module.exports = {
create: function(context) {
let ALWAYS_MESSAGE = "Expected blank line after variable declarations.",
const ALWAYS_MESSAGE = "Expected blank line after variable declarations.",
NEVER_MESSAGE = "Unexpected blank line after variable declarations.";
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
// Default `mode` to "always".
let mode = context.options[0] === "never" ? "never" : "always";
const mode = context.options[0] === "never" ? "never" : "always";
// Cache starting and ending line numbers of comments for faster lookup
let commentEndLine = sourceCode.getAllComments().reduce(function(result, token) {
const commentEndLine = sourceCode.getAllComments().reduce(function(result, token) {
result[token.loc.start.line] = token.loc.end.line;
return result;
}, {});
@ -45,6 +45,37 @@ module.exports = {
// Helpers
//--------------------------------------------------------------------------
/**
* Gets a token from the given node to compare line to the next statement.
*
* In general, the token is the last token of the node. However, the token is the second last token if the following conditions satisfy.
*
* - The last token is semicolon.
* - The semicolon is on a different line from the previous token of the semicolon.
*
* This behavior would address semicolon-less style code. e.g.:
*
* var foo = 1
*
* ;(a || b).doSomething()
*
* @param {ASTNode} node - The node to get.
* @returns {Token} The token to compare line to the next statement.
*/
function getLastToken(node) {
const lastToken = sourceCode.getLastToken(node);
if (lastToken.type === "Punctuator" && lastToken.value === ";") {
const prevToken = sourceCode.getTokenBefore(lastToken);
if (prevToken.loc.end.line !== lastToken.loc.start.line) {
return prevToken;
}
}
return lastToken;
}
/**
* Determine if provided keyword is a variable declaration
* @private
@ -83,7 +114,7 @@ module.exports = {
* @returns {boolean} True if `node` is last of their parent block.
*/
function isLastNode(node) {
let token = sourceCode.getTokenAfter(node);
const token = sourceCode.getTokenAfter(node);
return !token || (token.type === "Punctuator" && token.value === "}");
}
@ -95,7 +126,7 @@ module.exports = {
* @returns {boolean} True if `token` does not start immediately after a comment
*/
function hasBlankLineAfterComment(token, commentStartLine) {
let commentEnd = commentEndLine[commentStartLine];
const commentEnd = commentEndLine[commentStartLine];
// If there's another comment, repeat check for blank line
if (commentEndLine[commentEnd + 1]) {
@ -114,11 +145,9 @@ module.exports = {
* @returns {void}
*/
function checkForBlankLine(node) {
let lastToken = sourceCode.getLastToken(node),
const lastToken = getLastToken(node),
nextToken = sourceCode.getTokenAfter(node),
nextLineNum = lastToken.loc.end.line + 1,
noNextLineToken,
hasNextLineComment;
nextLineNum = lastToken.loc.end.line + 1;
// Ignore if there is no following statement
if (!nextToken) {
@ -147,8 +176,8 @@ module.exports = {
}
// Next statement is not a `var`...
noNextLineToken = nextToken.loc.start.line > nextLineNum;
hasNextLineComment = (typeof commentEndLine[nextLineNum] !== "undefined");
const noNextLineToken = nextToken.loc.start.line > nextLineNum;
const hasNextLineComment = (typeof commentEndLine[nextLineNum] !== "undefined");
if (mode === "never" && noNextLineToken && !hasNextLineComment) {
context.report(node, NEVER_MESSAGE, { identifier: node.name });

19
tools/eslint/lib/rules/newline-before-return.js

@ -20,7 +20,7 @@ module.exports = {
},
create: function(context) {
let sourceCode = context.getSourceCode();
const sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
// Helpers
@ -34,7 +34,7 @@ module.exports = {
* @private
*/
function isPrecededByTokens(node, testTokens) {
let tokenBefore = sourceCode.getTokenBefore(node);
const tokenBefore = sourceCode.getTokenBefore(node);
return testTokens.some(function(token) {
return tokenBefore.value === token;
@ -48,7 +48,7 @@ module.exports = {
* @private
*/
function isFirstNode(node) {
let parentType = node.parent.type;
const parentType = node.parent.type;
if (node.parent.body) {
return Array.isArray(node.parent.body)
@ -75,8 +75,8 @@ module.exports = {
* @private
*/
function calcCommentLines(node, lineNumTokenBefore) {
let comments = sourceCode.getComments(node).leading,
numLinesComments = 0;
const comments = sourceCode.getComments(node).leading;
let numLinesComments = 0;
if (!comments.length) {
return numLinesComments;
@ -109,10 +109,9 @@ module.exports = {
* @private
*/
function hasNewlineBefore(node) {
let tokenBefore = sourceCode.getTokenBefore(node),
lineNumNode = node.loc.start.line,
lineNumTokenBefore,
commentLines;
const tokenBefore = sourceCode.getTokenBefore(node),
lineNumNode = node.loc.start.line;
let lineNumTokenBefore;
/**
* Global return (at the beginning of a script) is a special case.
@ -128,7 +127,7 @@ module.exports = {
lineNumTokenBefore = 0; // global return at beginning of script
}
commentLines = calcCommentLines(node, lineNumTokenBefore);
const commentLines = calcCommentLines(node, lineNumTokenBefore);
return (lineNumNode - lineNumTokenBefore - commentLines) > 1;
}

12
tools/eslint/lib/rules/newline-per-chained-call.js

@ -33,10 +33,10 @@ module.exports = {
create: function(context) {
let options = context.options[0] || {},
const options = context.options[0] || {},
ignoreChainWithDepth = options.ignoreChainWithDepth || 2;
let sourceCode = context.getSourceCode();
const 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) {
let prefix = node.computed ? "[" : ".";
let lines = sourceCode.getText(node.property).split(/\r\n|\r|\n/g);
let suffix = node.computed && lines.length === 1 ? "]" : "";
const prefix = node.computed ? "[" : ".";
const lines = sourceCode.getText(node.property).split(/\r\n|\r|\n/g);
const suffix = node.computed && lines.length === 1 ? "]" : "";
return prefix + lines[0] + suffix;
}
@ -59,7 +59,7 @@ module.exports = {
return;
}
let callee = node.callee;
const callee = node.callee;
let parent = callee.object;
let depth = 1;

33
tools/eslint/lib/rules/no-alert.js

@ -4,6 +4,12 @@
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const getPropertyName = require("../ast-utils").getStaticPropertyName;
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
@ -28,22 +34,6 @@ function report(context, node, identifierName) {
context.report(node, "Unexpected {{name}}.", { name: identifierName });
}
/**
* Returns the property name of a MemberExpression.
* @param {ASTNode} memberExpressionNode The MemberExpression node.
* @returns {string|null} Returns the property name if available, null else.
*/
function getPropertyName(memberExpressionNode) {
if (memberExpressionNode.computed) {
if (memberExpressionNode.property.type === "Literal") {
return memberExpressionNode.property.value;
}
} else {
return memberExpressionNode.property.name;
}
return null;
}
/**
* Finds the escope reference in the given scope.
* @param {Object} scope The scope to search.
@ -51,7 +41,7 @@ function getPropertyName(memberExpressionNode) {
* @returns {Reference|null} Returns the found reference or null if none were found.
*/
function findReference(scope, node) {
let references = scope.references.filter(function(reference) {
const references = scope.references.filter(function(reference) {
return reference.identifier.range[0] === node.range[0] &&
reference.identifier.range[1] === node.range[1];
});
@ -70,7 +60,7 @@ function findReference(scope, node) {
* @returns {boolean} Whether or not the name is shadowed.
*/
function isShadowed(scope, globalScope, node) {
let reference = findReference(scope, node);
const reference = findReference(scope, node);
return reference && reference.resolved && reference.resolved.defs.length > 0;
}
@ -117,20 +107,19 @@ module.exports = {
},
CallExpression: function(node) {
let callee = node.callee,
identifierName,
const callee = node.callee,
currentScope = context.getScope();
// without window.
if (callee.type === "Identifier") {
identifierName = callee.name;
const identifierName = callee.name;
if (!isShadowed(currentScope, globalScope, callee) && isProhibitedIdentifier(callee.name)) {
report(context, node, identifierName);
}
} else if (callee.type === "MemberExpression" && isGlobalThisReferenceOrGlobalWindow(currentScope, globalScope, callee.object)) {
identifierName = getPropertyName(callee);
const identifierName = getPropertyName(callee);
if (isProhibitedIdentifier(identifierName)) {
report(context, node, identifierName);

8
tools/eslint/lib/rules/no-bitwise.js

@ -8,7 +8,7 @@
//
// Set of bitwise operators.
//
let BITWISE_OPERATORS = [
const BITWISE_OPERATORS = [
"^", "|", "&", "<<", ">>", ">>>",
"^=", "|=", "&=", "<<=", ">>=", ">>>=",
"~"
@ -47,9 +47,9 @@ module.exports = {
},
create: function(context) {
let options = context.options[0] || {};
let allowed = options.allow || [];
let int32Hint = options.int32Hint === true;
const options = context.options[0] || {};
const allowed = options.allow || [];
const int32Hint = options.int32Hint === true;
/**
* Reports an unexpected use of a bitwise operator.

2
tools/eslint/lib/rules/no-caller.js

@ -25,7 +25,7 @@ module.exports = {
return {
MemberExpression: function(node) {
let objectName = node.object.name,
const objectName = node.object.name,
propertyName = node.property.name;
if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/)) {

2
tools/eslint/lib/rules/no-case-declarations.js

@ -41,7 +41,7 @@ module.exports = {
return {
SwitchCase: function(node) {
for (let i = 0; i < node.consequent.length; i++) {
let statement = node.consequent[i];
const statement = node.consequent[i];
if (isLexicalDeclaration(statement)) {
context.report({

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save