Skip to content
This repository has been archived by the owner on Oct 16, 2021. It is now read-only.

Commit

Permalink
tools: update ESLint to 3.3.0 and enable rules
Browse files Browse the repository at this point in the history
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: nodejs/node#8097
Reviewed-By: targos - Michaël Zasso <[email protected]>
Reviewed-By: jasnell - James M Snell <[email protected]>
Reviewed-By: Roman Reiss <[email protected]>
  • Loading branch information
Trott committed Aug 16, 2016
1 parent 88650aa commit 05b566a
Show file tree
Hide file tree
Showing 391 changed files with 4,755 additions and 5,775 deletions.
5 changes: 4 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion tools/eslint/conf/category-list.json
Original file line number Diff line number Diff line change
Expand Up @@ -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:",
Expand All @@ -32,4 +37,4 @@
{ "removed": "spaced-line-comment", "replacedBy": ["spaced-comment"] }
]
}
}
}
2 changes: 1 addition & 1 deletion tools/eslint/conf/environments.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// Requirements
//------------------------------------------------------------------------------

let globals = require("globals");
const globals = require("globals");

//------------------------------------------------------------------------------
// Public Interface
Expand Down
11 changes: 5 additions & 6 deletions tools/eslint/conf/eslint-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}, {});
Expand Down
5 changes: 5 additions & 0 deletions tools/eslint/conf/eslint.json
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand All @@ -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"
}
Expand Down
165 changes: 130 additions & 35 deletions tools/eslint/lib/ast-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 &&
Expand All @@ -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));
}

/**
Expand Down Expand Up @@ -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;
Expand All @@ -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) &&
Expand Down Expand Up @@ -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 ||
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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) {

Expand Down Expand Up @@ -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 false;
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);
Expand Down Expand Up @@ -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;
}
};
Loading

0 comments on commit 05b566a

Please sign in to comment.