Comparing version 0.18.0 to 0.19.0
@@ -22,2 +22,3 @@ { | ||
"no-constant-condition": 2, | ||
"no-continue": 0, | ||
"no-control-regex": 2, | ||
@@ -143,2 +144,3 @@ "no-debugger": 2, | ||
"operator-assignment": [0, "always"], | ||
"operator-linebreak": 0, | ||
"padded-blocks": 0, | ||
@@ -145,0 +147,0 @@ "quote-props": 0, |
@@ -41,2 +41,3 @@ /** | ||
* @property {boolean} reset True disables all default rules and environments. | ||
* @property {boolean|object} baseConfig Base config object. False disables all default rules and environments. | ||
* @property {boolean} ignore False disables use of .eslintignore. | ||
@@ -73,2 +74,3 @@ * @property {string[]} rulePaths An array of directories to load custom rules from. | ||
reset: false, | ||
baseConfig: require(path.resolve(__dirname, "..", "conf", "eslint.json")), | ||
rulePaths: [], | ||
@@ -75,0 +77,0 @@ useEslintrc: true, |
@@ -219,2 +219,3 @@ /** | ||
var useConfig; | ||
options = options || {}; | ||
@@ -226,4 +227,12 @@ | ||
this.baseConfig = options.reset ? { rules: {} } : | ||
require(path.resolve(__dirname, "..", "conf", "eslint.json")); | ||
if (options.reset || options.baseConfig === false) { | ||
// If `options.reset` is truthy or `options.baseConfig` is set to `false`, | ||
// disable all default rules and environments | ||
this.baseConfig = { rules: {} }; | ||
} else { | ||
// If `options.baseConfig` is an object, just use it, | ||
// otherwise use default base config from `conf/eslint.json` | ||
this.baseConfig = options.baseConfig || | ||
require(path.resolve(__dirname, "..", "conf", "eslint.json")); | ||
} | ||
@@ -230,0 +239,0 @@ this.baseConfig.format = options.format; |
@@ -27,15 +27,6 @@ /** | ||
// Have to modify estraverse until TryStatement.handlers is removed | ||
estraverse.VisitorKeys.TryStatement = ["block", "handlers", "finalizer"]; | ||
// TODO: Remove when estraverse is updated | ||
estraverse.Syntax.Super = "Super"; | ||
estraverse.VisitorKeys.Super = []; | ||
// TODO: Remove when estraverse is updated | ||
estraverse.Syntax.ExportNamedDeclaration = "ExportNamedDeclaration"; | ||
estraverse.Syntax.ExportDefaultDeclaration = "ExportDefaultDeclaration"; | ||
estraverse.Syntax.ExportAllDeclaration = "ExportAllDeclaration"; | ||
estraverse.Syntax.ExportSpecifier = "ExportSpecifier"; | ||
estraverse.VisitorKeys.ExportNamedDeclaration = ["declaration", "specifies", "source"]; | ||
estraverse.VisitorKeys.ExportAllDeclaration = ["source"]; | ||
estraverse.VisitorKeys.ExportDefaultDeclaration = ["declaration"]; | ||
estraverse.VisitorKeys.ExportNamedDeclaration = ["declaration", "specifiers", "source"]; | ||
estraverse.VisitorKeys.ExportSpecifier = ["exported", "local"]; | ||
/** | ||
@@ -980,3 +971,7 @@ * Parses a list of "name:boolean_value" or/and "name" options divided by comma or | ||
if (scope) { | ||
return scope; | ||
if (scope.type === "function-expression-name") { | ||
return scope.childScopes[0]; | ||
} else { | ||
return scope; | ||
} | ||
} | ||
@@ -983,0 +978,0 @@ |
@@ -111,3 +111,2 @@ /** | ||
function declareClass(node) { | ||
pushScope(); | ||
@@ -117,2 +116,4 @@ if (node.id) { | ||
} | ||
pushScope(); | ||
} | ||
@@ -164,2 +165,10 @@ | ||
case "AssignmentPattern": | ||
declareByNodeType(node.left); | ||
break; | ||
case "RestElement": | ||
declareByNodeType(node.argument); | ||
break; | ||
// no default | ||
@@ -172,2 +181,8 @@ } | ||
/** | ||
* Adds declarations of the function parameters and pushes the scope | ||
* @param {ASTNode} node The node containing declarations. | ||
* @returns {void} | ||
* @private | ||
*/ | ||
function functionHandler(node) { | ||
@@ -180,3 +195,2 @@ pushScope(); | ||
declare(node.id ? [node.id.name] : []); | ||
declare(node.rest ? [node.rest.name] : []); | ||
@@ -186,2 +200,24 @@ declare(["arguments"]); | ||
/** | ||
* Adds declaration of the function name in its parent scope then process the function | ||
* @param {ASTNode} node The node containing declarations. | ||
* @returns {void} | ||
* @private | ||
*/ | ||
function functionDeclarationHandler(node) { | ||
declare(node.id ? [node.id.name] : []); | ||
functionHandler(node); | ||
} | ||
/** | ||
* Process function declarations and declares its name in its own scope | ||
* @param {ASTNode} node The node containing declarations. | ||
* @returns {void} | ||
* @private | ||
*/ | ||
function functionExpressionHandler(node) { | ||
functionHandler(node); | ||
declare(node.id ? [node.id.name] : []); | ||
} | ||
function variableDeclarationHandler(node) { | ||
@@ -238,3 +274,3 @@ node.declarations.forEach(function(declaration) { | ||
"FunctionDeclaration": functionHandler, | ||
"FunctionDeclaration": functionDeclarationHandler, | ||
"FunctionDeclaration:exit": popScope, | ||
@@ -251,5 +287,6 @@ | ||
"FunctionExpression": functionHandler, | ||
"FunctionExpression": functionExpressionHandler, | ||
"FunctionExpression:exit": popScope, | ||
// Arrow functions cannot have names | ||
"ArrowFunctionExpression": functionHandler, | ||
@@ -256,0 +293,0 @@ "ArrowFunctionExpression:exit": popScope, |
@@ -59,2 +59,7 @@ /** | ||
// "never" check properties | ||
if (properties === "never") { | ||
return; | ||
} | ||
// Always report underscored object names | ||
@@ -61,0 +66,0 @@ if (node.parent.object.type === "Identifier" && |
@@ -66,2 +66,11 @@ /** | ||
/** | ||
* Checks whether a node is contained on a single line. | ||
* @param {ASTNode} node AST Node being evaluated. | ||
* @returns {boolean} True if the node is a single line. | ||
*/ | ||
function isSingleLine(node) { | ||
return (node.loc.end.line === node.loc.start.line); | ||
} | ||
//------------------------------------------------------------------------------ | ||
@@ -179,2 +188,26 @@ // Rule Definition | ||
/** | ||
* Creates groups of properties. | ||
* @param {ASTNode} node ObjectExpression node being evaluated. | ||
* @returns {ASTNode[]} Groups of property AST node lists. | ||
*/ | ||
function createGroups(node) { | ||
if (node.properties.length === 1) { | ||
return node.properties; | ||
} | ||
return node.properties.reduce(function(groups, property) { | ||
var currentGroup = last(groups), | ||
prev = last(currentGroup); | ||
if (!prev || continuesPropertyGroup(prev, property)) { | ||
currentGroup.push(property); | ||
} else { | ||
groups.push([property]); | ||
} | ||
return groups; | ||
}, [[]]); | ||
} | ||
/** | ||
* Verifies correct vertical alignment of a group of properties. | ||
@@ -184,3 +217,3 @@ * @param {ASTNode[]} properties List of Property AST nodes. | ||
*/ | ||
function verifyAlignment(properties) { | ||
function verifyGroupAlignment(properties) { | ||
var length = properties.length, | ||
@@ -214,2 +247,43 @@ widths = properties.map(getKeyWidth), // Width of keys, including quotes | ||
/** | ||
* Verifies vertical alignment, taking into account groups of properties. | ||
* @param {ASTNode} node ObjectExpression node being evaluated. | ||
* @returns {void} | ||
*/ | ||
function verifyAlignment(node) { | ||
createGroups(node).forEach(function(group) { | ||
verifyGroupAlignment(group); | ||
}); | ||
} | ||
/** | ||
* Verifies spacing of property conforms to specified options. | ||
* @param {ASTNode} node Property node being evaluated. | ||
* @returns {void} | ||
*/ | ||
function verifySpacing(node) { | ||
var whitespace = getPropertyWhitespace(node); | ||
if (whitespace) { // Object literal getters/setters lack colons | ||
report(node, "key", whitespace.beforeColon, beforeColon); | ||
report(node, "value", whitespace.afterColon, afterColon); | ||
} | ||
} | ||
/** | ||
* Verifies spacing of each property in a list. | ||
* @param {ASTNode[]} properties List of Property AST nodes. | ||
* @returns {void} | ||
*/ | ||
function verifyListSpacing(properties) { | ||
var length = properties.length; | ||
for (var i = 0; i < length; i++) { | ||
verifySpacing(properties[i]); | ||
} | ||
} | ||
//-------------------------------------------------------------------------- | ||
// Public API | ||
//-------------------------------------------------------------------------- | ||
if (align) { // Verify vertical alignment | ||
@@ -219,16 +293,7 @@ | ||
"ObjectExpression": function(node) { | ||
node.properties.reduce(function(groups, property) { | ||
var currentGroup = last(groups), | ||
prev = last(currentGroup); | ||
if (!prev || continuesPropertyGroup(prev, property)) { | ||
currentGroup.push(property); | ||
} else { | ||
groups.push([property]); | ||
} | ||
return groups; | ||
}, [[]]).forEach(function(group) { | ||
verifyAlignment(group); | ||
}); | ||
if (isSingleLine(node)) { | ||
verifyListSpacing(node.properties); | ||
} else { | ||
verifyAlignment(node); | ||
} | ||
} | ||
@@ -241,7 +306,3 @@ }; | ||
"Property": function (node) { | ||
var whitespace = getPropertyWhitespace(node); | ||
if (whitespace) { // Object literal getters/setters lack colons | ||
report(node, "key", whitespace.beforeColon, beforeColon); | ||
report(node, "value", whitespace.afterColon, afterColon); | ||
} | ||
verifySpacing(node); | ||
} | ||
@@ -248,0 +309,0 @@ }; |
@@ -5,2 +5,3 @@ /** | ||
* @copyright 2015 Gopal Venkatesan. All rights reserved. | ||
* @copyright 2015 Casey Visco. All rights reserved. | ||
*/ | ||
@@ -15,33 +16,77 @@ | ||
module.exports = function(context) { | ||
var mode = context.options[0], | ||
validator; // regex to validate the rule | ||
if (mode === "never") { | ||
validator = /\S(?:\r?\n)?\S/; | ||
} else { // assume mode === "always" | ||
validator = /\S(?:\r?\n){2,}\S?/; | ||
mode = "always"; | ||
var ALWAYS_MESSAGE = "Expected blank line after variable declarations.", | ||
NEVER_MESSAGE = "Unexpected blank line after variable declarations."; | ||
// Default `mode` to "always". This means that invalid options will also | ||
// be treated as "always" and the only special case is "never" | ||
var mode = context.options[0] === "never" ? "never" : "always"; | ||
// Cache line numbers of comments for faster lookup | ||
var comments = context.getAllComments().map(function (token) { | ||
return token.loc.start.line; | ||
}); | ||
//-------------------------------------------------------------------------- | ||
// Helpers | ||
//-------------------------------------------------------------------------- | ||
/** | ||
* Determine if provided keyword is a variable declaration | ||
* @private | ||
* @param {String} keyword - keyword to test | ||
* @returns {Boolean} True if `keyword` is a type of var | ||
*/ | ||
function isVar(keyword) { | ||
return keyword === "var" || keyword === "let" || keyword === "const"; | ||
} | ||
return { | ||
"VariableDeclaration:exit": function(node) { | ||
var lastToken = context.getLastToken(node), | ||
nextToken = context.getTokenAfter(node), | ||
// peek few characters beyond the last token (typically the semi-colon) | ||
sourceLines = context.getSource(lastToken, 0, 3); | ||
/** | ||
* Checks that a blank line exists after a variable declaration when mode is | ||
* set to "always", or checks that there is no blank line when mode is set | ||
* to "never" | ||
* @private | ||
* @param {ASTNode} node - `VariableDeclaration` node to test | ||
* @returns {void} | ||
*/ | ||
function checkForBlankLine(node) { | ||
var lastToken = context.getLastToken(node), | ||
nextToken = context.getTokenAfter(node), | ||
nextLineNum = lastToken.loc.end.line + 1, | ||
noNextLineToken, | ||
hasNextLineComment; | ||
// Some coding styles like Google uses multiple `var` statements. | ||
// So if the next token is a `var` statement don't do anything. | ||
if (nextToken && nextToken.type === "Keyword" && | ||
(nextToken.value === "var" || nextToken.value === "let" || nextToken.value === "const")) { | ||
return; | ||
} | ||
// Ignore if there is no following statement | ||
if (!nextToken) { | ||
return; | ||
} | ||
// Next statement is not a `var` | ||
if (sourceLines && !sourceLines.match(validator)) { | ||
context.report(node, "Newline is " + mode + " expected after a \"var\" statement.", | ||
{ identifier: node.name }); | ||
} | ||
// Some coding styles use multiple `var` statements, so do nothing if | ||
// the next token is a `var` statement. | ||
if (nextToken.type === "Keyword" && isVar(nextToken.value)) { | ||
return; | ||
} | ||
// Next statement is not a `var`... | ||
noNextLineToken = nextToken.loc.start.line > nextLineNum; | ||
hasNextLineComment = comments.indexOf(nextLineNum) >= 0; | ||
if (mode === "never" && noNextLineToken && !hasNextLineComment) { | ||
context.report(node, NEVER_MESSAGE, { identifier: node.name }); | ||
} | ||
if (mode === "always" && (!noNextLineToken || hasNextLineComment)) { | ||
context.report(node, ALWAYS_MESSAGE, { identifier: node.name }); | ||
} | ||
} | ||
//-------------------------------------------------------------------------- | ||
// Public | ||
//-------------------------------------------------------------------------- | ||
return { | ||
"VariableDeclaration": checkForBlankLine | ||
}; | ||
}; |
@@ -19,5 +19,3 @@ /** | ||
var parent = node.parent, | ||
parentType = parent.type, | ||
comments, | ||
i; | ||
parentType = parent.type; | ||
@@ -34,8 +32,5 @@ // if the body is not empty, we can just return immediately | ||
// 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; | ||
} | ||
// any other block is only allowed to be empty, if it contains a comment | ||
if (context.getComments(node).trailing.length > 0) { | ||
return; | ||
} | ||
@@ -42,0 +37,0 @@ |
@@ -40,5 +40,7 @@ /** | ||
// "arguments" is a special case that has no identifiers (#1759) | ||
variable.identifiers.length > 0 | ||
variable.identifiers.length > 0 && | ||
// function names are exempt | ||
variable.defs.length && variable.defs[0].type !== "FunctionName" | ||
) { | ||
context.report(variable.identifiers[0], "{{a}} is already declared in the upper scope.", {a: variable.name}); | ||
@@ -67,5 +69,6 @@ } | ||
"FunctionDeclaration": checkForShadows, | ||
"FunctionExpression": checkForShadows | ||
"FunctionExpression": checkForShadows, | ||
"ArrowFunctionExpression": checkForShadows | ||
}; | ||
}; |
@@ -13,3 +13,3 @@ /** | ||
var escope = require("escope"); | ||
// none! | ||
@@ -63,30 +63,7 @@ //------------------------------------------------------------------------------ | ||
var NOT_DEFINED_MESSAGE = "'{{name}}' is not defined.", | ||
READ_ONLY_MESSAGE = "'{{name}}' is read only."; | ||
var NOT_DEFINED_MESSAGE = "\"{{name}}\" is not defined.", | ||
READ_ONLY_MESSAGE = "\"{{name}}\" is read only."; | ||
// TODO: Remove once escope is updated | ||
var hackedImports = []; | ||
/** | ||
* Temporary function to fix escope issue. Remove once we upgrade to | ||
* escope 3.x. | ||
* @param {ASTNode} node The import specifier node. | ||
* @returns {void} | ||
* @private | ||
*/ | ||
function fixImport(node) { | ||
var scope = context.getScope(), | ||
variable = new escope.Variable(node.local.name, scope); | ||
variable.defs.push(node); | ||
scope.variables.push(variable); | ||
hackedImports.push(variable); | ||
} | ||
return { | ||
// TODO: Remove once escope is updated | ||
"ImportSpecifier": fixImport, | ||
"ImportNamespaceSpecifier": fixImport, | ||
"ImportDefaultSpecifier": fixImport, | ||
"Program:exit": function(/*node*/) { | ||
@@ -104,7 +81,2 @@ | ||
// hack until https://github.com/eslint/eslint/issues/1968 is properly fixed | ||
if (name === "super") { | ||
return; | ||
} | ||
if (!variable) { | ||
@@ -117,6 +89,2 @@ context.report(ref.identifier, NOT_DEFINED_MESSAGE, { name: name }); | ||
// TODO: Remove once escope is updated | ||
globalScope.variables = globalScope.variables.filter(function (variable) { | ||
return hackedImports.indexOf(variable) < 0; | ||
}); | ||
} | ||
@@ -123,0 +91,0 @@ |
@@ -38,3 +38,3 @@ /** | ||
if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier)) { | ||
context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); | ||
context.report(node, "Unexpected dangling \"_\" in \"" + identifier + "\"."); | ||
} | ||
@@ -49,3 +49,3 @@ } | ||
!isSpecialCaseIdentifierInVariableExpression(identifier)) { | ||
context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); | ||
context.report(node, "Unexpected dangling \"_\" in \"" + identifier + "\"."); | ||
} | ||
@@ -59,3 +59,3 @@ } | ||
!isSpecialCaseIdentifierForMemberExpression(identifier)) { | ||
context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); | ||
context.report(node, "Unexpected dangling \"_\" in \"" + identifier + "\"."); | ||
} | ||
@@ -62,0 +62,0 @@ } |
@@ -16,2 +16,5 @@ /** | ||
var ALWAYS_MESSAGE = "Block must be padded by blank lines.", | ||
NEVER_MESSAGE = "Block must not be padded by blank lines."; | ||
/** | ||
@@ -22,3 +25,3 @@ * Checks if the given non empty block node has a blank line before its first child node. | ||
*/ | ||
function isNonEmptyBlockTopPadded(node) { | ||
function isBlockTopPadded(node) { | ||
var blockStart = node.loc.start.line, | ||
@@ -42,6 +45,6 @@ first = node.body[0], | ||
*/ | ||
function isNonEmptyBlockBottomPadded(node) { | ||
function isBlockBottomPadded(node) { | ||
var blockEnd = node.loc.end.line, | ||
last = node.body[node.body.length - 1], | ||
lastLine = last.loc.end.line, | ||
lastLine = context.getLastToken(last).loc.end.line, | ||
expectedLastLine = blockEnd - 2, | ||
@@ -58,20 +61,2 @@ trailingComments = context.getComments(last).trailing; | ||
/** | ||
* Checks if the given non empty block node starts AND ends with a blank line. | ||
* @param {ASTNode} node The AST node of a BlockStatement. | ||
* @returns {boolean} Whether or not the block starts and ends with a blank line. | ||
*/ | ||
function isNonEmptyBlockPadded(node) { | ||
return isNonEmptyBlockTopPadded(node) && isNonEmptyBlockBottomPadded(node); | ||
} | ||
/** | ||
* Checks if the given non empty block node starts OR ends with a blank line. | ||
* @param {ASTNode} node The AST node of a BlockStatement. | ||
* @returns {boolean} Whether or not the block starts and ends with a blank line. | ||
*/ | ||
function hasNonEmptyBlockExtraPadding(node) { | ||
return isNonEmptyBlockTopPadded(node) || isNonEmptyBlockBottomPadded(node); | ||
} | ||
/** | ||
* Checks the given BlockStatement node to be padded if the block is not empty. | ||
@@ -83,10 +68,22 @@ * @param {ASTNode} node The AST node of a BlockStatement. | ||
if (node.body.length > 0) { | ||
var blockHasTopPadding = isBlockTopPadded(node), | ||
blockHasBottomPadding = isBlockBottomPadded(node); | ||
if (requirePadding) { | ||
if (!isNonEmptyBlockPadded(node)) { | ||
context.report(node, "Block must be padded by blank lines."); | ||
if (!blockHasTopPadding) { | ||
context.report(node, ALWAYS_MESSAGE); | ||
} | ||
if (!blockHasBottomPadding) { | ||
context.report(node, node.loc.end, ALWAYS_MESSAGE); | ||
} | ||
} else { | ||
if (hasNonEmptyBlockExtraPadding(node)) { | ||
context.report(node, "Block must not be padded by blank lines."); | ||
if (blockHasTopPadding) { | ||
context.report(node, NEVER_MESSAGE); | ||
} | ||
if (blockHasBottomPadding) { | ||
context.report(node, node.loc.end, NEVER_MESSAGE); | ||
} | ||
} | ||
@@ -93,0 +90,0 @@ } |
@@ -55,3 +55,3 @@ /** | ||
if (!(key.type === "Literal" && typeof key.value === "string")) { | ||
if (!node.method && !(key.type === "Literal" && typeof key.value === "string")) { | ||
context.report(node, "Unquoted property `{{key}}` found.", { | ||
@@ -58,0 +58,0 @@ key: key.name || key.value |
@@ -12,3 +12,3 @@ /** | ||
var OPT_OUT_PATTERN = /[\[\(\/\+\-]/; | ||
var OPT_OUT_PATTERN = /[\[\(\/\+\-]/; // One of [(/+- | ||
@@ -22,2 +22,21 @@ var always = context.options[0] !== "never"; | ||
/** | ||
* Reports a semicolon error with appropriate location and message. | ||
* @param {ASTNode} node The node with an extra or missing semicolon. | ||
* @returns {void} | ||
*/ | ||
function report(node) { | ||
var message = always ? "Missing semicolon." : "Extra semicolon."; | ||
context.report(node, context.getLastToken(node).loc.end, message); | ||
} | ||
/** | ||
* Checks whether a token is a semicolon punctuator. | ||
* @param {Token} token The token. | ||
* @returns {boolean} True if token is a semicolon punctuator. | ||
*/ | ||
function isSemicolon(token) { | ||
return (token.type === "Punctuator" && token.value === ";"); | ||
} | ||
/** | ||
* Check if a semicolon is unnecessary, only true if: | ||
@@ -27,12 +46,22 @@ * - next token is on a new line and is not one of the opt-out tokens | ||
* @param {Token} lastToken last token of current node. | ||
* @param {Token} nextToken next token after current node. | ||
* @returns {boolean} whether the semicolon is unnecessary. | ||
*/ | ||
function isUnnecessarySemicolon(lastToken, nextToken) { | ||
function isUnnecessarySemicolon(lastToken) { | ||
var isDivider, isOptOutToken, lastTokenLine, nextToken, nextTokenLine; | ||
var lastTokenLine = lastToken.loc.end.line, | ||
nextTokenLine = nextToken && nextToken.loc.start.line, | ||
isOptOutToken = nextToken && OPT_OUT_PATTERN.test(nextToken.value), | ||
isDivider = nextToken && (nextToken.value === "}" || nextToken.value === ";"); | ||
if (!isSemicolon(lastToken)) { | ||
return false; | ||
} | ||
nextToken = context.getTokenAfter(lastToken); | ||
if (!nextToken) { | ||
return true; | ||
} | ||
lastTokenLine = lastToken.loc.end.line; | ||
nextTokenLine = nextToken.loc.start.line; | ||
isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value); | ||
isDivider = (nextToken.value === "}" || nextToken.value === ";"); | ||
return (lastTokenLine !== nextTokenLine && !isOptOutToken) || isDivider; | ||
@@ -47,15 +76,11 @@ } | ||
function checkForSemicolon(node) { | ||
var lastToken = context.getLastToken(node), | ||
nextToken = context.getTokenAfter(node); | ||
var lastToken = context.getLastToken(node); | ||
if (always) { | ||
if (lastToken.type !== "Punctuator" || lastToken.value !== ";") { | ||
context.report(node, lastToken.loc.end, "Missing semicolon."); | ||
if (!isSemicolon(lastToken)) { | ||
report(node); | ||
} | ||
} else { | ||
if (lastToken.type === "Punctuator" && | ||
lastToken.value === ";" && | ||
isUnnecessarySemicolon(lastToken, nextToken) | ||
) { | ||
context.report(node, node.loc.end, "Extra semicolon."); | ||
if (isUnnecessarySemicolon(lastToken)) { | ||
report(node); | ||
} | ||
@@ -71,3 +96,2 @@ } | ||
function checkForSemicolonForVariableDeclaration(node) { | ||
var ancestors = context.getAncestors(), | ||
@@ -97,15 +121,13 @@ parentIndex = ancestors.length - 1, | ||
"ContinueStatement": checkForSemicolon, | ||
"EmptyStatement": function (node) { | ||
var lastToken, nextToken; | ||
if (!always) { | ||
lastToken = context.getLastToken(node); | ||
nextToken = context.getTokenAfter(node) || context.getLastToken(node); | ||
if (isUnnecessarySemicolon(lastToken, nextToken)) { | ||
context.report(node, "Extra semicolon."); | ||
} | ||
"ImportDeclaration": checkForSemicolon, | ||
"ExportAllDeclaration": checkForSemicolon, | ||
"ExportNamedDeclaration": function (node) { | ||
if (!node.declaration) { | ||
checkForSemicolon(node); | ||
} | ||
}, | ||
"ExportDefaultDeclaration": function (node) { | ||
if (!/(?:Class|Function)Declaration/.test(node.declaration.type)) { | ||
checkForSemicolon(node); | ||
} | ||
} | ||
@@ -112,0 +134,0 @@ }; |
@@ -40,4 +40,4 @@ /** | ||
missingSpaceClosers = [], | ||
rejectedSpaceOpeners = [" ", "\\n", "\\r"], | ||
rejectedSpaceClosers = [" ", "\\n", "\\r"], | ||
rejectedSpaceOpeners = ["\\s"], | ||
rejectedSpaceClosers = ["\\s"], | ||
missingSpaceCheck, | ||
@@ -102,4 +102,4 @@ rejectedSpaceCheck; | ||
function getAlwaysChecks(opts) { | ||
var missingSpaceOpeners = [" ", "\\)", "\\r", "\\n"], | ||
missingSpaceClosers = [" ", "\\(", "\\r", "\\n"], | ||
var missingSpaceOpeners = ["\\s", "\\)"], | ||
missingSpaceClosers = ["\\s", "\\("], | ||
rejectedSpaceOpeners = [], | ||
@@ -106,0 +106,0 @@ rejectedSpaceClosers = [], |
{ | ||
"name": "eslint", | ||
"version": "0.18.0", | ||
"version": "0.19.0", | ||
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>", | ||
@@ -42,4 +42,4 @@ "description": "An AST-based pattern checker for JavaScript.", | ||
"escape-string-regexp": "^1.0.2", | ||
"escope": "2.0.6", | ||
"espree": "^1.12.0", | ||
"escope": "^3.0.0", | ||
"espree": "^2.0.1", | ||
"estraverse": "^2.0.0", | ||
@@ -70,2 +70,3 @@ "estraverse-fb": "^1.3.1", | ||
"jsonlint": "^1.6.2", | ||
"markdownlint": "^0.0.3", | ||
"mocha": "^2.1.0", | ||
@@ -72,0 +73,0 @@ "mocha-phantomjs": "^3.5.0", |
@@ -9,3 +9,3 @@ [![NPM version][npm-image]][npm-url] | ||
[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) | ||
[Website](http://eslint.org) | [Configuring](http://eslint.org/docs/user-guide/configuring) | [Rules](http://eslint.org/docs/rules/) | [Contributing](http://eslint.org/docs/developer-guide/contributing) | [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: |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
501157
183
12796
22
14
+ Addedes6-weak-map@2.0.3(transitive)
+ Addedescope@3.6.0(transitive)
+ Addedespree@2.2.5(transitive)
+ Addedesrecurse@4.3.0(transitive)
+ Addedestraverse@4.3.05.3.0(transitive)
- Removedd@0.1.1(transitive)
- Removedes6-iterator@0.1.3(transitive)
- Removedes6-symbol@2.0.1(transitive)
- Removedes6-weak-map@0.1.4(transitive)
- Removedescope@2.0.6(transitive)
- Removedespree@1.12.3(transitive)
- Removedesrecurse@1.2.0(transitive)
- Removedutil-extend@1.0.3(transitive)
Updatedescope@^3.0.0
Updatedespree@^2.0.1