Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eslint

Package Overview
Dependencies
Maintainers
1
Versions
373
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint - npm Package Compare versions

Comparing version 0.17.1 to 0.18.0

lib/rules/newline-after-var.js

8

bin/eslint.js

@@ -10,3 +10,9 @@ #!/usr/bin/env node

process.stdin.pipe(concat({ encoding: "string" }, function(text) {
exitCode = cli.execute(process.argv, text);
try {
exitCode = cli.execute(process.argv, text);
} catch (ex) {
console.error(ex.message);
console.error(ex.stack);
exitCode = 1;
}
}));

@@ -13,0 +19,0 @@ } else {

@@ -72,2 +72,3 @@ {

"no-octal-escape": 2,
"no-param-reassign": 0,
"no-path-concat": 0,

@@ -139,2 +140,3 @@ "no-plusplus": 0,

"new-parens": 2,
"newline-after-var": 0,
"one-var": 0,

@@ -152,2 +154,3 @@ "operator-assignment": [0, "always"],

"space-before-blocks": [0, "always"],
"space-before-function-paren": [0, "always"],
"space-before-function-parentheses": [0, "always"],

@@ -154,0 +157,0 @@ "space-in-brackets": [0, "never"],

4

lib/config.js

@@ -58,2 +58,3 @@ /**

} catch (e) {
debug("Error reading YAML file: " + filePath);
e.message = "Cannot read config file: " + filePath + "\nError: " + e.message;

@@ -140,2 +141,3 @@ throw e;

for (i = 0; i < numFiles; i++) {
localConfigFile = localConfigFiles[i];

@@ -264,3 +266,3 @@ localConfig = loadConfig(localConfigFile);

debug("Constructing config for " + filePath);
debug("Constructing config for " + (filePath ? filePath : "text"));

@@ -267,0 +269,0 @@ config = this.cache[directory];

@@ -997,2 +997,3 @@ /**

var scope = this.getScope(),
specialScope = currentConfig.ecmaFeatures.globalReturn || currentConfig.ecmaFeatures.modules,
variables,

@@ -1002,2 +1003,7 @@ i,

// Special Node.js scope means we need to start one level deeper
if (scope.type === "global" && specialScope) {
scope = scope.childScopes[0];
}
do {

@@ -1004,0 +1010,0 @@ variables = scope.variables;

@@ -91,2 +91,16 @@ /**

/**
* Declares all relevant identifiers for module imports.
* @param {ASTNode} node The AST node representing an import.
* @returns {void}
* @private
*/
function declareImports(node) {
declare([node.local.name]);
if (node.imported && node.imported.name !== node.local.name) {
declare([node.imported.name]);
}
}
/**
* Declares all relevant identifiers for classes.

@@ -143,3 +157,5 @@ * @param {ASTNode} node The AST node representing a class.

node.elements.forEach(function(element) {
declarations.push(element.name);
if (element) {
declarations.push(element.name);
}
});

@@ -190,2 +206,6 @@ break;

"ImportSpecifier": declareImports,
"ImportDefaultSpecifier": declareImports,
"ImportNamespaceSpecifier": declareImports,
"BlockStatement": function(node) {

@@ -192,0 +212,0 @@ var statements = node.body;

/**
* @fileoverview Rule to flag non-camelcased identifiers
* @author Nicholas C. Zakas
* @copyright 2015 Dieter Oberkofler. All rights reserved.
*/

@@ -40,2 +41,9 @@

var options = context.options[0] || {},
properties = options.properties || "";
if (properties !== "always" && properties !== "never") {
properties = "always";
}
return {

@@ -67,2 +75,14 @@

// Properties have their own rules
} else if (node.parent.type === "Property") {
// "never" check properties
if (properties === "never") {
return;
}
if (isUnderscored(name) && effectiveParent.type !== "CallExpression") {
report(node);
}
// Report anything that is underscored that isn't a CallExpression

@@ -73,4 +93,5 @@ } else if (isUnderscored(name) && effectiveParent.type !== "CallExpression") {

}
};
};

@@ -18,11 +18,14 @@ /**

* Determines whether the current FunctionExpression node is a get, set, or
* shorthand method in an object literal.
* shorthand method in an object literal or a class.
* @returns {boolean} True if the node is a get, set, or shorthand method.
*/
function isObjectMethod() {
function isObjectOrClassMethod() {
var parent = context.getAncestors().pop();
return (parent.type === "Property" && (
parent.method ||
parent.kind === "get" ||
parent.kind === "set"
return (parent.type === "MethodDefinition" || (
parent.type === "Property" && (
parent.method ||
parent.kind === "get" ||
parent.kind === "set"
)
));

@@ -36,3 +39,3 @@ }

if (!name && !isObjectMethod()) {
if (!name && !isObjectOrClassMethod()) {
context.report(node, "Missing function expression name.");

@@ -39,0 +42,0 @@ }

@@ -422,3 +422,3 @@ /**

if (node.loc.start.column === children[0].loc.start.column) {
if (children.length && node.loc.start.column === children[0].loc.start.column) {
indents = 0;

@@ -425,0 +425,0 @@ }

@@ -23,21 +23,2 @@ /**

/**
* Gets an object literal property's key as the identifier name or string value.
* @param {ASTNode} property Property node whose key to retrieve.
* @returns {string} The property's key.
*/
function getKey(property) {
return property.key.name || property.key.value;
}
/**
* Gets the number of characters in a key, including quotes around string keys.
* @param {ASTNode} property Property of on object literal.
* @returns {int} Width of the key, including string quotes where present.
*/
function getKeyWidth(property) {
var key = property.key;
return (key.type === "Identifier" ? key.name : key.raw).length;
}
/**
* Gets the last element of an array.

@@ -91,4 +72,4 @@ * @param {Array} arr An array.

var messages = {
key: "{{error}} space after key \"{{key}}\".",
value: "{{error}} space before value for key \"{{key}}\"."
key: "{{error}} space after {{computed}}key \"{{key}}\".",
value: "{{error}} space before value for {{computed}}key \"{{key}}\"."
};

@@ -113,17 +94,14 @@

/**
* Gets the whitespace around the colon in an object literal property.
* @param {ASTNode} property Property node from an object literal.
* @returns {Object} Whitespace before and after the property's colon.
* Gets an object literal property's key as the identifier name or string value.
* @param {ASTNode} property Property node whose key to retrieve.
* @returns {string} The property's key.
*/
function getPropertyWhitespace(property) {
var whitespace = /^(\s*):(\s*)/.exec(context.getSource().slice(
property.key.range[1], property.value.range[0]
));
function getKey(property) {
var key = property.key;
if (whitespace) {
return {
beforeColon: whitespace[1],
afterColon: whitespace[2]
};
if (property.computed) {
return context.getSource().slice(key.range[0], key.range[1]);
}
return property.key.name || property.key.value;
}

@@ -149,2 +127,3 @@

error: diff > 0 ? "Extra" : "Missing",
computed: property.computed ? "computed " : "",
key: getKey(property)

@@ -156,2 +135,49 @@ });

/**
* Gets the number of characters in a key, including quotes around string
* keys and braces around computed property keys.
* @param {ASTNode} property Property of on object literal.
* @returns {int} Width of the key.
*/
function getKeyWidth(property) {
var key = property.key,
startToken, endToken;
// [computed]: value
if (property.computed) {
startToken = context.getTokenBefore(key);
endToken = context.getTokenAfter(key);
return endToken.range[1] - startToken.range[0];
}
// name: value
if (key.type === "Identifier") {
return key.name.length;
}
// "literal": value
// 42: value
if (key.type === "Literal") {
return key.raw.length;
}
}
/**
* Gets the whitespace around the colon in an object literal property.
* @param {ASTNode} property Property node from an object literal.
* @returns {Object} Whitespace before and after the property's colon.
*/
function getPropertyWhitespace(property) {
var whitespace = /(\s*):(\s*)/.exec(context.getSource().slice(
property.key.range[1], property.value.range[0]
));
if (whitespace) {
return {
beforeColon: whitespace[1],
afterColon: whitespace[2]
};
}
}
/**
* Verifies correct vertical alignment of a group of properties.

@@ -158,0 +184,0 @@ * @param {ASTNode[]} properties List of Property AST nodes.

@@ -11,11 +11,12 @@ /**

var CAPS_ALLOWED = [
"Object",
"Array",
"Boolean",
"Date",
"Error",
"Function",
"Number",
"Object",
"RegExp",
"String",
"Boolean",
"Date",
"Array",
"Symbol",
"RegExp"
"Symbol"
];

@@ -143,3 +144,3 @@

return node.callee.object.type === "Identifier" &&
node.callee.object.name === "Date";
node.callee.object.name === "Date";
}

@@ -146,0 +147,0 @@ return false;

@@ -39,3 +39,3 @@ /**

case "AssignmentExpression":
return isConstant(node.right);
return (node.operator === "=") && isConstant(node.right);
case "SequenceExpression":

@@ -42,0 +42,0 @@ return isConstant(node.expressions[node.expressions.length - 1]);

@@ -26,11 +26,41 @@ /**

function checkParams(node) {
var dups = {};
var params = {},
dups = {};
/**
* Marks a given param as either seen or duplicated.
* @param {string} name The name of the param to mark.
* @returns {void}
* @private
*/
function markParam(name) {
if (params.hasOwnProperty(name)) {
dups[name] = 1;
} else {
params[name] = 1;
}
}
// loop through and find each duplicate param
node.params.map(function(param) {
return param.name;
}).forEach(function(param, i, params) {
var lastPos = params.lastIndexOf(param);
if (i !== lastPos) {
dups[param] = [i, lastPos];
node.params.forEach(function(param) {
switch (param.type) {
case "Identifier":
markParam(param.name);
break;
case "ObjectPattern":
param.properties.forEach(function(property) {
markParam(property.key.name);
});
break;
case "ArrayPattern":
param.elements.forEach(function(element) {
markParam(element.name);
});
break;
// no default
}

@@ -37,0 +67,0 @@ });

@@ -5,2 +5,3 @@ /**

* @copyright Nicholas C. Zakas. All rights reserved.
* @copyright 2015 Dieter Oberkofler. All rights reserved.
*/

@@ -18,16 +19,26 @@ "use strict";

"BlockStatement": function(node) {
var ancestors = context.getAncestors(),
parent = ancestors[ancestors.length - 1],
var parent = node.parent,
parentType = parent.type,
hasHandler = !!(parent.handler || (parent.handlers && parent.handlers.length)),
isFinallyBlock = (parentType === "TryStatement") && (parent.finalizer === node);
comments,
i;
if (/Function|CatchClause/.test(parentType) ||
(isFinallyBlock && !hasHandler)) {
// if the body is not empty, we can just return immediately
if (node.body.length !== 0) {
return;
}
if (node.body.length === 0) {
context.report(node, "Empty block statement.");
// a function is generally allowed to be empty
if (parentType === "FunctionDeclaration" || parentType === "FunctionExpression" || parentType === "ArrowFunctionExpression") {
return;
}
// any other block is only allowed to be empty, if it contains an empty comment
comments = context.getComments(node).trailing;
for (i = 0; i < comments.length; i++) {
if (comments[i].value.trim() === "empty") {
return;
}
}
context.report(node, "Empty block statement.");
},

@@ -34,0 +45,0 @@

@@ -14,4 +14,3 @@ /**

var inCatch = false,
exceptionName = null;
var catchStack = [];

@@ -21,9 +20,7 @@ return {

"CatchClause": function(node) {
inCatch = true;
exceptionName = node.param.name;
catchStack.push(node.param.name);
},
"CatchClause:exit": function() {
inCatch = false;
exceptionName = null;
catchStack.pop();
},

@@ -33,5 +30,7 @@

if (inCatch) {
if (catchStack.length > 0) {
if (node.left.name === exceptionName) {
var exceptionName = catchStack[catchStack.length - 1];
if (node.left.name && node.left.name === exceptionName) {
context.report(node, "Do not assign to the exception parameter.");

@@ -38,0 +37,0 @@ }

@@ -56,12 +56,2 @@ /**

/**
* Checks if a node name match the JSX tag convention.
* @param {String} name - Name of the node to check.
* @returns {boolean} Whether or not the node name match the JSX tag convention.
*/
var tagConvention = /^[a-z]|\-/;
function isTagName(name) {
return tagConvention.test(name);
}
//------------------------------------------------------------------------------

@@ -80,28 +70,2 @@ // Rule Definition

/**
* Compare an identifier with the variables declared in the scope
* @param {ASTNode} node - Identifier or JSXIdentifier node
* @returns {void}
*/
function checkIdentifierInJSX(node) {
var scope = context.getScope(),
variables = scope.variables,
i,
len;
while (scope.type !== "global") {
scope = scope.upper;
variables = scope.variables.concat(variables);
}
for (i = 0, len = variables.length; i < len; i++) {
if (variables[i].name === node.name) {
return;
}
}
context.report(node, NOT_DEFINED_MESSAGE, { name: node.name });
}
/**
* Temporary function to fix escope issue. Remove once we upgrade to

@@ -156,8 +120,2 @@ * escope 3.x.

});
},
"JSXOpeningElement": function(node) {
if (!isTagName(node.name.name)) {
checkIdentifierInJSX(node.name);
}
}

@@ -164,0 +122,0 @@

@@ -54,4 +54,6 @@ /**

/**
* Determines if a reference is a read operation.
* @param {Reference} ref - an escope Reference
* @returns {Boolean} whether the given reference represents a read operation
* @private
*/

@@ -63,5 +65,33 @@ function isReadRef(ref) {

/**
* Determine if an identifier is referencing the enclosing function name.
* @param {Reference} ref The reference to check.
* @returns {boolean} True if it's a self-reference, false if not.
* @private
*/
function isSelfReference(ref) {
if (ref.from.type === "function" && ref.from.block.id) {
return ref.identifier.name === ref.from.block.id.name;
}
return false;
}
/**
* Determines if a reference should be counted as a read. A reference should
* be counted only if it's a read and it's not a reference to the containing
* function declaration name.
* @param {Reference} ref The reference to check.
* @returns {boolean} True if it's a value read reference, false if not.
* @private
*/
function isValidReadRef(ref) {
return isReadRef(ref) && !isSelfReference(ref);
}
/**
* Gets an array of local variables without read references.
* @param {Scope} scope - an escope Scope object
* @returns {Variable[]} most of the local variables with no read references
* @private
*/

@@ -83,4 +113,6 @@ function getUnusedLocals(scope) {

}
var type = variables[i].defs[0].type;
var def = variables[i].defs[0],
type = def.type;
// skip catch variables

@@ -90,2 +122,8 @@ if (type === "CatchClause") {

}
// skip any setter argument
if (type === "Parameter" && def.node.parent.type === "Property" && def.node.parent.kind === "set") {
continue;
}
// if "args" option is "none", skip any parameter

@@ -101,3 +139,3 @@ if (config.args === "none" && type === "Parameter") {

if (variables[i].references.filter(isReadRef).length === 0 && !isExported(variables[i])) {
if (variables[i].references.filter(isValidReadRef).length === 0 && !isExported(variables[i])) {
unused.push(variables[i]);

@@ -119,3 +157,3 @@ }

if (config.vars === "all") {
var unresolvedRefs = globalScope.through.filter(isReadRef).map(function(ref) {
var unresolvedRefs = globalScope.through.filter(isValidReadRef).map(function(ref) {
return ref.identifier.name;

@@ -122,0 +160,0 @@ });

@@ -22,6 +22,11 @@ /**

function checkFunction(node) {
var ancestors = context.getAncestors(),
previousToken, nextToken;
var previousToken, nextToken;
if (!/CallExpression|NewExpression/.test(ancestors.pop().type)) {
if (node.type === "ArrowFunctionExpression" &&
/(?:Call|New|Logical|Binary|Conditional|Update)Expression/.test(node.parent.type)
) {
return;
}
if (!/CallExpression|NewExpression/.test(node.parent.type)) {
previousToken = context.getTokenBefore(node);

@@ -28,0 +33,0 @@ nextToken = context.getTokenAfter(node);

/**
* @fileoverview A rule to ensure the use of a single variable declaration.
* @author Ian Christian Myers
* @copyright 2015 Danny Fritz. All rights reserved.
* @copyright 2013 Ian Christian Myers. All rights reserved.

@@ -15,2 +16,4 @@ */

var MODE = context.options[0] || "always";
//--------------------------------------------------------------------------

@@ -22,2 +25,7 @@ // Helpers

/**
* Increments the functionStack counter.
* @returns {void}
* @private
*/
function startFunction() {

@@ -27,2 +35,7 @@ functionStack.push(false);

/**
* Decrements the functionStack counter.
* @returns {void}
* @private
*/
function endFunction() {

@@ -32,7 +45,13 @@ functionStack.pop();

function checkDeclarations(node) {
/**
* Determines if there is more than one var statement in the current scope.
* @returns {boolean} Returns true if it is the first var declaration, false if not.
* @private
*/
function hasOnlyOneVar() {
if (functionStack[functionStack.length - 1]) {
context.report(node, "Combine this with the previous 'var' statement.");
return true;
} else {
functionStack[functionStack.length - 1] = true;
return false;
}

@@ -51,3 +70,14 @@ }

"VariableDeclaration": checkDeclarations,
"VariableDeclaration": function(node) {
var declarationCount = node.declarations.length;
if (MODE === "never") {
if (declarationCount > 1) {
context.report(node, "Split 'var' declaration into multiple statements.");
}
} else {
if (hasOnlyOneVar()) {
context.report(node, "Combine this with the previous 'var' statement.");
}
}
},

@@ -54,0 +84,0 @@ "Program:exit": endFunction,

@@ -12,2 +12,3 @@ /**

module.exports = function(context) {
var int32Hint = context.options[0] ? context.options[0].int32Hint === true : false;

@@ -42,3 +43,5 @@ var OPERATORS = [

if (!isSpaced(node.left, node.right)) {
report(node);
if (!(int32Hint && context.getSource(node).substr(-2) === "|0")) {
report(node);
}
}

@@ -45,0 +48,0 @@ }

@@ -158,11 +158,14 @@ /**

if (jsdocParams[i] && (name !== jsdocParams[i])) {
context.report(jsdocNode, "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.", {
name: name,
jsdocName: jsdocParams[i]
});
} else if (!params[name]) {
context.report(jsdocNode, "Missing JSDoc for parameter '{{name}}'.", {
name: name
});
// TODO(nzakas): Figure out logical things to do with destructured, default, rest params
if (param.type === "Identifier") {
if (jsdocParams[i] && (name !== jsdocParams[i])) {
context.report(jsdocNode, "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.", {
name: name,
jsdocName: jsdocParams[i]
});
} else if (!params[name]) {
context.report(jsdocNode, "Missing JSDoc for parameter '{{name}}'.", {
name: name
});
}
}

@@ -169,0 +172,0 @@ });

@@ -31,2 +31,12 @@ /**

/**
* Check to see if its a ES6 import declaration
* @param {ASTNode} node - any node
* @returns {Boolean} whether the given node represents a import declaration
*/
function looksLikeImport(node) {
return node.type === "ImportDeclaration" || node.type === "ImportSpecifier" ||
node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier";
}
/**
* Checks whether this variable is on top of the block body

@@ -42,3 +52,3 @@ * @param {ASTNode} node - The node to check

for (; i < l; ++i) {
if (!looksLikeDirective(statements[i])) {
if (!looksLikeDirective(statements[i]) && !looksLikeImport(statements[i])) {
break;

@@ -45,0 +55,0 @@ }

{
"name": "eslint",
"version": "0.17.1",
"version": "0.18.0",
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",

@@ -5,0 +5,0 @@ "description": "An AST-based pattern checker for JavaScript.",

@@ -9,3 +9,3 @@ [![NPM version][npm-image]][npm-url]

[Website](http://eslint.org) | [Documentation](http://eslint.org/docs) | [Contributing](http://eslint.org/docs/developer-guide/contributing.html) | [Twitter](https://twitter.com/geteslint) | [Mailing List](https://groups.google.com/group/eslint)
[Website](http://eslint.org) | [Configuring](http://eslint.org/docs/user-guide/configuring) | [Rules](http://eslint.org/docs/user-guide/rules) | [Contributing](http://eslint.org/docs/developer-guide/contributing.html) | [Twitter](https://twitter.com/geteslint) | [Mailing List](https://groups.google.com/group/eslint)

@@ -12,0 +12,0 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code. In many ways, it is similar to JSLint and JSHint with a few exceptions:

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc