mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
2.9 KiB
92 lines
2.9 KiB
10 years ago
|
/**
|
||
|
* @fileoverview A rule to suggest using of const declaration for variables that are never modified after declared.
|
||
|
* @author Toru Nagashima
|
||
|
* @copyright 2015 Toru Nagashima. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Rule Definition
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
module.exports = function(context) {
|
||
|
|
||
|
/**
|
||
|
* Checks whether a reference is the initializer.
|
||
|
* @param {Reference} reference - A reference to check.
|
||
|
* @returns {boolean} Whether or not the reference is the initializer.
|
||
|
*/
|
||
|
function isInitializer(reference) {
|
||
|
return reference.init === true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks whether a reference is read-only or the initializer.
|
||
|
* @param {Reference} reference - A reference to check.
|
||
|
* @returns {boolean} Whether or not the reference is read-only or the initializer.
|
||
|
*/
|
||
|
function isReadOnlyOrInitializer(reference) {
|
||
|
return reference.isReadOnly() || reference.init === true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Searches and reports variables that are never modified after declared.
|
||
|
* @param {Scope} scope - A scope of the search domain.
|
||
|
* @returns {void}
|
||
|
*/
|
||
|
function checkForVariables(scope) {
|
||
|
// Skip the TDZ type.
|
||
|
if (scope.type === "TDZ") {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var variables = scope.variables;
|
||
|
for (var i = 0, end = variables.length; i < end; ++i) {
|
||
|
var variable = variables[i];
|
||
|
var def = variable.defs[0];
|
||
|
var declaration = def && def.parent;
|
||
|
var statement = declaration && declaration.parent;
|
||
|
var references = variable.references;
|
||
|
var identifier = variable.identifiers[0];
|
||
|
|
||
|
if (statement != null &&
|
||
|
identifier != null &&
|
||
|
declaration.type === "VariableDeclaration" &&
|
||
|
declaration.kind === "let" &&
|
||
|
(statement.type !== "ForStatement" || statement.init !== declaration) &&
|
||
|
references.some(isInitializer) &&
|
||
|
references.every(isReadOnlyOrInitializer)
|
||
|
) {
|
||
|
context.report(
|
||
|
identifier,
|
||
|
"`{{name}}` is never modified, use `const` instead.",
|
||
|
{name: identifier.name});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds multiple items to the tail of an array.
|
||
|
* @param {any[]} array - A destination to add.
|
||
|
* @param {any[]} values - Items to be added.
|
||
|
* @returns {void}
|
||
|
*/
|
||
|
var pushAll = Function.apply.bind(Array.prototype.push);
|
||
|
|
||
|
return {
|
||
|
"Program:exit": function () {
|
||
|
var stack = [context.getScope()];
|
||
|
while (stack.length) {
|
||
|
var scope = stack.pop();
|
||
|
pushAll(stack, scope.childScopes);
|
||
|
|
||
|
checkForVariables(scope);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
};
|
||
|
|
||
|
module.exports.schema = [];
|