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

eslint

Package Overview
Dependencies
Maintainers
2
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.24.1 to 1.0.0-rc-1

conf/replacements.json

13

conf/environments.js

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

globalReturn: true
},
rules: {
"no-catch-shadow": 0,
"no-console": 0,
"no-mixed-requires": 2,
"no-new-require": 2,
"no-path-concat": 2,
"no-process-exit": 2,
"global-strict": [0, "always"],
"handle-callback-err": [2, "err"]
}

@@ -65,2 +55,5 @@ },

},
serviceworker: {
globals: globals.serviceworker
},
es6: {

@@ -67,0 +60,0 @@ ecmaFeatures: {

{
"ecmaFeatures": {},
"parser": "espree",
"env": {
"browser": false,
"node": false,
"amd": false,
"mocha": false,
"jasmine": false
},
"rules": {
"no-alert": 2,
"no-array-constructor": 2,
"no-alert": 0,
"no-array-constructor": 0,
"no-bitwise": 0,
"no-caller": 2,
"no-catch-shadow": 2,
"no-comma-dangle": 0,
"no-caller": 0,
"no-catch-shadow": 0,
"no-class-assign": 0,
"no-cond-assign": 2,
"no-console": 2,
"no-const-assign": 0,
"no-constant-condition": 2,

@@ -32,18 +24,16 @@ "no-continue": 0,

"no-empty": 2,
"no-empty-class": 0,
"no-empty-character-class": 2,
"no-empty-label": 2,
"no-empty-label": 0,
"no-eq-null": 0,
"no-eval": 2,
"no-eval": 0,
"no-ex-assign": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-extend-native": 0,
"no-extra-bind": 0,
"no-extra-boolean-cast": 2,
"no-extra-parens": 0,
"no-extra-semi": 2,
"no-extra-strict": 2,
"no-fallthrough": 2,
"no-floating-decimal": 0,
"no-func-assign": 2,
"no-implied-eval": 2,
"no-implied-eval": 0,
"no-inline-comments": 0,

@@ -53,25 +43,25 @@ "no-inner-declarations": [2, "functions"],

"no-irregular-whitespace": 2,
"no-iterator": 2,
"no-label-var": 2,
"no-labels": 2,
"no-lone-blocks": 2,
"no-iterator": 0,
"no-label-var": 0,
"no-labels": 0,
"no-lone-blocks": 0,
"no-lonely-if": 0,
"no-loop-func": 2,
"no-loop-func": 0,
"no-mixed-requires": [0, false],
"no-mixed-spaces-and-tabs": [2, false],
"linebreak-style": [0, "unix"],
"no-multi-spaces": 2,
"no-multi-str": 2,
"no-multi-spaces": 0,
"no-multi-str": 0,
"no-multiple-empty-lines": [0, {"max": 2}],
"no-native-reassign": 2,
"no-native-reassign": 0,
"no-negated-in-lhs": 2,
"no-nested-ternary": 0,
"no-new": 2,
"no-new-func": 2,
"no-new-object": 2,
"no-new": 0,
"no-new-func": 0,
"no-new-object": 0,
"no-new-require": 0,
"no-new-wrappers": 2,
"no-new-wrappers": 0,
"no-obj-calls": 2,
"no-octal": 2,
"no-octal-escape": 2,
"no-octal-escape": 0,
"no-param-reassign": 0,

@@ -81,4 +71,4 @@ "no-path-concat": 0,

"no-process-env": 0,
"no-process-exit": 2,
"no-proto": 2,
"no-process-exit": 0,
"no-proto": 0,
"no-redeclare": 2,

@@ -88,61 +78,61 @@ "no-regex-spaces": 2,

"no-restricted-modules": 0,
"no-return-assign": 2,
"no-script-url": 2,
"no-return-assign": 0,
"no-script-url": 0,
"no-self-compare": 0,
"no-sequences": 2,
"no-shadow": 2,
"no-shadow-restricted-names": 2,
"no-space-before-semi": 0,
"no-spaced-func": 2,
"no-sequences": 0,
"no-shadow": 0,
"no-shadow-restricted-names": 0,
"no-spaced-func": 0,
"no-sparse-arrays": 2,
"no-sync": 0,
"no-ternary": 0,
"no-trailing-spaces": 2,
"no-trailing-spaces": 0,
"no-this-before-super": 0,
"no-throw-literal": 0,
"no-undef": 2,
"no-undef-init": 2,
"no-undef-init": 0,
"no-undefined": 0,
"no-unexpected-multiline": 0,
"no-underscore-dangle": 2,
"no-underscore-dangle": 0,
"no-unneeded-ternary": 0,
"no-unreachable": 2,
"no-unused-expressions": 2,
"no-unused-expressions": 0,
"no-unused-vars": [2, {"vars": "all", "args": "after-used"}],
"no-use-before-define": 2,
"no-use-before-define": 0,
"no-useless-call": 0,
"no-void": 0,
"no-var": 0,
"prefer-const": 0,
"no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
"no-with": 2,
"no-wrap-func": 2,
"no-with": 0,
"array-bracket-spacing": [0, "never"],
"arrow-parens": 0,
"arrow-spacing": 0,
"accessor-pairs": 0,
"block-scoped-var": 0,
"brace-style": [0, "1tbs"],
"camelcase": 2,
"callback-return": 0,
"camelcase": 0,
"comma-dangle": [2, "never"],
"comma-spacing": 2,
"comma-spacing": 0,
"comma-style": 0,
"complexity": [0, 11],
"computed-property-spacing": [0, "never"],
"consistent-return": 2,
"consistent-return": 0,
"consistent-this": [0, "that"],
"constructor-super": 0,
"curly": [2, "all"],
"curly": [0, "all"],
"default-case": 0,
"dot-location": 0,
"dot-notation": [2, { "allowKeywords": true }],
"eol-last": 2,
"eqeqeq": 2,
"dot-notation": [0, { "allowKeywords": true }],
"eol-last": 0,
"eqeqeq": 0,
"func-names": 0,
"func-style": [0, "declaration"],
"generator-star": 0,
"generator-star-spacing": 0,
"global-strict": [2, "never"],
"guard-for-in": 0,
"handle-callback-err": 0,
"indent": 0,
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
"init-declarations": 0,
"key-spacing": [0, { "beforeColon": false, "afterColon": true }],
"lines-around-comment": 0,

@@ -154,4 +144,4 @@ "max-depth": [0, 4],

"max-statements": [0, 10],
"new-cap": 2,
"new-parens": 2,
"new-cap": 0,
"new-parens": 0,
"newline-after-var": 0,

@@ -164,21 +154,20 @@ "object-curly-spacing": [0, "never"],

"padded-blocks": 0,
"prefer-const": 0,
"prefer-spread": 0,
"quote-props": 0,
"quotes": [2, "double"],
"quotes": [0, "double"],
"radix": 0,
"semi": 2,
"semi-spacing": [2, {"before": false, "after": true}],
"require-yield": 0,
"semi": 0,
"semi-spacing": [0, {"before": false, "after": true}],
"sort-vars": 0,
"space-after-function-name": [0, "never"],
"space-after-keywords": [0, "always"],
"space-before-blocks": [0, "always"],
"space-before-function-paren": [0, "always"],
"space-before-function-parentheses": [0, "always"],
"space-in-brackets": [0, "never"],
"space-in-parens": [0, "never"],
"space-infix-ops": 2,
"space-return-throw-case": 2,
"space-unary-ops": [2, { "words": true, "nonwords": false }],
"space-infix-ops": 0,
"space-return-throw-case": 0,
"space-unary-ops": [0, { "words": true, "nonwords": false }],
"spaced-comment": 0,
"spaced-line-comment": [0, "always"],
"strict": 2,
"strict": 0,
"use-isnan": 2,

@@ -190,4 +179,4 @@ "valid-jsdoc": 0,

"wrap-regex": 0,
"yoda": [2, "never"]
"yoda": [0, "never"]
}
}

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

linter: require("./eslint"),
cli: require("./cli"),
CLIEngine: require("./cli-engine"),
validator: require("./config-validator")
};

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

* @property {string} configFile The configuration file to use.
* @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|object} baseConfig Base config object. True enables recommend rules and environments.
* @property {boolean} ignore False disables use of .eslintignore.

@@ -74,4 +73,3 @@ * @property {string[]} rulePaths An array of directories to load custom rules from.

configFile: null,
reset: false,
baseConfig: require(path.resolve(__dirname, "..", "conf", "eslint.json")),
baseConfig: false,
rulePaths: [],

@@ -101,3 +99,3 @@ useEslintrc: true,

if (pluginNames) {
pluginNames.forEach(function (pluginName) {
pluginNames.forEach(function(pluginName) {
var pluginNamespace = util.getNamespace(pluginName),

@@ -393,3 +391,3 @@ pluginNameWithoutNamespace = util.removeNameSpace(pluginName),

*/
isPathIgnored: function (filePath) {
isPathIgnored: function(filePath) {
var ignoredPaths;

@@ -396,0 +394,0 @@

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

rulePaths: cliOptions.rulesdir,
reset: cliOptions.reset,
useEslintrc: cliOptions.eslintrc

@@ -121,3 +120,3 @@ };

results.forEach(function (result) {
results.forEach(function(result) {
var filteredMessages = result.messages.filter(isErrorMessage);

@@ -124,0 +123,0 @@

@@ -31,5 +31,5 @@ /**

exec("npm i eslint-plugin-react --save-dev", callback);
} else {
callback();
return;
}
callback();
}

@@ -43,3 +43,3 @@

function processAnswers(answers) {
var config = {rules: {}, env: {}};
var config = {rules: {}, env: {}, extends: "eslint:recommended"};
config.rules.indent = [2, answers.indent];

@@ -59,2 +59,3 @@ config.rules.quotes = [2, answers.quotes];

config.plugins = ["react"];
config.ecmaFeatures.experimentalObjectRestSpread = true;
}

@@ -124,3 +125,3 @@ }

default: false,
when: function (answers) {
when: function(answers) {
return answers.jsx;

@@ -127,0 +128,0 @@ }

@@ -82,3 +82,3 @@ /**

];
validateRule.errors.forEach(function (error) {
validateRule.errors.forEach(function(error) {
message.push(

@@ -101,3 +101,3 @@ "\tValue \"", error.value, "\" ", error.message, ".\n"

if (typeof config.rules === "object") {
Object.keys(config.rules).forEach(function (id) {
Object.keys(config.rules).forEach(function(id) {
validateRuleOptions(id, config.rules[id], source);

@@ -104,0 +104,0 @@ });

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

isAbsolutePath = require("path-is-absolute"),
validator = require("./config-validator");
validator = require("./config-validator"),
pathIsInside = require("path-is-inside");

@@ -112,5 +113,9 @@ //------------------------------------------------------------------------------

// Make the last element in an array take the highest precedence
config = configExtends.reduceRight(function (previousValue, parentPath) {
config = configExtends.reduceRight(function(previousValue, parentPath) {
if (isFilePath(parentPath)) {
if (parentPath === "eslint:recommended") {
// Add an explicit substitution for eslint:recommended to conf/eslint.json
// this lets us use the eslint.json file as the recommended rules
parentPath = path.resolve(__dirname, "../conf/eslint.json");
} else if (isFilePath(parentPath)) {
// If the `extends` path is relative, use the directory of the current configuration

@@ -153,3 +158,3 @@ // file as the reference point. Otherwise, use as-is.

pluginNames.forEach(function (pluginName) {
pluginNames.forEach(function(pluginName) {
var pluginNamespace = util.getNamespace(pluginName),

@@ -216,3 +221,4 @@ pluginNameWithoutNamespace = util.removeNameSpace(pluginName),

localConfigFiles = thisConfig.findLocalConfigFiles(directory),
numFiles = localConfigFiles.length;
numFiles = localConfigFiles.length,
rootPath;

@@ -236,2 +242,12 @@ for (i = 0; i < numFiles; i++) {

// Check for root flag
if (localConfig.root === true) {
rootPath = path.dirname(localConfigFile);
}
// If root flag is set, don't consider file if it is above root
if (rootPath && !pathIsInside(path.dirname(localConfigFile), rootPath)) {
continue;
}
found = true;

@@ -249,4 +265,2 @@ debug("Using " + localConfigFile);

* @param {Object<string,boolean>} envs The environment settings.
* @param {boolean} reset The value of the command line reset option. If true,
* rules are not automatically merged into the config.
* @returns {Object} A configuration object with the appropriate rules and globals

@@ -256,3 +270,3 @@ * set.

*/
function createEnvironmentConfig(envs, reset) {
function createEnvironmentConfig(envs) {

@@ -267,3 +281,3 @@ var envConfig = {

if (envs) {
Object.keys(envs).filter(function (name) {
Object.keys(envs).filter(function(name) {
return envs[name];

@@ -275,6 +289,2 @@ }).forEach(function(name) {

if (!reset && environment.rules) {
assign(envConfig.rules, environment.rules);
}
if (environment.globals) {

@@ -314,16 +324,7 @@ assign(envConfig.globals, environment.globals);

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"));
}
this.baseConfig = options.baseConfig || { rules: {} };
this.useEslintrc = (options.useEslintrc !== false);
this.env = (options.envs || []).reduce(function (envs, name) {
this.env = (options.envs || []).reduce(function(envs, name) {
envs[name] = true;

@@ -333,3 +334,3 @@ return envs;

this.globals = (options.globals || []).reduce(function (globals, def) {
this.globals = (options.globals || []).reduce(function(globals, def) {
// Default "foo" to false and handle "foo:false" and "foo:true"

@@ -356,3 +357,3 @@ var parts = def.split(":");

*/
Config.prototype.getConfig = function (filePath) {
Config.prototype.getConfig = function(filePath) {
var config,

@@ -385,3 +386,3 @@ userConfig,

// Step 3: Merge in environment-specific globals and rules from .eslintrc files
config = util.mergeConfigs(config, createEnvironmentConfig(userConfig.env, this.options.reset));
config = util.mergeConfigs(config, createEnvironmentConfig(userConfig.env));

@@ -396,3 +397,3 @@ // Step 4: Merge in the user-specified configuration from .eslintrc and package.json

if (this.useSpecificConfig.env) {
config = util.mergeConfigs(config, createEnvironmentConfig(this.useSpecificConfig.env, this.options.reset));
config = util.mergeConfigs(config, createEnvironmentConfig(this.useSpecificConfig.env));
}

@@ -405,3 +406,3 @@

debug("Merging command line environment settings");
config = util.mergeConfigs(config, createEnvironmentConfig(this.env, this.options.reset));
config = util.mergeConfigs(config, createEnvironmentConfig(this.env));

@@ -434,3 +435,3 @@ // Step 7: Merge in command line rules

*/
Config.prototype.findLocalConfigFiles = function (directory) {
Config.prototype.findLocalConfigFiles = function(directory) {

@@ -437,0 +438,0 @@ if (!this.localConfigFinder) {

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

escapeRegExp = require("escape-string-regexp"),
validator = require("./config-validator");
validator = require("./config-validator"),
replacements = require("../conf/replacements.json");

@@ -29,2 +30,9 @@ //------------------------------------------------------------------------------

// additional changes to make estraverse happy
estraverse.Syntax.ExperimentalSpreadProperty = "ExperimentalSpreadProperty";
estraverse.Syntax.ExperimentalRestProperty = "ExperimentalRestProperty";
estraverse.VisitorKeys.ExperimentalSpreadProperty = ["argument"];
estraverse.VisitorKeys.ExperimentalRestProperty = ["argument"];
/**

@@ -78,3 +86,3 @@ * Parses a list of "name:boolean_value" or/and "name" options divided by comma or

line: location.start.line,
column: location.start.column
column: location.start.column + 1
});

@@ -136,2 +144,3 @@

var declaredGlobals = {},
exportedGlobals = {},
explicitGlobals = {},

@@ -142,3 +151,3 @@ builtin = environments.builtin;

Object.keys(config.env).forEach(function (name) {
Object.keys(config.env).forEach(function(name) {
if (config.env[name]) {

@@ -152,2 +161,3 @@ var environmentGlobals = environments[name] && environments[name].globals;

assign(exportedGlobals, config.exported);
assign(declaredGlobals, config.globals);

@@ -175,2 +185,10 @@ assign(explicitGlobals, config.astGlobals);

});
// mark all exported variables as such
Object.keys(exportedGlobals).forEach(function(name) {
var variable = getVariable(globalScope, name);
if (variable) {
variable.eslintUsed = true;
}
});
}

@@ -255,2 +273,3 @@

var commentConfig = {
exported: {},
astGlobals: {},

@@ -265,3 +284,3 @@ rules: {},

var value = comment.value.trim();
var match = /^(eslint-\w+|eslint-\w+-\w+|eslint|globals?)(\s|$)/.exec(value);
var match = /^(eslint-\w+|eslint-\w+-\w+|eslint|exported|globals?)(\s|$)/.exec(value);

@@ -273,2 +292,6 @@ if (match) {

switch (match[1]) {
case "exported":
assign(commentConfig.exported, parseBooleanConfig(value));
break;
case "globals":

@@ -313,3 +336,3 @@ case "global":

// apply environment configs
Object.keys(commentConfig.env).forEach(function (name) {
Object.keys(commentConfig.env).forEach(function(name) {
if (environments[name]) {

@@ -400,2 +423,36 @@ commentConfig = util.mergeConfigs(commentConfig, environments[name]);

/**
* Provide a stub rule with a given message
* @param {string} message The message to be displayed for the rule
* @returns {Function} Stub rule function
*/
function createStubRule(message) {
function createRuleModule(context) {
return {
Program: function(node) {
context.report(node, message);
}
};
}
if (message) {
return createRuleModule;
} else {
throw new Error("No message passed to stub rule");
}
}
/**
* Provide a rule replacement message
* @param {string} ruleId Name of the rule
* @returns {string} Message detailing rule replacement
*/
function getRuleReplacementMessage(ruleId) {
if (ruleId in replacements.rules) {
var newRules = replacements.rules[ruleId];
return "Rule \'" + ruleId + "\' was removed and replaced by: " + newRules.join(", ");
}
}
//------------------------------------------------------------------------------

@@ -482,3 +539,3 @@ // Public Interface

line: ex.lineNumber,
column: ex.column
column: ex.column + 1
});

@@ -633,29 +690,38 @@

}).forEach(function(key) {
var ruleCreator = rules.get(key),
severity = getRuleSeverity(config.rules[key]),
options = getRuleOptions(config.rules[key]),
var ruleCreator,
severity,
options,
rule;
if (ruleCreator) {
try {
rule = ruleCreator(new RuleContext(
key, api, severity, options,
config.settings, config.ecmaFeatures
));
// add all the node types as listeners
Object.keys(rule).forEach(function(nodeType) {
api.on(nodeType, timing.enabled
? timing.time(key, rule[nodeType])
: rule[nodeType]
);
});
} catch(ex) {
ex.message = "Error while loading rule '" + key + "': " + ex.message;
throw ex;
if (rules.get(key)) {
ruleCreator = rules.get(key);
} else {
var replacementMsg = getRuleReplacementMessage(key);
if (replacementMsg) {
ruleCreator = createStubRule(replacementMsg);
} else {
ruleCreator = createStubRule("Definition for rule '" + key + "' was not found");
}
rules.define(key, ruleCreator);
}
} else {
throw new Error("Definition for rule '" + key + "' was not found.");
severity = getRuleSeverity(config.rules[key]);
options = getRuleOptions(config.rules[key]);
try {
rule = ruleCreator(new RuleContext(
key, api, severity, options,
config.settings, config.ecmaFeatures
));
// add all the node types as listeners
Object.keys(rule).forEach(function(nodeType) {
api.on(nodeType, timing.enabled
? timing.time(key, rule[nodeType])
: rule[nodeType]
);
});
} catch(ex) {
ex.message = "Error while loading rule '" + key + "': " + ex.message;
throw ex;
}

@@ -689,3 +755,3 @@ });

scopeMap = [];
currentScopes.forEach(function (scope, index) {
currentScopes.forEach(function(scope, index) {
var range = scope.block.range[0];

@@ -789,3 +855,3 @@

Object.keys(opts || {}).forEach(function (key) {
Object.keys(opts || {}).forEach(function(key) {
var rx = new RegExp(escapeRegExp("{{" + key + "}}"), "g");

@@ -804,3 +870,3 @@ message = message.replace(rx, opts[key]);

line: location.line,
column: location.column,
column: location.column + 1, // switch to 1-base instead of 0-base
nodeType: node.type,

@@ -960,5 +1026,5 @@ source: currentTextLines[location.line - 1] || ""

estraverse.traverse(controller.root, {
enter: function (node) {
enter: function(node, parent) {
if (node.range[0] <= index && index < node.range[1]) {
result = node;
result = assign({ parent: parent }, node);
} else {

@@ -968,3 +1034,3 @@ this.skip();

},
leave: function (node) {
leave: function(node) {
if (node === result) {

@@ -1089,4 +1155,27 @@ this.break();

/**
* Gets variables that are declared by a specified node.
*
* The variables are its `defs[].node` or `defs[].parent` is same as the specified node.
* Specifically, below:
*
* - `VariableDeclaration` - variables of its all declarators.
* - `VariableDeclarator` - variables.
* - `FunctionDeclaration`/`FunctionExpression` - its function name and parameters.
* - `ArrowFunctionExpression` - its parameters.
* - `ClassDeclaration`/`ClassExpression` - its class name.
* - `CatchClause` - variables of its exception.
* - `ImportDeclaration` - variables of its all specifiers.
* - `ImportSpecifier`/`ImportDefaultSpecifier`/`ImportNamespaceSpecifier` - a variable.
* - others - always an empty array.
*
* @param {ASTNode} node A node to get.
* @returns {escope.Variable[]} Variables that are declared by the node.
*/
api.getDeclaredVariables = function(node) {
return (scopeManager && scopeManager.getDeclaredVariables(node)) || [];
};
return api;
}());

@@ -57,3 +57,3 @@ /**

*/
FileFinder.prototype.findInDirectoryOrParents = function (directory) {
FileFinder.prototype.findInDirectoryOrParents = function(directory) {
var cache = this.cache,

@@ -109,3 +109,3 @@ child,

*/
FileFinder.prototype.findAllInDirectoryAndParents = function (directory) {
FileFinder.prototype.findAllInDirectoryAndParents = function(directory) {
var cache = this.cache,

@@ -112,0 +112,0 @@ child,

@@ -88,3 +88,3 @@ /**

*/
IgnoredPaths.load = function (options) {
IgnoredPaths.load = function(options) {
var patterns;

@@ -112,3 +112,3 @@

*/
IgnoredPaths.prototype.contains = function (filepath) {
IgnoredPaths.prototype.contains = function(filepath) {
if (this.patterns === null) {

@@ -115,0 +115,0 @@ throw new Error("No ignore patterns loaded, call 'load' first");

@@ -50,7 +50,2 @@ /**

}, {
option: "reset",
type: "Boolean",
default: "false",
description: "Set all default rules to off"
}, {
option: "eslintrc",

@@ -57,0 +52,0 @@ type: "Boolean",

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

"getComments",
"getDeclaredVariables",
"getFilename",

@@ -17,0 +18,0 @@ "getFirstToken",

@@ -56,4 +56,4 @@ /**

*/
exports.import = function (pluginRules, pluginName) {
Object.keys(pluginRules).forEach(function (ruleId) {
exports.import = function(pluginRules, pluginName) {
Object.keys(pluginRules).forEach(function(ruleId) {
var qualifiedRuleId = pluginName + "/" + ruleId,

@@ -60,0 +60,0 @@ rule = pluginRules[ruleId];

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

return {
"ObjectExpression": function (node) {
"ObjectExpression": function(node) {
if (checkSetWithoutGet || checkGetWithoutSet) {

@@ -67,1 +67,16 @@ checkLonelySetGet(node);

};
module.exports.schema = [
{
"type": "object",
"properties": {
"getWithoutSet": {
"type": "boolean"
},
"setWithoutGet": {
"type": "boolean"
}
},
"additionalProperties": false
}
];

@@ -275,3 +275,3 @@ /**

"VariableDeclaration": function (node) {
"VariableDeclaration": function(node) {
variableDeclarationHandler(node);

@@ -278,0 +278,0 @@ },

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

module.exports = function (context) {
module.exports = function(context) {
var allowDangle = context.options[0];

@@ -17,0 +17,0 @@ var forbidDangle = allowDangle !== "always-multiline" && allowDangle !== "always";

@@ -57,7 +57,7 @@ /**

scope.variables.some(function (variable) {
scope.variables.some(function(variable) {
var lookup;
if (variable.name === alias) {
if (variable.defs.some(function (def) {
if (variable.defs.some(function(def) {
return def.node.type === "VariableDeclarator" &&

@@ -73,3 +73,3 @@ def.node.init !== null;

// assigned later in the same scope.
if (!lookup.references.some(function (reference) {
if (!lookup.references.some(function(reference) {
var write = reference.writeExpr;

@@ -83,3 +83,3 @@

})) {
variable.defs.map(function (def) {
variable.defs.map(function(def) {
return def.node;

@@ -99,3 +99,3 @@ }).forEach(reportBadAssignment);

"VariableDeclarator": function (node) {
"VariableDeclarator": function(node) {
var id = node.id;

@@ -110,3 +110,3 @@ var isDestructuring =

"AssignmentExpression": function (node) {
"AssignmentExpression": function(node) {
if (node.left.type === "Identifier") {

@@ -113,0 +113,0 @@ checkAssignment(node, node.left.name, node.right);

@@ -94,3 +94,3 @@ /**

"DoWhileStatement": function (node) {
"DoWhileStatement": function(node) {
checkBody(node, node.body, "do");

@@ -97,0 +97,0 @@ },

@@ -13,3 +13,3 @@ /**

module.exports = function (context) {
module.exports = function(context) {

@@ -65,1 +65,7 @@ var config = context.options[0],

};
module.exports.schema = [
{
"enum": ["object", "property"]
}
];

@@ -47,3 +47,3 @@ /**

function getParameters(scope) {
return scope.variables.filter(function (variable) {
return scope.variables.filter(function(variable) {
return variable.defs[0] && variable.defs[0].type === "Parameter";

@@ -50,0 +50,0 @@ });

/**
* @fileoverview This option sets a specific tab width for your code
* This rule has been ported and modified from JSCS.
* @author Dmitriy Shekhovtsov
* @copyright 2015 Dmitriy Shekhovtsov. All rights reserved.
* @copyright 2013 Dulin Marat and other contributors.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*eslint no-use-before-define:[2, "nofunc"]*/
* This rule has been ported and modified from nodeca.
* @author Vitaly Puzrin
* @author Gyandeep Singh
* @copyright 2015 Vitaly Puzrin. All rights reserved.
* @copyright 2015 Gyandeep Singh. All rights reserved.
Copyright (C) 2014 by Vitaly Puzrin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
"use strict";

@@ -33,20 +34,20 @@

//------------------------------------------------------------------------------
var util = require("util");
module.exports = function (context) {
// indentation defaults: 4 spaces
var indentChar = " ";
module.exports = function(context) {
var MESSAGE = "Expected indentation of {{needed}} characters.";
var extraColumnStart = 0;
var indentType = "spaces";
var indentSize = 4;
var options = {indentSwitchCase: false};
var lines = null;
var indentStack = [0];
var linesToCheck = null;
var breakIndents = null;
if (context.options.length) {
if (context.options[0] === "tab") {
indentChar = "\t";
indentSize = 1;
indentType = "tab";
} else /* istanbul ignore else : this will be caught by options validation */ if (typeof context.options[0] === "number") {
indentSize = context.options[0];
indentType = "spaces";
}

@@ -60,404 +61,347 @@

var blockParents = [
"IfStatement",
"WhileStatement",
"DoWhileStatement",
"ForStatement",
"ForInStatement",
"ForOfStatement",
"FunctionDeclaration",
"FunctionExpression",
"ArrowExpression",
"CatchClause",
"WithStatement"
];
var caseIndentStore = {};
var indentableNodes = {
BlockStatement: "body",
Program: "body",
ObjectExpression: "properties",
ArrayExpression: "elements",
SwitchStatement: "cases"
};
/**
* Get node indent
* @param {ASTNode} node Node to examine
* @param {boolean} byLastLine get indent of node's last line
* @param {boolean} excludeCommas skip comma on start of line
* @returns {int} Indent
*/
function getNodeIndent(node, byLastLine, excludeCommas) {
byLastLine = byLastLine || false;
excludeCommas = excludeCommas || false;
if (options.indentSwitchCase) {
indentableNodes.SwitchCase = "consequent";
}
var src = context.getSource(node, node.loc.start.column + extraColumnStart);
var lines = src.split("\n");
if (byLastLine) {
src = lines[lines.length - 1];
} else {
src = lines[0];
}
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
var skip = excludeCommas ? "," : "";
/**
* Mark line to be checked
* @param {Number} line - line number
* @returns {void}
*/
function markCheckLine(line) {
linesToCheck[line].check = true;
}
var regExp;
if (indentType === "spaces") {
regExp = new RegExp("^[ " + skip + "]+");
} else {
regExp = new RegExp("^[\t" + skip + "]+");
}
/**
* Mark line with targeted node to be checked
* @param {ASTNode} checkNode - targeted node
* @returns {void}
*/
function markCheck(checkNode) {
markCheckLine(checkNode.loc.start.line - 1);
var indent = regExp.exec(src);
return indent ? indent[0].length : 0;
}
/**
* Sets pushing indent of current node
* @param {ASTNode} node - targeted node
* @param {Number} indents - indents count to push
* Check indent for nodes list
* @param {ASTNode[]} nodes list of node objects
* @param {int} indent needed indent
* @param {boolean} excludeCommas skip comma on start of line
* @returns {void}
*/
function markPush(node, indents) {
linesToCheck[node.loc.start.line - 1].push.push(indents);
function checkNodesIndent(nodes, indent, excludeCommas) {
nodes.forEach(function(node) {
var nodeIndent = getNodeIndent(node, false, excludeCommas);
if (nodeIndent !== indent) {
context.report(node, MESSAGE, { gotten: nodeIndent, needed: indent });
}
});
}
/**
* Marks line as outdent, end of block statement for example
* @param {ASTNode} node - targeted node
* @param {Number} outdents - count of outedents in targeted line
* Check last node line indent this detects, that block closed correctly
* @param {ASTNode} node Node to examine
* @param {int} lastLineIndent needed indent
* @returns {void}
*/
function markPop(node, outdents) {
linesToCheck[node.loc.end.line - 1].pop.push(outdents);
function checkLastNodeLineIndent(node, lastLineIndent) {
var endIndent = getNodeIndent(node, true);
if (endIndent !== lastLineIndent) {
context.report(
node,
{ line: node.loc.end.line, column: node.loc.end.column },
MESSAGE,
{ gotten: endIndent, needed: lastLineIndent }
);
}
}
/**
* Set alt push for current node
* @param {ASTNode} node - targeted node
* Check indent for function block content
* @param {ASTNode} node node to examine
* @returns {void}
*/
function markPushAlt(node) {
linesToCheck[node.loc.start.line - 1].pushAltLine.push(node.loc.end.line - 1);
}
function checkIndentInFunctionBlock(node) {
/**
* Marks end of node block to be checked
* and marks targeted node as indent pushing
* @param {ASTNode} pushNode - targeted node
* @param {Number} indents - indent count to push
* @returns {void}
*/
function markPushAndEndCheck(pushNode, indents) {
markPush(pushNode, indents);
markCheckLine(pushNode.loc.end.line - 1);
}
// Search first caller in chain.
// Ex.:
//
// Models <- Identifier
// .User
// .find()
// .exec(function() {
// // function body
// });
//
// Looks for 'Models'
var calleeNode = node.parent; // FunctionExpression
while (calleeNode.parent &&
calleeNode.parent.type === "CallExpression") {
calleeNode = calleeNode.parent;
}
/**
* Mark node as switch case statement
* and set push\pop indentation changes
* @param {ASTNode} caseNode - targeted node
* @param {ASTNode[]} children - consequent child nodes of case node
* @returns {void}
*/
function markCase(caseNode, children) {
var outdentNode = getCaseOutdent(children);
var indent;
if (outdentNode) {
// If a case statement has a `break` as a direct child and it is the
// first one encountered, use it as the example for all future case indentation
if (breakIndents === null) {
breakIndents = (caseNode.loc.start.column === outdentNode.loc.start.column) ? 1 : 0;
}
markPop(outdentNode, breakIndents);
if (calleeNode.parent &&
(calleeNode.parent.type === "Property" ||
calleeNode.parent.type === "ArrayExpression")) {
// If function is part of array or object, comma can be put at left
indent = getNodeIndent(calleeNode, false, true);
} else {
markPop(caseNode, 0);
// If function is standalone, simple calculate indent
indent = getNodeIndent(calleeNode);
}
indent += indentSize;
// If function content is not empty
if (node.body.length > 0) {
// Calculate left shift position don't require strict indent
// allow function body allign to (indentSize * X)
while (getNodeIndent(node.body[0]) > indent) {
indent += indentSize;
}
}
checkNodesIndent(node.body, indent);
checkLastNodeLineIndent(node, indent - indentSize);
}
/**
* Mark child nodes to be checked later of targeted node,
* only if child node not in same line as targeted one
* (if child and parent nodes wrote in single line)
* @param {ASTNode} node - targeted node
* @returns {void}
* Checks if the given node starts and ends on the same line
* @param {ASTNode} node The node to check
* @returns {boolean} Whether or not the block starts and ends on the same line.
*/
function markChildren(node) {
getChildren(node).forEach(function(childNode) {
if (childNode.loc.start.line !== node.loc.start.line || node.type === "Program") {
markCheck(childNode);
}
});
function isSingleLineNode(node) {
var lastToken = context.getLastToken(node),
startLine = node.loc.start.line,
endLine = lastToken.loc.end.line;
return startLine === endLine;
}
/**
* Mark child block as scope pushing and mark to check
* @param {ASTNode} node - target node
* @param {String} property - target node property containing child
* Check indent for array block content or object block content
* @param {ASTNode} node node to examine
* @returns {void}
*/
function markAlternateBlockStatement(node, property) {
var child = node[property];
if (child && child.type === "BlockStatement") {
markCheck(child);
function checkIndentInArrayOrObjectBlock(node) {
// Skip inline
if (isSingleLineNode(node)) {
return;
}
}
/**
* Checks whether node is multiline or single line
* @param {ASTNode} node - target node
* @returns {boolean} - is multiline node
*/
function isMultiline(node) {
return node.loc.start.line !== node.loc.end.line;
}
var elements = (node.type === "ArrayExpression") ? node.elements : node.properties;
/**
* Get switch case statement outdent node if any
* @param {ASTNode[]} caseChildren - case statement childs
* @returns {ASTNode} - outdent node
*/
function getCaseOutdent(caseChildren) {
var outdentNode;
caseChildren.some(function(node) {
if (node.type === "BreakStatement") {
outdentNode = node;
return true;
// Skip if first element is in same line with this node
if (elements.length > 0 && elements[0].loc.start.line === node.loc.start.line) {
return;
}
var nodeIndent = getNodeIndent(node);
var elementsIndent = nodeIndent + indentSize;
// Elements can have double indent (detected by first item)
if (elements.length > 0 &&
getNodeIndent(elements[0]) === elementsIndent + indentSize) {
elementsIndent = elementsIndent + indentSize;
}
// Comma can be placed before property name
checkNodesIndent(elements, elementsIndent, true);
if (elements.length > 0) {
// Skip last block line check if last item in same line
if (elements[elements.length - 1].loc.end.line === node.loc.end.line) {
return;
}
});
}
return outdentNode;
checkLastNodeLineIndent(node, elementsIndent - indentSize);
}
/**
* Returns block containing node
* @param {ASTNode} node - targeted node
* @returns {ASTNode} - block node
* Check indentation for blocks
* @param {ASTNode} node node to check
* @returns {void}
*/
function getBlockNodeToMark(node) {
var parent = node.parent;
function blockIndentationCheck(node) {
// Skip inline blocks
if (isSingleLineNode(node)) {
return;
}
// The parent of an else is the entire if/else block. To avoid over indenting
// in the case of a non-block if with a block else, mark push where the else starts,
// not where the if starts!
if (parent.type === "IfStatement" && parent.alternate === node) {
return node;
if (node.parent && (node.parent.type === "FunctionExpression")) {
checkIndentInFunctionBlock(node);
return;
}
// The end line to check of a do while statement needs to be the location of the
// closing curly brace, not the while statement, to avoid marking the last line of
// a multiline while as a line to check.
if (parent.type === "DoWhileStatement") {
return node;
var indent;
var nodesToCheck = [];
// For this statements we should check indent from statement begin
// (not from block begin)
var statementsWithProperties = [
"IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement"
];
if (node.parent && statementsWithProperties.indexOf(node.parent.type) !== -1) {
indent = getNodeIndent(node.parent);
} else {
indent = getNodeIndent(node);
}
// Detect bare blocks: a block whose parent doesn"t expect blocks in its syntax specifically.
if (blockParents.indexOf(parent.type) === -1) {
return node;
if (node.type === "IfStatement" && node.consequent.type !== "BlockStatement") {
nodesToCheck = [node.consequent];
} else if (util.isArray(node.body)) {
nodesToCheck = node.body;
} else {
nodesToCheck = [node.body];
}
return parent;
}
if (nodesToCheck.length > 0) {
checkNodesIndent(nodesToCheck, indent + indentSize);
}
/**
* Get node's children
* @param {ASTNode} node - current node
* @returns {ASTNode[]} - children
*/
function getChildren(node) {
var childrenProperty = indentableNodes[node.type];
return node[childrenProperty];
}
/**
* Gets indentation in line `i`
* @param {Number} i - number of line to get indentation
* @returns {Number} - count of indentation symbols
*/
function getIndentationFromLine(i) {
var rNotIndentChar = new RegExp("[^" + indentChar + "]");
var firstContent = lines[i].search(rNotIndentChar);
if (firstContent === -1) {
firstContent = lines[i].length;
if (node.type === "BlockStatement") {
checkLastNodeLineIndent(node, indent);
}
return firstContent;
}
/**
* Compares expected and actual indentation
* and reports any violations
* @param {ASTNode} node - node used only for reporting
* Check indentation for variable decalartions
* @param {ASTNode} node node to examine
* @returns {void}
*/
function checkIndentations(node) {
linesToCheck.forEach(function(line, i) {
var actualIndentation = getIndentationFromLine(i);
var expectedIndentation = getExpectedIndentation(line, actualIndentation);
function checkIndentInVariableDeclarations(node) {
var elements = node.declarations;
if (line.check) {
// Skip if first element is in same line with this node
if (elements.length > 0 && elements[0].loc.start.line === node.loc.start.line) {
elements = elements.slice(1); // remove the first element
}
var nodeIndent = getNodeIndent(node);
var elementsIndent = nodeIndent + indentSize;
if (actualIndentation !== expectedIndentation) {
context.report(node,
{line: i + 1, column: expectedIndentation},
"Expected indentation of " + expectedIndentation + " characters.");
// correct the indentation so that future lines
// can be validated appropriately
actualIndentation = expectedIndentation;
}
// Comma can be placed before decalartion
checkNodesIndent(elements, elementsIndent, true);
if (elements.length > 0) {
// Skip last block line check if last item in same line
if (elements[elements.length - 1].loc.end.line === node.loc.end.line) {
return;
}
}
if (line.push.length) {
pushExpectedIndentations(line, actualIndentation);
}
});
checkLastNodeLineIndent(node, elementsIndent - indentSize);
}
/**
* Counts expected indentation for given line number
* @param {Number} line - line number
* @param {Number} actual - actual indentation
* @returns {number} - expected indentation
* Check and decide wheteher to check for indentation for blockless nodes
* Scenarios are for or while statements without brances around them
* @param {ASTNode} node node to examine
* @returns {void}
*/
function getExpectedIndentation(line, actual) {
var outdent = indentSize * Math.max.apply(null, line.pop);
function blockLessNodes(node) {
if (node.body.type !== "BlockStatement") {
blockIndentationCheck(node);
}
}
var idx = indentStack.length - 1;
var expected = indentStack[idx];
/**
* Returns the expected indentation for the case statement
* @param {ASTNode} node node to examine
* @param {int} switchIndent indent for switch statement
* @returns {int} indent size
*/
function expectedCaseIndent(node, switchIndent) {
var switchNode = (node.type === "SwitchStatement") ? node : node.parent;
var caseIndent;
if (!Array.isArray(expected)) {
expected = [expected];
}
if (caseIndentStore[switchNode.loc.start.line]) {
return caseIndentStore[switchNode.loc.start.line];
} else {
if (typeof switchIndent === "undefined") {
switchIndent = getNodeIndent(switchNode);
}
expected = expected.map(function(value) {
if (line.pop.length) {
value -= outdent;
caseIndent = switchIndent + indentSize;
if (switchNode.cases.length > 0 && !options.indentSwitchCase) {
caseIndent = switchIndent;
}
return value;
}).reduce(function(previous, current) {
// when the expected is an array, resolve the value
// back into a Number by checking both values are the actual indentation
return actual === current ? current : previous;
});
caseIndentStore[switchNode.loc.start.line] = caseIndent;
return caseIndent;
}
}
indentStack[idx] = expected;
return {
"Program": function(node) {
var nodeIndent = getNodeIndent(node);
line.pop.forEach(function() {
indentStack.pop();
});
// Root nodes should have no indent
checkNodesIndent(node.body, nodeIndent);
},
return expected;
}
"BlockStatement": blockIndentationCheck,
/**
* Store in stack expected indentations
* @param {Number} line - current line
* @param {Number} actualIndentation - actual indentation at current line
* @returns {void}
*/
function pushExpectedIndentations(line, actualIndentation) {
var indents = Math.max.apply(null, line.push);
var expected = actualIndentation + (indentSize * indents);
"WhileStatement": blockLessNodes,
// when a line has alternate indentations, push an array of possible values
// on the stack, to be resolved when checked against an actual indentation
if (line.pushAltLine.length) {
expected = [expected];
line.pushAltLine.forEach(function(altLine) {
expected.push(getIndentationFromLine(altLine) + (indentSize * indents));
});
}
"ForStatement": blockLessNodes,
line.push.forEach(function() {
indentStack.push(expected);
});
}
"ForInStatement": blockLessNodes,
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
"ForOfStatement": blockLessNodes,
return {
"Program": function (node) {
lines = context.getSourceLines();
linesToCheck = lines.map(function () {
return {
push: [],
pushAltLine: [],
pop: [],
check: false
};
});
"DoWhileStatement": blockLessNodes,
if (!isMultiline(node)) {
return;
"IfStatement": function(node) {
if (node.consequent.type !== "BlockStatement" && node.consequent.loc.start.line > node.loc.start.line) {
blockIndentationCheck(node);
}
markChildren(node);
},
"Program:exit": function (node) {
checkIndentations(node);
},
"BlockStatement": function (node) {
if (!isMultiline(node)) {
return;
"VariableDeclaration": function(node) {
if (node.declarations[node.declarations.length - 1].loc.start.line > node.declarations[0].loc.start.line) {
checkIndentInVariableDeclarations(node);
}
markChildren(node);
markPop(node, 1);
markPushAndEndCheck(getBlockNodeToMark(node), 1);
},
"IfStatement": function (node) {
markAlternateBlockStatement(node, "alternate");
"ObjectExpression": function(node) {
checkIndentInArrayOrObjectBlock(node);
},
"TryStatement": function (node) {
markAlternateBlockStatement(node, "handler");
markAlternateBlockStatement(node, "finalizer");
"ArrayExpression": function(node) {
checkIndentInArrayOrObjectBlock(node);
},
"SwitchStatement": function (node) {
if (!isMultiline(node)) {
return;
}
"SwitchStatement": function(node) {
// Switch is not a 'BlockStatement'
var switchIndent = getNodeIndent(node);
var caseIndent = expectedCaseIndent(node, switchIndent);
checkNodesIndent(node.cases, caseIndent);
var indents = 1;
var children = getChildren(node);
if (children.length && node.loc.start.column === children[0].loc.start.column) {
indents = 0;
}
markChildren(node);
markPop(node, indents);
markPushAndEndCheck(node, indents);
checkLastNodeLineIndent(node, switchIndent);
},
"SwitchCase": function (node) {
if (!options.indentSwitchCase) {
"SwitchCase": function(node) {
// Skip inline cases
if (isSingleLineNode(node)) {
return;
}
if (!isMultiline(node)) {
return;
}
var children = getChildren(node);
if (children.length === 1 && children[0].type === "BlockStatement") {
return;
}
markPush(node, 1);
markCheck(node);
markChildren(node);
markCase(node, children);
},
// indentations inside of function expressions can be offset from
// either the start of the function or the end of the function, therefore
// mark all starting lines of functions as potential indentations
"FunctionDeclaration": function (node) {
markPushAlt(node);
},
"FunctionExpression": function (node) {
markPushAlt(node);
var caseIndent = expectedCaseIndent(node);
checkNodesIndent(node.consequent, caseIndent + indentSize);
}

@@ -464,0 +408,0 @@ };

@@ -300,3 +300,3 @@ /**

return {
"Property": function (node) {
"Property": function(node) {
verifySpacing(node);

@@ -303,0 +303,0 @@ }

@@ -15,3 +15,3 @@ /**

module.exports = function (context) {
module.exports = function(context) {
var EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.",

@@ -18,0 +18,0 @@ EXPECTED_CRLF_MSG = "Expected linebreaks to be 'CRLF' but found 'LF'.";

@@ -36,3 +36,3 @@ /**

var lines = [];
comments.forEach(function (token) {
comments.forEach(function(token) {
var start = token.loc.start.line;

@@ -39,0 +39,0 @@ var end = token.loc.end.line;

@@ -24,3 +24,3 @@ /**

// Cache line numbers of comments for faster lookup
var comments = context.getAllComments().map(function (token) {
var comments = context.getAllComments().map(function(token) {
return token.loc.start.line;

@@ -27,0 +27,0 @@ });

@@ -55,3 +55,3 @@ /**

function findReference(scope, node) {
var references = scope.references.filter(function (reference) {
var references = scope.references.filter(function(reference) {
return reference.identifier.range[0] === node.range[0] &&

@@ -73,3 +73,3 @@ reference.identifier.range[1] === node.range[1];

function isGloballyShadowed(globalScope, identifierName) {
return globalScope.variables.some(function (variable) {
return globalScope.variables.some(function(variable) {
return variable.name === identifierName && variable.defs.length > 0;

@@ -125,3 +125,3 @@ });

"Program": function () {
"Program": function() {
globalScope = context.getScope();

@@ -128,0 +128,0 @@ },

@@ -41,7 +41,7 @@ /**

"SwitchStatement": function(/*node*/) {
"SwitchStatement": function(/* node */) {
switchStatement.push({});
},
"SwitchStatement:exit": function(/*node*/) {
"SwitchStatement:exit": function(/* node */) {
switchStatement.pop();

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

@@ -101,3 +101,3 @@ /**

"IfStatement": function (node) {
"IfStatement": function(node) {
// Don't bother finding a ReturnStatement, if there's no `else`

@@ -111,3 +111,3 @@ // or if the alternate is also an if (indicating an else if).

var body = consequent.body;
body.forEach(function (bodyNode) {
body.forEach(function(bodyNode) {
checkForReturnOrIf(bodyNode, alternate);

@@ -114,0 +114,0 @@ });

@@ -44,1 +44,3 @@ /**

};
module.exports.schema = [];

@@ -15,3 +15,3 @@ /**

return {
"UnaryExpression": function (node) {
"UnaryExpression": function(node) {
var ancestors = context.getAncestors(),

@@ -18,0 +18,0 @@ parent = ancestors.pop(),

@@ -8,3 +8,3 @@ /**

var FALLTHROUGH_COMMENT = /falls\sthrough/;
var FALLTHROUGH_COMMENT = /falls?\s?through/i;

@@ -11,0 +11,0 @@ //------------------------------------------------------------------------------

@@ -31,3 +31,3 @@ /**

errors = errors.filter(function (error) {
errors = errors.filter(function(error) {
var errorLoc = error[1];

@@ -67,3 +67,3 @@ if (errorLoc.line >= locStart.line && errorLoc.line <= locEnd.line) {

sourceLines.forEach(function (sourceLine, lineIndex) {
sourceLines.forEach(function(sourceLine, lineIndex) {
var lineNumber = lineIndex + 1,

@@ -113,3 +113,3 @@ location,

return {
"Program": function (node) {
"Program": function(node) {
/**

@@ -128,6 +128,6 @@ * As we can easily fire warnings for all white space issues with all the source its simpler to fire them here

"Literal": removeInvalidNodeErrors,
"Program:exit": function () {
"Program:exit": function() {
// If we have any errors remaining report on them
errors.forEach(function (error) {
errors.forEach(function(error) {
context.report.apply(this, error);

@@ -134,0 +134,0 @@ });

@@ -10,2 +10,78 @@ /**

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Gets the containing loop node of a specified node.
*
* We don't need to check nested functions, so this ignores those.
* `Scope.through` contains references of nested functions.
*
* @param {ASTNode} node - An AST node to get.
* @returns {ASTNode|null} The containing loop node of the specified node, or `null`.
*/
function getContainingLoopNode(node) {
var parent = node.parent;
while (parent != null) {
switch (parent.type) {
case "WhileStatement":
case "DoWhileStatement":
return parent;
case "ForStatement":
// `init` is outside of the loop.
if (parent.init !== node) {
return parent;
}
break;
case "ForInStatement":
case "ForOfStatement":
// `right` is outside of the loop.
if (parent.right !== node) {
return parent;
}
break;
case "ArrowFunctionExpression":
case "FunctionExpression":
case "FunctionDeclaration":
// We don't need to check nested functions.
return null;
default:
break;
}
node = parent;
parent = node.parent;
}
return null;
}
/**
* Checks whether or not a reference refers to a variable that is block-binding in the loop.
* @param {ASTNode} loopNode - A containing loop node.
* @param {escope.Reference} reference - A reference to check.
* @returns {boolean} Whether or not a reference refers to a variable that is block-binding in the loop.
*/
function isBlockBindingsInLoop(loopNode, reference) {
// A reference to a `let`/`const` variable always has a resolved variable.
var variable = reference.resolved;
var definition = variable && variable.defs[0];
var declaration = definition && definition.parent;
return (
// Checks whether this is `let`/`const`.
declaration != null &&
declaration.type === "VariableDeclaration" &&
(declaration.kind === "let" || declaration.kind === "const") &&
// Checks whether this is in the loop.
declaration.range[0] > loopNode.range[0] &&
declaration.range[1] < loopNode.range[1]
);
}
//------------------------------------------------------------------------------
// Rule Definition

@@ -16,3 +92,7 @@ //------------------------------------------------------------------------------

/**
* Reports if the given node has an ancestor node which is a loop.
* Reports such functions:
*
* - has an ancestor node which is a loop.
* - has a reference that refers to a variable that is block-binding in the loop.
*
* @param {ASTNode} node The AST node to check.

@@ -22,29 +102,9 @@ * @returns {boolean} Whether or not the node is within a loop.

function checkForLoops(node) {
var ancestors = context.getAncestors();
/**
* Checks if the given node is a loop and current context is in the loop.
* @param {ASTNode} ancestor The AST node to check.
* @param {number} index The index of ancestor in ancestors.
* @returns {boolean} Whether or not the node is a loop and current context is in the loop.
*/
function isInLoop(ancestor, index) {
switch (ancestor.type) {
case "ForStatement":
return ancestor.init !== ancestors[index + 1];
case "ForInStatement":
case "ForOfStatement":
return ancestor.right !== ancestors[index + 1];
case "WhileStatement":
case "DoWhileStatement":
return true;
default:
return false;
}
var loopNode = getContainingLoopNode(node);
if (loopNode == null) {
return;
}
if (ancestors.some(isInLoop)) {
var references = context.getScope().through;
if (references.length > 0 && !references.every(isBlockBindingsInLoop.bind(null, loopNode))) {
context.report(node, "Don't make functions within a loop");

@@ -51,0 +111,0 @@ }

@@ -110,3 +110,3 @@ /**

declarations.forEach(function (declaration) {
declarations.forEach(function(declaration) {
var type = getDeclarationType(declaration.init);

@@ -131,3 +131,3 @@ contains[type] = true;

declarations.forEach(function (declaration) {
declarations.forEach(function(declaration) {
if (getDeclarationType(declaration.init) === DECL_REQUIRE) {

@@ -134,0 +134,0 @@ found[inferModuleType(declaration.init)] = true;

@@ -23,3 +23,3 @@ /**

if (options && options.exceptions) {
Object.keys(options.exceptions).forEach(function (key) {
Object.keys(options.exceptions).forEach(function(key) {
if (options.exceptions[key]) {

@@ -26,0 +26,0 @@ exceptions[key] = true;

@@ -11,3 +11,3 @@ /**

module.exports = function (context) {
module.exports = function(context) {
// trim restricted module names

@@ -61,3 +61,3 @@ var restrictedModules = context.options;

return {
"CallExpression": function (node) {
"CallExpression": function(node) {
if (isRequireCall(node)) {

@@ -64,0 +64,0 @@ var restrictedModuleName = getRestrictedModuleName(node);

@@ -5,4 +5,4 @@ /**

*/
/*jshint scripturl: true */
/*eslint no-script-url: 0*/
/* jshint scripturl: true */
/* eslint no-script-url: 0 */

@@ -9,0 +9,0 @@ "use strict";

@@ -97,3 +97,3 @@ /**

function isContainedInScopeVars(variable, scopeVars) {
return scopeVars.some(function (scopeVar) {
return scopeVars.some(function(scopeVar) {
return (

@@ -119,3 +119,3 @@ scopeVar.identifiers.length > 0 &&

variables.forEach(function (variable) {
variables.forEach(function(variable) {
// "arguments" is a special case that has no identifiers (#1759)

@@ -159,3 +159,3 @@ if (variable.identifiers.length > 0 && isContainedInScopeVars(variable, scope.variables)) {

return {
"Program:exit": function () {
"Program:exit": function() {
var globalScope = context.getScope(),

@@ -162,0 +162,0 @@ stack = globalScope.childScopes.slice(),

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

/*jshint node:true*/
/* jshint node:true */

@@ -9,0 +9,0 @@ "use strict";

@@ -67,3 +67,3 @@ /**

"Program:exit": function(/*node*/) {
"Program:exit": function(/* node */) {

@@ -70,0 +70,0 @@ var globalScope = context.getScope();

@@ -98,5 +98,5 @@ /**

function isUsedVariable(variable, references) {
var functionNodes = variable.defs.filter(function (def) {
var functionNodes = variable.defs.filter(function(def) {
return def.type === "FunctionName";
}).map(function (def) {
}).map(function(def) {
return def.node;

@@ -106,3 +106,3 @@ }),

return references.some(function (ref) {
return references.some(function(ref) {
return isReadRef(ref) && !(isFunctionDefinition && isSelfReference(ref, functionNodes));

@@ -161,3 +161,3 @@ });

}
// skip function expression names
// skip function expression names and variables marked with markVariableAsUsed()
if (scope.functionExpressionScope || variable.eslintUsed) {

@@ -225,3 +225,5 @@ continue;

if (unusedVar.eslintExplicitGlobal) {
if (unusedVar.eslintUsed) {
continue; // explicitly exported variables
} else if (unusedVar.eslintExplicitGlobal) {
context.report(programNode, MESSAGE, unusedVar);

@@ -228,0 +230,0 @@ } else if (unusedVar.defs.length > 0) {

@@ -16,3 +16,3 @@ /**

return {
"VariableDeclaration": function (node) {
"VariableDeclaration": function(node) {
if (node.kind === "var") {

@@ -19,0 +19,0 @@ context.report(node, "Unexpected var, use let or const instead.");

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

module.exports = function (context) {
module.exports = function(context) {

@@ -58,3 +58,3 @@ var configuration = context.options[0] || {},

warningRegExps.forEach(function (regex, index) {
warningRegExps.forEach(function(regex, index) {
if (regex.test(comment)) {

@@ -76,3 +76,3 @@ matches.push(warningTerms[index]);

matches.forEach(function (matchedTerm) {
matches.forEach(function(matchedTerm) {
context.report(node, "Unexpected " + matchedTerm + " comment.");

@@ -79,0 +79,0 @@ });

@@ -102,3 +102,3 @@ /**

"AssignmentExpression": validateBinaryExpression,
"VariableDeclarator": function (node) {
"VariableDeclarator": function(node) {
if (node.init) {

@@ -105,0 +105,0 @@ validateBinaryExpression(node);

@@ -13,3 +13,3 @@ /**

module.exports = function (context) {
module.exports = function(context) {
var requirePadding = context.options[0] !== "never";

@@ -21,2 +21,26 @@

/**
* Retrieves an array of all comments defined inside the given node.
* @param {ASTNode} node The AST node.
* @returns {ASTNode[]} An array of comment nodes.
*/
function getCommentsInNode(node) {
var allComments = context.getAllComments();
return allComments.filter(function(comment) {
return node.range[0] < comment.range[0] &&
node.range[1] > comment.range[1];
});
}
/**
* Checks if the location of a node or token is before the location of another node or token
* @param {ASTNode|Token} a The node or token to check if its location is before b.
* @param {ASTNode|Token} b The node or token which will be compared with a.
* @returns {boolean} True if a is located before b.
*/
function isLocatedBefore(a, b) {
return a.range[1] < b.range[0];
}
/**
* Checks if the given non empty block node has a blank line before its first child node.

@@ -31,6 +55,7 @@ * @param {ASTNode} node The AST node of a BlockStatement.

expectedFirstLine = blockStart + 2,
leadingComments = context.getComments(first).leading;
comments = getCommentsInNode(node),
firstComment = comments[0];
if (leadingComments.length > 0) {
firstLine = leadingComments[0].loc.start.line;
if (firstComment && isLocatedBefore(firstComment, first)) {
firstLine = firstComment.loc.start.line;
}

@@ -49,8 +74,10 @@

last = node.body[node.body.length - 1],
lastLine = context.getLastToken(last).loc.end.line,
lastToken = context.getLastToken(last),
lastLine = lastToken.loc.end.line,
expectedLastLine = blockEnd - 2,
trailingComments = context.getComments(last).trailing;
comments = getCommentsInNode(node),
lastComment = comments[comments.length - 1];
if (trailingComments.length > 0) {
lastLine = trailingComments[trailingComments.length - 1].loc.end.line;
if (lastComment && isLocatedBefore(lastToken, lastComment)) {
lastLine = lastComment.loc.end.line;
}

@@ -57,0 +84,0 @@

@@ -78,3 +78,3 @@ /**

return {
"Program:exit": function () {
"Program:exit": function() {
var stack = [context.getScope()];

@@ -81,0 +81,0 @@ while (stack.length) {

@@ -13,3 +13,3 @@ /**

module.exports = function (context) {
module.exports = function(context) {

@@ -143,3 +143,3 @@ var config = context.options[0],

"ThrowStatement": checkNode,
"ForStatement": function (node) {
"ForStatement": function(node) {
if (node.init) {

@@ -146,0 +146,0 @@ checkSemicolonSpacing(context.getTokenAfter(node.init), node);

@@ -118,3 +118,3 @@ /**

"ExportAllDeclaration": checkForSemicolon,
"ExportNamedDeclaration": function (node) {
"ExportNamedDeclaration": function(node) {
if (!node.declaration) {

@@ -124,3 +124,3 @@ checkForSemicolon(node);

},
"ExportDefaultDeclaration": function (node) {
"ExportDefaultDeclaration": function(node) {
if (!/(?:Class|Function)Declaration/.test(node.declaration.type)) {

@@ -127,0 +127,0 @@ checkForSemicolon(node);

@@ -48,3 +48,3 @@ /**

return {
"IfStatement": function (node) {
"IfStatement": function(node) {
check(node);

@@ -60,3 +60,3 @@ // check the `else`

"WhileStatement": check,
"DoWhileStatement": function (node) {
"DoWhileStatement": function(node) {
check(node);

@@ -68,3 +68,3 @@ // check the `while`

"SwitchStatement": check,
"TryStatement": function (node) {
"TryStatement": function(node) {
check(node);

@@ -71,0 +71,0 @@ // check the `finally`

@@ -13,3 +13,3 @@ /**

module.exports = function (context) {
module.exports = function(context) {
var requireSpace = context.options[0] !== "never";

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

@@ -182,3 +182,3 @@ /**

function sortSkipRanges() {
skipRanges.sort(function (a, b) {
skipRanges.sort(function(a, b) {
return a[0] - b[0];

@@ -185,0 +185,0 @@ });

@@ -21,3 +21,3 @@ /**

var markerMatcher = new RegExp(" ");
var jsDocMatcher = new RegExp("((^(\\*)))[ \\n]");
var jsDocMatcher = new RegExp("((^(\\*)))[ \\r\\n]");

@@ -51,3 +51,3 @@ // Fetch the options dict

// the markerMatcher includes any markers in the list, followed by space/tab
markerMatcher = new RegExp("((^(" + markers.join("))|(^(") + ")))[ \\t\\n]");
markerMatcher = new RegExp("((^(" + markers.join("))|(^(") + ")))[ \\t\\r\\n]");
}

@@ -88,3 +88,3 @@

// Space expected and not found
if (node.value.indexOf(" ") !== 0 && node.value.indexOf("\t") !== 0 && node.value.indexOf("\n") !== 0) {
if (node.value.indexOf(" ") !== 0 && node.value.indexOf("\t") !== 0 && node.value.indexOf("\n") !== 0 && node.value.indexOf("\r") !== 0) {

@@ -91,0 +91,0 @@ /*

@@ -80,70 +80,2 @@ /**

//--------------------------------------------------------------------------
// "deprecated" mode (default)
//--------------------------------------------------------------------------
/**
* Determines if a given node is "use strict".
* @param {ASTNode} node The node to check.
* @returns {boolean} True if the node is a strict pragma, false if not.
* @void
*/
function isStrictPragma(node) {
return (node && node.type === "ExpressionStatement" &&
node.expression.value === "use strict");
}
/**
* When you enter a scope, push the strict value from the previous scope
* onto the stack.
* @param {ASTNode} node The AST node being checked.
* @returns {void}
* @private
*/
function enterScope(node) {
var isStrict = false,
isProgram = (node.type === "Program"),
isParentGlobal = scopes.length === 1,
isParentStrict = scopes.length ? scopes[scopes.length - 1] : false;
// look for the "use strict" pragma
if (isModule) {
isStrict = true;
} else if (isProgram) {
isStrict = isStrictPragma(node.body[0]) || isParentStrict;
} else {
isStrict = node.body.body && isStrictPragma(node.body.body[0]) || isParentStrict;
}
scopes.push(isStrict);
// never warn if the parent is strict or the function is strict
if (!isParentStrict && !isStrict && isParentGlobal) {
context.report(node, "Missing \"use strict\" statement.");
}
}
/**
* When you exit a scope, pop off the top scope and see if it's true or
* false.
* @returns {void}
* @private
*/
function exitScope() {
scopes.pop();
}
modes.deprecated = {
"Program": enterScope,
"FunctionDeclaration": enterScope,
"FunctionExpression": enterScope,
"ArrowFunctionExpression": enterScope,
"Program:exit": exitScope,
"FunctionDeclaration:exit": exitScope,
"FunctionExpression:exit": exitScope,
"ArrowFunctionExpression:exit": exitScope
};
//--------------------------------------------------------------------------
// "never" mode

@@ -189,3 +121,3 @@ //--------------------------------------------------------------------------

//--------------------------------------------------------------------------
// "function" mode
// "function" mode (Default)
//--------------------------------------------------------------------------

@@ -232,7 +164,11 @@

"FunctionExpression": enterFunction,
"ArrowFunctionExpression": enterFunction,
"FunctionDeclaration:exit": exitFunction,
"FunctionExpression:exit": exitFunction
"FunctionExpression:exit": exitFunction,
"ArrowFunctionExpression:exit": exitFunction
};
return modes[mode || "deprecated"];
return modes[mode || "function"];

@@ -239,0 +175,0 @@ };

@@ -14,6 +14,6 @@ /**

module.exports = function (context) {
module.exports = function(context) {
return {
"BinaryExpression": function (node) {
"BinaryExpression": function(node) {
if (/^(?:[<>]|[!=]=)=?$/.test(node.operator) && (node.left.name === "NaN" || node.right.name === "NaN")) {

@@ -20,0 +20,0 @@ context.report(node, "Use the isNaN function to compare with NaN.");

@@ -37,7 +37,10 @@ /**

* When parsing a new function, store it in our function stack.
* @param {ASTNode} node A function node to check.
* @returns {void}
* @private
*/
function startFunction() {
fns.push({returnPresent: false});
function startFunction(node) {
fns.push({
returnPresent: (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement")
});
}

@@ -44,0 +47,0 @@

@@ -22,3 +22,3 @@ /**

"UnaryExpression": function (node) {
"UnaryExpression": function(node) {
var parent, sibling;

@@ -25,0 +25,0 @@

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

module.exports = function (context) {
module.exports = function(context) {
var errorMessage = "All \"var\" declarations must be at the top of the function scope.";

@@ -99,3 +99,3 @@

return {
"VariableDeclaration": function (node) {
"VariableDeclaration": function(node) {
var ancestors = context.getAncestors();

@@ -102,0 +102,0 @@ var parent = ancestors.pop();

@@ -117,3 +117,3 @@ /**

module.exports = function (context) {
module.exports = function(context) {

@@ -120,0 +120,0 @@ // Default to "never" (!always) if no option

@@ -77,7 +77,7 @@ /**

if (target && typeof target === "object") {
Object.keys(target).forEach(function (key) {
Object.keys(target).forEach(function(key) {
dst[key] = target[key];
});
}
Object.keys(src).forEach(function (key) {
Object.keys(src).forEach(function(key) {
if (Array.isArray(src[key]) || Array.isArray(target[key])) {

@@ -84,0 +84,0 @@ dst[key] = deepmerge(target[key], src[key], key === "plugins");

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

callback(filePath);
return;
} else if (fileStat.isDirectory()) {

@@ -83,2 +84,3 @@ traverse(file, stack);

callback(name);
return;
} else {

@@ -85,0 +87,0 @@ traverse(name, []);

{
"name": "eslint",
"version": "0.24.1",
"version": "1.0.0-rc-1",
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",

@@ -42,7 +42,7 @@ "description": "An AST-based pattern checker for JavaScript.",

"escape-string-regexp": "^1.0.2",
"escope": "^3.1.0",
"espree": "^2.0.1",
"escope": "^3.2.0",
"espree": "^2.2.0",
"estraverse": "^4.1.0",
"estraverse-fb": "^1.3.1",
"globals": "^8.0.0",
"globals": "^8.2.0",
"inquirer": "^0.8.2",

@@ -56,2 +56,3 @@ "is-my-json-valid": "^2.10.0",

"path-is-absolute": "^1.0.0",
"path-is-inside": "^1.0.1",
"strip-json-comments": "~1.0.1",

@@ -58,0 +59,0 @@ "text-table": "~0.2.0",

[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Build status][appveyor-image]][appveyor-url]
[![Test coverage][coveralls-image]][coveralls-url]

@@ -108,2 +109,4 @@ [![Downloads][downloads-image]][downloads-url]

[travis-url]: https://travis-ci.org/eslint/eslint
[appveyor-image]: https://ci.appveyor.com/api/projects/status/nnjjujvp9535u3cl/branch/master?svg=true
[appveyor-url]: https://ci.appveyor.com/project/nzakas/eslint/branch/master
[coveralls-image]: https://img.shields.io/coveralls/eslint/eslint/master.svg?style=flat-square

@@ -110,0 +113,0 @@ [coveralls-url]: https://coveralls.io/r/eslint/eslint?branch=master

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