Socket
Socket
Sign inDemoInstall

eslint

Package Overview
Dependencies
34
Maintainers
1
Versions
357
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.7 to 0.1.0-dev

conf/environments.json

101

conf/eslint.json
{
"env": {
"browser": false,
"node": false,
"amd": false
},
"rules": {
"no-alert": 1,
"no-caller": 1,
"no-alert": 2,
"no-caller": 2,
"no-bitwise": 0,
"no-console": 1,
"no-dangle": 1,
"no-debugger": 1,
"no-empty": 1,
"no-eval": 1,
"no-catch-shadow": 2,
"no-console": 2,
"no-comma-dangle": 2,
"no-debugger": 2,
"no-dupe-keys": 2,
"no-else-return": 0,
"no-empty": 2,
"no-empty-class": 2,
"no-eq-null": 0,
"no-eval": 2,
"no-ex-assign": 2,
"no-func-assign": 2,
"no-floating-decimal": 0,
"no-implied-eval": 1,
"no-with": 1,
"no-fallthrough": 1,
"no-unreachable": 1,
"no-undef-init": 1,
"no-octal": 1,
"no-new-wrappers": 1,
"no-new": 1,
"no-new-func": 1,
"no-implied-eval": 2,
"no-with": 2,
"no-fallthrough": 2,
"no-global-strict": 2,
"no-unreachable": 2,
"no-undef": 2,
"no-undef-init": 2,
"no-octal": 2,
"no-octal-escape": 2,
"no-obj-calls": 2,
"no-new-wrappers": 2,
"no-new": 2,
"no-new-func": 2,
"no-native-reassign": 2,
"no-plusplus": 0,
"no-delete-var": 2,
"no-return-assign": 2,
"no-new-array": 2,
"no-new-object": 2,
"no-label-var": 2,
"no-ternary": 0,
"no-self-compare": 0,
"no-sync": 0,
"no-underscore-dangle": 2,
"no-loop-func": 2,
"no-empty-label": 2,
"no-unused-vars": 2,
"no-script-url": 2,
"no-proto": 2,
"no-iterator": 2,
"no-mixed-requires": [0, false],
"no-wrap-func": 2,
"no-shadow": 2,
"no-use-before-define": 2,
"no-redeclare": 2,
"smarter-eqeqeq": 0,
"brace-style": 0,
"camelcase": 1,
"curly": 1,
"dot-notation": 1,
"eqeqeq": 1,
"new-parens": 1,
"camelcase": 2,
"curly": 2,
"dot-notation": 2,
"eqeqeq": 2,
"new-parens": 2,
"guard-for-in": 0,
"radix": 0,
"new-cap": 1,
"new-cap": 2,
"one-var": 0,
"quote-props": 0,
"semi": 1,
"use-isnan": 1,
"quotes": [1, "double"]
"semi": 2,
"use-isnan": 2,
"quotes": [2, "double"],
"max-depth": [0, 4],
"max-params": [0, 3],
"max-statements": [0, 10],
"regex-spaces": 2,
"complexity": [0, 11],
"wrap-iife": 0,
"no-multi-str": 2,
"consistent-this": [0, "that"],
"unnecessary-strict": 2,
"max-len": [0, 80, 4]
}
}
# Home
## [About](About.md)
## [About](about/README.md)
Learn more about ESLint and why it came about and the general philosophy behind it.
## [Architecture](Architecture.md)
## [Architecture](architecture/README.md)
Explains how the code is organized and why it is organized in that way.
## [Rules](Rules.md)
## [Rules](rules/README.md)
ESLint comes with some default rules to get you started. This is the complete list.
## [Command Line Interface](Command-line-interface.md)
## [Command Line Interface](command-line-interface/README.md)
ESLint is written to be used primarily for the command line. Learn about its usage here.
## [Developer Guide](Developer-Guide.md)
## [Developer Guide](developer-guide/README.md)
The developer guide contains information for ESLint developers. If you want to contribute to the project, or even just tinker on your own, this guide explains how to get the source and work with it.

@@ -6,2 +6,8 @@ /**

/*
* The CLI object should *not* call process.exit() directly. It should only return
* exit codes. This allows other programs to use the CLI object and still control
* when the program exits.
*/
//------------------------------------------------------------------------------

@@ -15,9 +21,7 @@ // Requirements

rules = require("./rules"),
eslint = require("./eslint"); // TODO: More formatters
eslint = require("./eslint"), // TODO: More formatters
existsSync = fs.existsSync || path.existsSync,
Config = require("./config");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
var DEFAULT_CONFIG = "../conf/eslint.json";

@@ -30,13 +34,2 @@ //------------------------------------------------------------------------------

function readConfig(options) {
var configLocation = null;
if (options.c || options.config) {
configLocation = path.resolve(process.cwd(), options.c ||
options.config);
}
return require(configLocation || DEFAULT_CONFIG);
}
function isDirectory(name){

@@ -62,4 +55,4 @@ try {

fs.readdirSync(stack.join("/")).forEach(function(file){
var path = stack.concat([file]).join("/"),
stat = fs.statSync(path);
var filePath = stack.concat([file]).join("/"),
stat = fs.statSync(filePath);

@@ -69,3 +62,3 @@ if (file[0] === ".") {

} else if (stat.isFile() && /\.js$/.test(file)){
files.push(path);
files.push(filePath);
} else if (stat.isDirectory()){

@@ -88,10 +81,20 @@ traverse(file, stack);

function printResults(config) {
var formatter;
var formatter,
formatterPath;
if (existsSync(path.resolve(process.cwd(), config.format))) {
formatterPath = path.resolve(process.cwd(), config.format);
} else {
formatterPath = "./formatters/" + config.format;
}
try {
formatter = require("./formatters/" + config.format);
formatter = require(formatterPath);
console.log(formatter(results, config));
return true;
} catch (ex) {
console.log("Could not find formatter '%s'.", config.format);
process.exit(1);
return false;
}
console.log(formatter(results, config));
}

@@ -102,6 +105,6 @@

* @param {string} filename The filename of the file being checked.
* @param {Object} config The configuration object for ESLint.
* @param {Object} configHelper The configuration options for ESLint.
* @returns {int} The total number of errors.
*/
function processFile(filename, config) {
function processFile(filename, configHelper) {

@@ -112,3 +115,3 @@ // clear all existing settings for a new file

var filePath = path.resolve(filename),
existsSync = fs.existsSync || path.existsSync,
config,
text,

@@ -118,7 +121,10 @@ messages;

if (existsSync(filePath)) {
config = configHelper.getConfig(filePath);
text = fs.readFileSync(path.resolve(filename), "utf8");
messages = eslint.verify(text, config);
} else {
console.log("Could not find file at '%s'.", filePath);
process.exit(1);
messages = [{
fatal: true,
message: "Could not find file at '" + filePath + "'."
}];
}

@@ -131,7 +137,16 @@

return messages.reduce(function(previous, message) {
if (message.fatal || config.rules[message.ruleId] === 2) {
var severity = null;
if (message.fatal) {
return previous + 1;
} else {
return previous;
}
severity = config.rules[message.ruleId][0] ||
config.rules[message.ruleId];
if (severity === 2) {
return previous + 1;
}
return previous;
}, 0);

@@ -143,6 +158,6 @@ }

* @param {string[]} files All of the filenames to process.
* @param {Object} config The configuration options for ESLint.
* @param {Object} configHelper The configuration options for ESLint.
* @returns {int} The total number of errors.
*/
function processFiles(files, config) {
function processFiles(files, configHelper) {

@@ -162,9 +177,9 @@ var fullFileList = [],

errors = fullFileList.reduce(function(previous, file) {
return previous + processFile(file, config);
return previous + processFile(file, configHelper);
}, 0);
printResults(config);
// If the formatter succeeds return validation errors count, otherwise
// return 1 for the formatter error.
return printResults(configHelper.getConfig()) ? errors : 1;
return errors;
}

@@ -191,3 +206,3 @@

files = currentOptions._,
config,
configHelper,
result;

@@ -208,3 +223,3 @@

config = readConfig(currentOptions);
configHelper = new Config(currentOptions);

@@ -217,9 +232,4 @@ // TODO: Figure out correct option vs. config for this

// assign format information
if (currentOptions.f) {
config.format = currentOptions.f;
}
result = processFiles(files, configHelper);
result = processFiles(files, config);
// result is the number of errors (not warnings)

@@ -230,9 +240,5 @@ return result > 0 ? 1 : 0;

return 0;
}
};
module.exports = cli;

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

estraverse = require("estraverse"),
escope = require("escope"),
environments = require("../conf/environments.json"),
rules = require("./rules"),
util = require("./util"),
RuleContext = require("./rule-context"),

@@ -25,2 +28,114 @@ EventEmitter = require("events").EventEmitter;

/**
* Parses a list of "option:value" options from a string and invokes the callback
* on each option-value pair.
* @param {string} string
* @param {function} callback
* @returns {void}
*/
function forEachOption(string, callback) {
// Collapse whitespace around : to make parsing easier
string = string.replace(/\s*:\s*/g, ":");
string.split(/\s+/).forEach(function(name) {
if (!name) {
return;
}
var pos = name.indexOf(":"),
value;
if (pos !== -1) {
value = name.substring(pos + 1, name.length);
name = name.substring(0, pos);
}
callback(name, value);
});
}
function parseBoolean(str) {
return str === "true";
}
/**
* Parses info about globals from a special block comment and adds them to the `declaredGlobals` map.
* @param {ASTNode} comment
* @param {object} declaredGlobals
* @returns {void}
*/
function parseComment(comment, declaredGlobals) {
if (comment.type !== "Block") {
return;
}
var text = comment.value;
var match;
if ((match = /^\s*(globals?)/.exec(text))) {
forEachOption(text.substring(match.index + match[1].length), function(name, value) {
declaredGlobals[name] = parseBoolean(value);
});
return true;
} else if ((match = /^\s*(js[lh]int)/.exec(text))) {
forEachOption(text.substring(match.index + match[1].length), function(name, value) {
if (parseBoolean(value) && Object.hasOwnProperty.call(environments, name)) {
util.mixin(declaredGlobals, environments[name]);
}
});
}
}
/**
* @param {Scope} scope
* @param {string} name
* @returns {Variable}
*/
function getVariable(scope, name) {
var variable = null;
scope.variables.some(function(v) {
if (v.name === name) {
variable = v;
return true;
}
return false;
});
return variable;
}
/**
* Ensures that variables representing built-in properties of the Global Object,
* and any globals declared by special block comments, are present in the global
* scope.
* @param {ASTNode} program The top node of the AST.
* @param {Scope} globalScope The global scope.
* @returns {void}
*/
function addDeclaredGlobals(program, globalScope, config) {
var declaredGlobals = {},
builtin = environments.builtin;
Object.keys(builtin).forEach(function(name) {
declaredGlobals[name] = builtin[name];
});
if (config.env) {
Object.keys(config.env).forEach(function (name) {
var environment = environments[name];
if (config.env[name] && environment) {
Object.keys(environment).forEach(function(name) {
declaredGlobals[name] = environment[name];
});
}
});
}
program.comments.forEach(function(comment) {
parseComment(comment, declaredGlobals);
});
Object.keys(declaredGlobals).forEach(function(name) {
var variable = getVariable(globalScope, name);
if (!variable) {
variable = new escope.Variable(name, globalScope);
globalScope.variables.push(variable);
}
variable.writeable = declaredGlobals[name];
});
}
//------------------------------------------------------------------------------

@@ -30,2 +145,6 @@ // Public Interface

/**
* Object that is responsible for verifying JavaScript text
* @name eslint
*/
module.exports = (function() {

@@ -35,5 +154,7 @@

messages = [],
commentsAttached = false,
currentText = null,
currentConfig = null,
currentTokens = null,
currentScopes = null,
controller = null;

@@ -48,5 +169,7 @@

messages = [];
commentsAttached = false;
currentConfig = null;
currentText = null;
currentTokens = null;
currentScopes = null;
controller = null;

@@ -63,2 +186,5 @@ };

var ast,
parseError = false;
if (!saveState) {

@@ -82,2 +208,3 @@ this.reset();

if (Array.isArray(config.rules[key])) {
// The additional config data is after the bool value

@@ -105,19 +232,13 @@ options = config.rules[key].slice(1);

/*
* Each node has a type property. Whenever a particular type of node is found,
* an event is fired. This allows any listeners to automatically be informed
* that this type of node has been found and react accordingly.
* Check for parsing errors first. If there's a parsing error, nothing
* else can happen. However, a parsing error does not throw an error
* from this method - it's just considered a fatal error message, a
* problem that ESLint identified just like any other.
*/
try {
var ast = esprima.parse(text, { loc: true, range: true, raw: true, tokens: true });
currentTokens = ast.tokens;
controller.traverse(ast, {
enter: function(node) {
api.emit(node.type, node);
},
leave: function(node) {
api.emit(node.type + ":after", node);
}
});
ast = esprima.parse(text, { loc: true, range: true, raw: true, tokens: true, comment: true });
} catch (ex) {
} catch (ex) {
parseError = true;
messages.push({

@@ -134,2 +255,34 @@ fatal: true,

if (!parseError) {
// gather data that may be needed by the rules
currentScopes = escope.analyze(ast).scopes;
/* get all tokens from the ast and store them as a hashtable to
* improve traversal speed when wanting to find tokens for a given
* node
*/
currentTokens = {};
ast.tokens.forEach(function(token) {
currentTokens[token.range[0]] = token;
});
// augment global scope with declared global variables
addDeclaredGlobals(ast, currentScopes[0], currentConfig);
/*
* Each node has a type property. Whenever a particular type of node is found,
* an event is fired. This allows any listeners to automatically be informed
* that this type of node has been found and react accordingly.
*/
controller.traverse(ast, {
enter: function(node) {
api.emit(node.type, node);
},
leave: function(node) {
api.emit(node.type + ":after", node);
}
});
}
return messages;

@@ -159,3 +312,4 @@ };

line: node.loc.start.line,
column: node.loc.start.column
column: node.loc.start.column,
source: api.getSource(node)
});

@@ -192,2 +346,30 @@ };

/**
* Returns all comments.
* @returns {Object[]}
*/
api.getAllComments = function () {
return controller.root.comments || [];
};
/**
* Gets all comments for the given node.
* @param {ASTNode} node The AST node to get the comments for.
* @returns {Object} The list of comments indexed by their position.
*/
api.getComments = function (node) {
var ast = controller.root;
if (!commentsAttached) {
// Attaching comments is a potentially expensive operation, so we do this lazily.
estraverse.attachComments(ast, ast.comments, ast.tokens);
commentsAttached = true;
}
return {
leading: node.leadingComments || [],
trailing: node.trailingComments || []
};
};
/**
* Gets all tokens that are related to the given node.

@@ -203,10 +385,16 @@ * @param {ASTNode} [node] The AST node to get the text for.

var endLocation = node.range[1] + (afterCount || 0) ;
return currentTokens.filter(function(token) {
return (token.range[0] >= startLocation &&
token.range[0] <= endLocation &&
token.range[1] >= startLocation &&
token.range[1] <= endLocation);
});
var tokens = [];
while (startLocation < endLocation) {
if (currentTokens[startLocation]) {
tokens.push(currentTokens[startLocation]);
startLocation = currentTokens[startLocation].range[1];
} else {
startLocation += 1;
}
}
return tokens;
} else {
return currentTokens || null;
return Object.keys(currentTokens).map(function(item) {
return item;
}) || null;
}

@@ -223,4 +411,77 @@ };

/**
* Gets the scope for the current node.
* @returns {Object} An object representing the current node's scope.
*/
api.getScope = function() {
var parents = controller.parents().reverse(),
innerScope = null;
// Don't do this for Program nodes - they have no parents
if (parents.length) {
// if current node is function declaration, add it to the list
var current = controller.current();
if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression") {
parents.splice(0, 0, current);
}
// Ascend the current node's parents
for (var i = 0; i < parents.length; i++) {
// The first node that requires a scope is the node that will be
// our current node's innermost scope.
if (escope.Scope.isScopeRequired(parents[i])) {
innerScope = parents[i];
break;
}
}
// Loop through the scopes returned by escope to find the innermost
// scope and return that scope.
for (var j = 0; j < currentScopes.length; j++) {
if (innerScope.type === currentScopes[j].block.type &&
innerScope.range[0] === currentScopes[j].block.range[0] &&
innerScope.range[1] === currentScopes[j].block.range[1]) {
return currentScopes[j];
}
}
} else {
return currentScopes[0]; // global scope
}
};
/**
* Defines a new linting rule.
* @param {string} unique rule identifier
* @param {function} function from context to object mapping AST node types to event handlers
* @returns {void}
*/
var defineRule = api.defineRule = function(ruleId, ruleModule) {
rules.define(ruleId, ruleModule);
};
/**
* Defines many new linting rules.
* @param {object} map from unique rule identifier to rule
* @returns {void}
*/
api.defineRules = function(rules) {
Object.getOwnPropertyNames(rules).forEach(function(ruleId){
defineRule(ruleId, rules[ruleId]);
});
};
/**
* Gets the default eslint configuration.
* @returns {Object} Object mapping rule IDs to their default configurations
*/
api.defaults = function() {
return require("./conf/eslint.json");
};
return api;
}());

@@ -12,8 +12,16 @@ /**

if (message.fatal || rules[message.ruleId] === 2) {
// TODO: Get rule severity in a better way
var severity = null;
if (message.fatal) {
return "Error";
} else {
return "Warning";
}
severity = rules[message.ruleId][0] || rules[message.ruleId];
if (severity === 2) {
return "Error";
}
return "Warning";
}

@@ -40,4 +48,4 @@

output += result.filePath + ": ";
output += "line " + message.line + ", col " +
message.column + ", " + getMessageType(message, rules);
output += "line " + (message.line || 0) + ", col " +
(message.column || 0) + ", " + getMessageType(message, rules);
output += " - " + message.message + "\n";

@@ -48,5 +56,5 @@ });

output += "\n" + total + " problems";
output += "\n" + total + " problem" + (total !== 1 ? "s" : "");
return output;
};

@@ -13,4 +13,7 @@ /**

"getTokens",
"getComments",
"getAllComments",
"isNodeJS",
"getAncestors"
"getAncestors",
"getScope"
];

@@ -17,0 +20,0 @@

@@ -7,20 +7,7 @@ /**

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
var fs = require("fs"),
path = require("path");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
var JS_EXT = ".js";
//------------------------------------------------------------------------------
// Privates
//------------------------------------------------------------------------------
var rules = {};
var rules = Object.create(null),
loadRules = require("./load-rules");

@@ -30,22 +17,14 @@ //------------------------------------------------------------------------------

//------------------------------------------------------------------------------
function define(ruleId, ruleModule) {
rules[ruleId] = ruleModule;
}
exports.load = function(directory) {
function load(rulesDir) {
var newRules = loadRules(rulesDir);
Object.keys(newRules).forEach(function(ruleId) {
define(ruleId, newRules[ruleId]);
});
}
exports.load = load;
try {
var fullPath = path.resolve(process.cwd(), directory),
files = fs.readdirSync(fullPath);
files.forEach(function(file) {
if (path.extname(file) === JS_EXT) {
var ruleId = file.replace(JS_EXT, "");
rules[ruleId] = require(path.join(fullPath, ruleId));
}
});
} catch (ex) {
console.error("Couldn't load rules from " + directory + ": " + ex.message);
process.exit(1);
}
};
exports.get = function(ruleId) {

@@ -55,2 +34,4 @@ return rules[ruleId];

exports.define = define;
//------------------------------------------------------------------------------

@@ -61,2 +42,2 @@ // Initialization

// loads built-in rules
exports.load(path.join(__dirname, "./rules"));
load();

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

"use strict";
//--------------------------------------------------------------------------

@@ -14,0 +16,0 @@ // Helpers

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

"use strict";
return {

@@ -21,3 +23,3 @@

if (name.indexOf("_") > -1 && name !== name.toUpperCase()) {
context.report(node, "Non-camelcased identifier '{{name}}' found.", { name: node.name });
context.report(node, "Identifier '{{name}}' is not in camel case.", { name: node.name });
}

@@ -24,0 +26,0 @@ }

@@ -18,2 +18,4 @@ /**

"use strict";
return {

@@ -41,2 +43,10 @@

"DoWhileStatement": function (node) {
if (node.body.type !== "BlockStatement") {
context.report(node, "Expected { after 'do'.");
}
},
"ForStatement": function(node) {

@@ -43,0 +53,0 @@

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

"use strict";
return {

@@ -18,5 +20,5 @@ "BinaryExpression": function(node) {

if (operator === "==") {
context.report(node, "Unexpected use of ==, use === instead.");
context.report(node, "Expected '===' and instead saw '=='.");
} else if (operator === "!=") {
context.report(node, "Unexpected use of !=, use !== instead.");
context.report(node, "Expected '!==' and instead saw '!='.");
}

@@ -23,0 +25,0 @@ }

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

"use strict";
return {

@@ -14,0 +16,0 @@

@@ -13,2 +13,4 @@ /**

"use strict";
return {

@@ -15,0 +17,0 @@ "NewExpression": function(node) {

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

"use strict";
return {

@@ -14,0 +16,0 @@

@@ -25,2 +25,4 @@ /**

"use strict";
return {

@@ -27,0 +29,0 @@

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

"use strict";
function report(node) {
context.report(node, "Unexpected use of '{{operator}}'.", { operator: node.operator });
}
return {
"BinaryExpression": function(node) {
// warn for ^ | &
if (node.operator.match(/^[\^&\|]$/)) {
context.report(node, "Unexpected use of {{operator}} found.", { operator: node.operator });
// warn for ^ | & ~ << >> >>>
if (node.operator.match(/^(?:[\^&\|~]|<<|>>>?)$/)) {
report(node);
}
},
"UnaryExpression": function(node) {
// warn for ~
if (node.operator === "~") {
report(node);
}
}

@@ -23,0 +37,0 @@ };

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

"use strict";
return {

@@ -19,3 +21,3 @@

if (objectName === "arguments" && propertyName.match(/^calle[er]$/)) {
if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/)) {
context.report(node, "Avoid arguments.{{property}}.", { property: propertyName });

@@ -22,0 +24,0 @@ }

@@ -13,2 +13,4 @@ /**

"use strict";
return {

@@ -15,0 +17,0 @@

@@ -13,2 +13,4 @@ /**

"use strict";
return {

@@ -15,0 +17,0 @@ "DebuggerStatement": function(node) {

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

"use strict";
return {

@@ -29,9 +31,5 @@ "BlockStatement": function(node) {

if (typeof node.cases === "undefined") {
if (typeof node.cases === "undefined" || node.cases.length === 0) {
context.report(node, "Empty switch statement.");
}
},
"EmptyStatement": function(node) {
context.report(node, "Empty statement.");
}

@@ -38,0 +36,0 @@ };

@@ -12,6 +12,8 @@ /**

"use strict";
return {
"CallExpression": function(node) {
if (node.callee.name === "eval") {
context.report(node, "Unexpected use of 'eval()'.");
context.report(node, "eval can be harmful.");
}

@@ -18,0 +20,0 @@ }

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

"use strict";
return {

@@ -16,0 +18,0 @@

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

"use strict";
return {

@@ -14,0 +16,0 @@ "Literal": function(node) {

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

"use strict";
return {

@@ -14,0 +16,0 @@ "CallExpression": function(node) {

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

"use strict";
return {

@@ -17,3 +19,3 @@

if (node.callee.name === "Function") {
context.report(node, "The Function constructor is eval");
context.report(node, "The Function constructor is eval.");
}

@@ -20,0 +22,0 @@ }

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

"use strict";
return {

@@ -18,3 +20,3 @@

if (wrapperObjects.indexOf(node.callee.name) > -1) {
context.report(node, "Do not use {{fn}} as a constructor", { fn: node.callee.name });
context.report(node, "Do not use {{fn}} as a constructor.", { fn: node.callee.name });
}

@@ -21,0 +23,0 @@ }

@@ -13,2 +13,4 @@ /**

"use strict";
return {

@@ -19,3 +21,3 @@

if (node.expression.type === "NewExpression") {
context.report(node, "Do not use 'new' for side effects");
context.report(node, "Do not use 'new' for side effects.");
}

@@ -22,0 +24,0 @@ }

@@ -12,6 +12,8 @@ /**

"use strict";
return {
"Literal": function(node) {
if (typeof node.value === "number" && node.raw[0] === "0" && node.raw.length > 1 && node.raw.indexOf("x") < 0) {
if (typeof node.value === "number" && /^0[0-7]/.test(node.raw)) {
context.report(node, "Octal literals should not be used.");

@@ -18,0 +20,0 @@ }

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

"use strict";
return {

@@ -20,3 +22,3 @@

if (init === "undefined") {
context.report(node, "Variable '{{name}}' initialized to undefined.", { name: name });
context.report(node, "It's not necessary to initialize '{{name}}' to undefined.", { name: name });
}

@@ -23,0 +25,0 @@ }

@@ -22,2 +22,4 @@ /**

"use strict";
function checkForUnreachable(node) {

@@ -24,0 +26,0 @@ switch (node.type) {

@@ -13,2 +13,4 @@ /**

"use strict";
return {

@@ -15,0 +17,0 @@ "WithStatement": function(node) {

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

"use strict";
return {

@@ -14,0 +16,0 @@

@@ -19,2 +19,4 @@ /**

"use strict";
/**

@@ -50,3 +52,3 @@ * Validate that a string passed in is surrounded by double quotes

if (!validDoubleQuotes(rawVal)) {
context.report(node, "Use double quotes for string literals.");
context.report(node, "Strings must use doublequote.");
}

@@ -56,3 +58,3 @@ break;

if (!validSingleQuotes(rawVal)) {
context.report(node, "Use single quotes for string literals.");
context.report(node, "Strings must use singlequote.");
}

@@ -59,0 +61,0 @@ break;

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

"use strict";
return {

@@ -14,0 +16,0 @@ "CallExpression": function(node) {

@@ -10,5 +10,6 @@ /**

//------------------------------------------------------------------------------
module.exports = function(context) {
"use strict";
//--------------------------------------------------------------------------

@@ -18,10 +19,26 @@ // Helpers

function checkTokenForSemicolon(node, token) {
if (token.type !== "Punctuator" || token.value !== ";") {
context.report(node, "Missing semicolon.");
}
}
function checkForSemicolon(node) {
// get tokens for the node plus one more token at the end
var tokens = context.getTokens(node, 0, 1),
var tokens = context.getTokens(node),
nextToken = tokens.pop();
if (nextToken.type !== "Punctuator" || nextToken.value !== ";") {
context.report(node, "Missing semicolon.");
checkTokenForSemicolon(node, nextToken);
}
function checkForSemicolonForVariableDeclaration(node) {
// get tokens for the node plus one more token at the end
var ancestors = context.getAncestors(),
parentIndex = ancestors.length-1,
parent = ancestors[parentIndex];
if ((parent.type !== "ForStatement" || parent.init !== node) &&
(parent.type !== "ForInStatement" || parent.left !== node)
) {
checkForSemicolon(node);
}

@@ -36,6 +53,7 @@ }

"VariableDeclaration": checkForSemicolon,
"VariableDeclaration": checkForSemicolonForVariableDeclaration,
"ExpressionStatement": checkForSemicolon
};
};

@@ -22,2 +22,4 @@ /**

"use strict";
return {

@@ -32,5 +34,5 @@ "BinaryExpression": function(node) {

if (operator === "==") {
context.report(node, "Unexpected use of ==, use === instead.");
context.report(node, "Expected '===' and instead saw '=='.");
} else if (operator === "!=") {
context.report(node, "Unexpected use of !=, use !== instead.");
context.report(node, "Expected '!==' and instead saw '!='.");
}

@@ -37,0 +39,0 @@ }

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

"use strict";
return {

@@ -14,0 +16,0 @@ "BinaryExpression": function(node) {

{
"name": "eslint",
"version": "0.0.7",
"version": "0.1.0-dev",
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",

@@ -11,5 +11,6 @@ "description": "An Esprima-based pattern checker for JavaScript.",

"scripts": {
"changelog": "bash ./scripts/changelog-update.sh",
"test": "bash ./scripts/test.sh",
"lint": "node node_modules/jshint/bin/jshint ./conf/eslint.json ./lib"
"changelog": "bash scripts/changelog-update.sh",
"test": "bash scripts/test.sh",
"lint": "node node_modules/jshint/bin/jshint ./conf/eslint.json ./lib",
"bundle": "bash scripts/bundle.sh"
},

@@ -22,5 +23,6 @@ "repository": {

"optimist": "*",
"estraverse": "~1.2.0",
"estraverse": "~1.3.0",
"esprima": "*",
"jshint": "*"
"jshint": "*",
"escope": "1.0.0"
},

@@ -31,3 +33,4 @@ "devDependencies": {

"sinon": "*",
"jshint": "~2.1.4"
"jshint": "~2.1.4",
"commonjs-everywhere": "~0.9.0"
},

@@ -34,0 +37,0 @@ "keywords": [

@@ -36,4 +36,8 @@ [![Build Status](https://secure.travis-ci.org/nzakas/eslint.png?branch=master)](http://travis-ci.org/nzakas/eslint)

### What are the plans for ESLint?
Our first goal for ESLint is to hit feature/rule and stability parity with JSHint so that developers can start using ESLint as part of their production toolchain. The master list of JSHint features to be implemented is maintained in this [Google Docs spreadsheet](https://docs.google.com/spreadsheet/lv?key=0Ap5QGaRT4AJ_dGV6VXBlMEw3NHhVRl9vQ0lIX2FnVlE&usp=sharing). To read about plans beyond parity with JSHint, check out the [ESLint Roadmap](https://github.com/nzakas/eslint/wiki/Release-goals).
### Where to ask for help?
Join our [Mailing List](https://groups.google.com/group/eslint)
Join our [Mailing List](https://groups.google.com/group/eslint)

@@ -1,1 +0,1 @@

var foo = "bar";
var foo = "bar"; if (foo) { foo = "bar2"; }

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

assert = require("assert"),
cli = require("../../lib/cli");
cli = require("../../lib/cli"),
path = require("path");

@@ -26,3 +27,3 @@ //------------------------------------------------------------------------------

"should load the specified config file": function(topic) {
var _log = console.log;
var log = console.log;

@@ -33,6 +34,6 @@ // Assign console.log to noop to skip CLI output

assert.doesNotThrow(function () {
cli.execute(["-c", topic, "lib/cli.js"]);
cli.execute(["-c", topic, "lib/cli.js"]);
});
console.log = _log;
console.log = log;
}

@@ -42,2 +43,187 @@

"when there is a local config file": {
topic: ["lib/cli.js"],
"should load the local config file": function(topic) {
var log = console.log;
// Assign console.log to noop to skip CLI output
console.log = function() {};
// Mock CWD
process.eslintCwd = path.resolve(__dirname, "..", "fixtures", "configurations", "single-quotes");
assert.doesNotThrow(function () {
exitStatus = cli.execute(topic);
});
cli.execute(topic);
process.eslintCwd = null;
console.log = log;
}
},
"when given a config with rules with options and severity level set to error": {
topic: ["--config", "tests/fixtures/configurations/quotes-error.json", "single-quoted.js"],
"should exit with an error status (1)": function(topic) {
var log = console.log,
exitStatus;
// Assign console.log to noop to skip CLI output
console.log = function() {};
assert.doesNotThrow(function () {
exitStatus = cli.execute(topic);
});
console.log = log;
assert.equal(exitStatus, 1);
},
},
"when given a config file and a directory of files": {
topic: ["--config","tests/fixtures/configurations/semi-error.json", "tests/fixtures/formatters"],
"should load and execute without error": function(topic) {
var log = console.log,
exitStatus;
// Assign console.log to noop to skip CLI output
console.log = function() {};
assert.doesNotThrow(function () {
exitStatus = cli.execute(topic);
});
console.log = log;
assert.equal(exitStatus, 0);
}
},
"when given a config with environment set to browser": {
topic: ["--config", "tests/fixtures/configurations/env-browser.json", "tests/fixtures/globals-browser.js"],
"should execute without any errors": function(topic) {
var log = console.log;
// Assign console.log to noop to skip CLI output
console.log = function() {};
var exit = cli.execute(topic);
assert.equal(exit, 0);
console.log = log;
}
},
"when given a config with environment set to Node.js": {
topic: ["--config", "tests/fixtures/configurations/env-node.json", "tests/fixtures/globals-node.js"],
"should execute without any errors": function(topic) {
var log = console.log;
// Assign console.log to noop to skip CLI output
console.log = function() {};
var exit = cli.execute(topic);
assert.equal(exit, 0);
console.log = log;
}
},
"when given a valid built-in formatter name": {
topic: "checkstyle",
"should execute without any errors": function(topic) {
var log = console.log;
// Assign console.log to noop to skip CLI output
console.log = function() {};
var exit = cli.execute(["-f", topic, "tests/fixtures/passing.js"]);
assert.equal(exit, 0);
console.log = log;
}
},
"when given an invalid built-in formatter name": {
topic: "fakeformatter",
"should execute with error": function(topic) {
var log = console.log;
// Assign console.log to noop to skip CLI output
console.log = function() {};
var exit = cli.execute(["-f", topic, "tests/fixtures/passing.js"]);
assert.equal(exit, 1);
console.log = log;
}
},
"when given a valid formatter path": {
topic: "tests/fixtures/formatters/simple.js",
"should execute without any errors": function(topic) {
var log = console.log;
// Assign console.log to noop to skip CLI output
console.log = function() {};
var exit = cli.execute(["-f", topic, "tests/fixtures/passing.js"]);
assert.equal(exit, 0);
console.log = log;
}
},
"when given an invalid formatter path": {
topic: "tests/fixtures/formatters/file-does-not-exist.js",
"should execute with error": function(topic) {
var log = console.log;
// Assign console.log to noop to skip CLI output
console.log = function() {};
var exit = cli.execute(["-f", topic, "tests/fixtures/passing.js"]);
assert.equal(exit, 1);
console.log = log;
}
},
"when executing a file with an error": {
topic: "tests/fixtures/configurations/semi-error.js",
"should execute with error": function(topic) {
var log = console.log;
// Assign console.log to noop to skip CLI output
console.log = function() {};
var exit = cli.execute([topic]);
assert.equal(exit, 1);
console.log = log;
}
},
"when calling execute more than once": {

@@ -49,3 +235,3 @@

var results = '',
_log = console.log;
log = console.log;

@@ -66,3 +252,3 @@ // Collect the CLI output.

console.log = _log;
console.log = log;
}

@@ -69,0 +255,0 @@

@@ -22,2 +22,18 @@ /**

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
function getVariable(scope, name) {
var variable = null;
scope.variables.some(function(v) {
if (v.name === name) {
variable = v;
return true;
}
return false;
});
return variable;
}
//------------------------------------------------------------------------------
// Tests

@@ -28,2 +44,23 @@ //------------------------------------------------------------------------------

"when using events": {
topic: TEST_CODE,
"an error should be thrown when an error occurs inside of an event handler": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function() {
throw new Error("Intentional error.");
});
assert.throws(function() {
eslint.verify(topic, config, true);
}, Error);
}
},
"when calling toSource()": {

@@ -195,2 +232,61 @@

"when retrieving comments": {
topic: [
"// my line comment",
"var a = 42;",
"/* my block comment */"
].join("\n"),
"should retrieve all comments": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function(/*node*/) {
var comments = eslint.getAllComments();
assert.equal(comments.length, 2);
});
eslint.verify(topic, config, true);
},
"should attach them to all nodes": function(topic) {
function assertCommentCount(leading, trailing) {
return function (node) {
var comments = eslint.getComments(node);
assert.equal(comments.leading.length, leading);
assert.equal(comments.trailing.length, trailing);
};
}
var config = { rules: {} };
eslint.reset();
eslint.on("Program", assertCommentCount(1, 0));
eslint.on("VariableDeclaration", assertCommentCount(0, 1));
eslint.on("VariableDeclarator", assertCommentCount(0, 0));
eslint.on("Identifier", assertCommentCount(0, 0));
eslint.on("Literal", assertCommentCount(0, 0));
eslint.verify(topic, config, true);
},
"should attach them lazily": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("VariableDeclaration", function (node) {
assert.equal(node.hasOwnProperty("leadingComments"), false);
assert.equal(node.hasOwnProperty("trailingComments"), false);
eslint.getComments(node);
assert.equal(node.hasOwnProperty("leadingComments"), false);
assert.equal(node.hasOwnProperty("trailingComments"), true);
});
eslint.verify(topic, config, true);
}
},
"when calling getAncestors": {

@@ -228,3 +324,45 @@

"when calling getScope": {
topic: "function foo() { q: for(;;) { break q; } } function bar () { var q = t; }",
"should retrieve the global scope correctly from a Program": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function(node) {
var scope = eslint.getScope();
assert.equal(scope.type, "global");
});
eslint.verify(topic, config, true);
},
"should retrieve the function scope correctly from a FunctionDeclaration": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("FunctionDeclaration", function(node) {
var scope = eslint.getScope();
assert.equal(scope.type, "function");
});
eslint.verify(topic, config, true);
},
"should retrieve the function scope correctly from a LabeledStatement": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("LabeledStatement", function(node) {
var scope = eslint.getScope();
assert.equal(scope.type, "function");
assert.equal(scope.block.id.name, "foo");
});
eslint.verify(topic, config, true);
}
},
"when evaluating code": {

@@ -353,4 +491,205 @@

},
"when evaluating code containing /*global */ and /*globals */ blocks": {
topic: "/*global a b:true c:false*/ function foo() {} /*globals d:true*/",
"variables should be available in global scope": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function(node) {
var scope = eslint.getScope();
var a = getVariable(scope, "a"),
b = getVariable(scope, "b"),
c = getVariable(scope, "c"),
d = getVariable(scope, "d");
assert.equal(a.name, "a");
assert.equal(a.writeable, false);
assert.equal(b.name, "b");
assert.equal(b.writeable, true);
assert.equal(c.name, "c");
assert.equal(c.writeable, false);
assert.equal(d.name, "d");
assert.equal(d.writeable, true);
});
eslint.verify(topic, config, true);
}
},
"when evaluating code containing a /*global */ block with sloppy whitespace": {
topic: "/* global a b : true c: false*/",
"variables should be available in global scope": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function(node) {
var scope = eslint.getScope(),
a = getVariable(scope, "a"),
b = getVariable(scope, "b"),
c = getVariable(scope, "c");
assert.equal(a.name, "a");
assert.equal(a.writeable, false);
assert.equal(b.name, "b");
assert.equal(b.writeable, true);
assert.equal(c.name, "c");
assert.equal(c.writeable, false);
});
eslint.verify(topic, config, true);
}
},
"when evaluating code containing /*jshint */ block": {
topic: "/*jslint node:true*/ function f() {} /*jshint browser:true foo:bar*/",
"variables should be available in global scope": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function(node) {
var scope = eslint.getScope(),
exports = getVariable(scope, "exports"),
window = getVariable(scope, "window");
assert.equal(exports.writeable, true);
assert.equal(window.writeable, false);
});
eslint.verify(topic, config, true);
}
},
"when evaluating code containing a /*jshint */ block with sloppy whitespace": {
topic: "/* jshint node : true browser : false*/",
"variables should be available in global scope": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function(node) {
var scope = eslint.getScope(),
exports = getVariable(scope, "exports"),
window = getVariable(scope, "window");
assert.equal(exports.writeable, true);
assert.equal(window, null);
});
eslint.verify(topic, config, true);
}
},
"when evaluating code containing a line comment": {
topic: "//global a \n function f() {}",
"should not introduce a global variable": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function(node) {
var scope = eslint.getScope();
assert.equal(getVariable(scope, "a"), null);
});
eslint.verify(topic, config, true);
}
},
"when evaluating code containing normal block comments": {
topic: "/**/ /*a*/ /*b:true*/ /*foo c:false*/",
"should not introduce a global variable": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function(node) {
var scope = eslint.getScope();
assert.equal(getVariable(scope, "a"), null);
assert.equal(getVariable(scope, "b"), null);
assert.equal(getVariable(scope, "foo"), null);
assert.equal(getVariable(scope, "c"), null);
});
eslint.verify(topic, config, true);
}
},
"when evaluating any code": {
topic: "",
"builtin global variables should be available in the global scope": function(topic) {
var config = { rules: {} };
eslint.reset();
eslint.on("Program", function(node) {
var scope = eslint.getScope();
assert.notEqual(getVariable(scope, "Object"), null);
assert.notEqual(getVariable(scope, "Array"), null);
assert.notEqual(getVariable(scope, "undefined"), null);
});
eslint.verify(topic, config, true);
}
},
"at any time": {
topic: "new-rule",
"can add a rule dynamically": function(topic) {
eslint.reset();
eslint.defineRule(topic, function(context) {
return {"Literal": function(node) { context.report(node, "message"); }};
});
var config = { rules: {} };
config.rules[topic] = 1;
var messages = eslint.verify("0", config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, topic);
assert.equal(messages[0].node.type, "Literal");
}
},
"at any time": {
topic: ["new-rule-0", "new-rule-1"],
"can add multiple rules dynamically": function(topics) {
eslint.reset();
var config = { rules: {} };
var newRules = {};
topics.forEach(function(topic){
config.rules[topic] = 1;
newRules[topic] = function(context) {
return {"Literal": function(node) { context.report(node, "message"); }};
};
});
eslint.defineRules(newRules);
var messages = eslint.verify("0", config);
assert.equal(messages.length, topics.length);
topics.forEach(function(topic){
assert.ok(messages.some(function(message){ return message.ruleId === topic; }));
});
messages.forEach(function(message){ assert.equal(message.node.type, "Literal"); });
}
}
}).export(module);

@@ -38,3 +38,3 @@ /**

var result = formatter(topic, config);
assert.equal("foo.js: line 5, col 10, Error - Unexpected foo.\n\n1 problems", result);
assert.equal("foo.js: line 5, col 10, Error - Unexpected foo.\n\n1 problem", result);
},

@@ -48,5 +48,14 @@

var result = formatter(topic, config);
assert.equal("foo.js: line 5, col 10, Warning - Unexpected foo.\n\n1 problems", result);
}
assert.equal("foo.js: line 5, col 10, Warning - Unexpected foo.\n\n1 problem", result);
},
"should return a string in the format filename: line x, col y, Error - z for errors with options config": function(topic) {
var config = {
rules: { foo: [2, "option"] }
};
var result = formatter(topic, config);
assert.equal("foo.js: line 5, col 10, Error - Unexpected foo.\n\n1 problem", result);
},
},

@@ -71,3 +80,3 @@

var result = formatter(topic, config);
assert.equal("foo.js: line 5, col 10, Error - Unexpected foo.\n\n1 problems", result);
assert.equal("foo.js: line 5, col 10, Error - Unexpected foo.\n\n1 problem", result);
}

@@ -130,4 +139,25 @@ },

}
},
"when passed one file not found message": {
topic: [{
filePath: "foo.js",
messages: [{
fatal: true,
message: "Couldn't find foo.js."
}]
}],
"should return a string without line and column": function(topic) {
var config = {
rules: { foo: 2, bar: 1 }
};
var result = formatter(topic, config);
assert.equal("foo.js: line 0, col 0, Error - Couldn't find foo.js.\n\n1 problem", result);
}
}
}).export(module);
}).export(module);

@@ -126,7 +126,25 @@ /**

}
},
"when asking for help": {
topic: "",
"should log the help content to the console": function(topic) {
var log = console.log;
var loggedMessages = [];
console.log = function(message) {
loggedMessages.push(message);
};
options.help()
assert.equal(loggedMessages.length, 1);
console.log = log;
}
}
}).export(module);

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

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Non-camelcased identifier 'first_name' found.");
assert.equal(messages[0].message, "Identifier 'first_name' is not in camel case.");
assert.include(messages[0].node.type, "Identifier");

@@ -119,3 +119,3 @@ assert.include(messages[0].node.name, "first_name");

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Non-camelcased identifier '__private_first_name' found.");
assert.equal(messages[0].message, "Identifier '__private_first_name' is not in camel case.");
assert.include(messages[0].node.type, "Identifier");

@@ -122,0 +122,0 @@ assert.include(messages[0].node.name, "__private_first_name");

@@ -120,2 +120,33 @@ /**

"when evaluating 'do bar(); while (foo)'": {
topic: "do bar(); while (foo)",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Expected { after 'do'.");
assert.include(messages[0].node.type, "DoWhileStatement");
}
},
"when evaluating 'do { bar(); } while (foo)'": {
topic: "do { bar(); } while (foo)",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
},
"when evaluating 'for (;foo;) bar()'": {

@@ -122,0 +153,0 @@

@@ -38,3 +38,3 @@ /**

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of ==, use === instead.");
assert.equal(messages[0].message, "Expected '===' and instead saw '=='.");
assert.include(messages[0].node.type, "BinaryExpression");

@@ -56,3 +56,3 @@ }

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of !=, use !== instead.");
assert.equal(messages[0].message, "Expected '!==' and instead saw '!='.");
assert.include(messages[0].node.type, "BinaryExpression");

@@ -59,0 +59,0 @@ }

@@ -38,3 +38,3 @@ /**

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of ^ found.");
assert.equal(messages[0].message, "Unexpected use of '^'.");
assert.include(messages[0].node.type, "BinaryExpression");

@@ -57,3 +57,3 @@ assert.include(messages[0].node.operator, "^");

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of | found.");
assert.equal(messages[0].message, "Unexpected use of '|'.");
assert.include(messages[0].node.type, "BinaryExpression");

@@ -76,3 +76,3 @@ assert.include(messages[0].node.operator, "|");

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of & found.");
assert.equal(messages[0].message, "Unexpected use of '&'.");
assert.include(messages[0].node.type, "BinaryExpression");

@@ -83,2 +83,56 @@ assert.include(messages[0].node.operator, "&");

"when evaluating '<<": {
topic: "a << b",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of '<<'.");
assert.include(messages[0].node.type, "BinaryExpression");
assert.include(messages[0].node.operator, "<<");
}
},
"when evaluating '>>": {
topic: "a >> b",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of '>>'.");
assert.include(messages[0].node.type, "BinaryExpression");
assert.include(messages[0].node.operator, ">>");
}
},
"when evaluating '>>>": {
topic: "a >>> b",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of '>>>'.");
assert.include(messages[0].node.type, "BinaryExpression");
assert.include(messages[0].node.operator, ">>>");
}
},
"when evaluating '+": {

@@ -96,6 +150,38 @@

}
}
},
"when evaluating '~": {
topic: "~a",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of '~'.");
assert.include(messages[0].node.type, "UnaryExpression");
assert.include(messages[0].node.operator, "~");
}
},
"when evaluating '!": {
topic: "!a",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
},
}).export(module);

@@ -90,4 +90,34 @@ /**

}
},
"when evaluating 'var x = arguments[0]'": {
topic: "var x = arguments[0]",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
},
"when evaluating 'var x = arguments[caller]'": {
topic: "var x = arguments[caller]",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
}
}).export(module);

@@ -201,19 +201,2 @@ /**

"when evaluating ';'": {
topic: ";",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Empty statement.");
assert.include(messages[0].node.type, "EmptyStatement");
}
},
"when evaluating '(function() { }())'": {

@@ -220,0 +203,0 @@

@@ -38,3 +38,3 @@ /**

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Unexpected use of 'eval()'.");
assert.equal(messages[0].message, "eval can be harmful.");
assert.include(messages[0].node.type, "CallExpression");

@@ -41,0 +41,0 @@ assert.include(messages[0].node.callee.name, "eval");

@@ -37,3 +37,3 @@ /**

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "The Function constructor is eval");
assert.equal(messages[0].message, "The Function constructor is eval.");
assert.include(messages[0].node.type, "NewExpression");

@@ -40,0 +40,0 @@ }

@@ -40,3 +40,3 @@ /**

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Do not use String as a constructor");
assert.equal(messages[0].message, "Do not use String as a constructor.");
assert.include(messages[0].node.type, "NewExpression");

@@ -59,3 +59,3 @@ }

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Do not use Number as a constructor");
assert.equal(messages[0].message, "Do not use Number as a constructor.");
assert.include(messages[0].node.type, "NewExpression");

@@ -78,3 +78,3 @@ }

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Do not use Boolean as a constructor");
assert.equal(messages[0].message, "Do not use Boolean as a constructor.");
assert.include(messages[0].node.type, "NewExpression");

@@ -97,3 +97,3 @@ }

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Do not use Math as a constructor");
assert.equal(messages[0].message, "Do not use Math as a constructor.");
assert.include(messages[0].node.type, "NewExpression");

@@ -116,3 +116,3 @@ }

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Do not use JSON as a constructor");
assert.equal(messages[0].message, "Do not use JSON as a constructor.");
assert.include(messages[0].node.type, "NewExpression");

@@ -119,0 +119,0 @@ }

@@ -38,3 +38,3 @@ /**

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Do not use 'new' for side effects");
assert.equal(messages[0].message, "Do not use 'new' for side effects.");
assert.include(messages[0].node.type, "ExpressionStatement");

@@ -41,0 +41,0 @@ }

@@ -54,5 +54,5 @@ /**

"when evaluating 'var a = 0x1234'": {
"when evaluating '0x1234'": {
topic: "var a = 0x1234;",
topic: "0x1234",

@@ -70,2 +70,17 @@ "should not report a violation": function(topic) {

"when evaluating '0X5'": {
topic: "0X5;",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
},
"when evaluating 'a = 1 + 01234'": {

@@ -103,2 +118,50 @@

},
"when evaluating the literal 00": {
topic: "00",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Octal literals should not be used.");
assert.include(messages[0].node.type, "Literal");
}
},
"when evaluating numbers between 0 and 1": {
topic: "0.1",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
},
"when evaluating 0-prefixed numbers in scientific notation": {
topic: "0.5e1",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
}
}).export(module);

@@ -51,3 +51,3 @@ /**

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Variable 'a' initialized to undefined.");
assert.equal(messages[0].message, "It's not necessary to initialize 'a' to undefined.");
assert.include(messages[0].node.type, "VariableDeclarator");

@@ -54,0 +54,0 @@ }

@@ -54,3 +54,3 @@ /**

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Use single quotes for string literals.");
assert.equal(messages[0].message, "Strings must use singlequote.");
}

@@ -72,3 +72,3 @@ },

assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Use double quotes for string literals.");
assert.equal(messages[0].message, "Strings must use doublequote.");
}

@@ -75,0 +75,0 @@ },

@@ -156,5 +156,124 @@ /**

}
},
"when evaluation 'setTimeout(function() {foo = \"bar\"; });'": {
topic: "setTimeout(function() {foo = \"bar\"; });",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
},
"when evaluation 'setTimeout(function() {foo = \"bar\";});'": {
topic: "setTimeout(function() {foo = \"bar\";});",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
},
"when evaluating 'for (var a in b){}": {
topic: "for (var a in b){}",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
},
"when evaluating 'for (var a in b) var i": {
topic: "for (var a in b) var i ",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Missing semicolon.");
assert.include(messages[0].node.type, "VariableDeclaration");
}
},
"when evaluating 'for (var i;;){}": {
topic: "for (var i;;){}",
"should not report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 0);
}
},
"when evaluating 'for (;;){var i}": {
topic: "for (;;){var i}",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Missing semicolon.");
assert.include(messages[0].node.type, "VariableDeclaration");
}
},
"when evaluating 'for (;;) var i": {
topic: "for (;;) var i ",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Missing semicolon.");
assert.include(messages[0].node.type, "VariableDeclaration");
}
},
"when evaluating 'for (var j;;) {var i}": {
topic: "for (var j;;) {var i}",
"should report a violation": function(topic) {
var config = { rules: {} };
config.rules[RULE_ID] = 1;
var messages = eslint.verify(topic, config);
assert.equal(messages.length, 1);
assert.equal(messages[0].ruleId, RULE_ID);
assert.equal(messages[0].message, "Missing semicolon.");
assert.include(messages[0].node.type, "VariableDeclaration");
}
}
}).export(module);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc