summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib/rules/vars-on-top.js
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-12-22 16:53:42 +0100
committerMichaël Zasso <targos@protonmail.com>2018-01-11 09:48:05 +0100
commit3dc30632755713179f345f4af024bd904c6162d0 (patch)
treef28c4f6dd6dfc5992edf301449d1a371d229755b /tools/node_modules/eslint/lib/rules/vars-on-top.js
parenta2c7085dd4a8e60d1a47572aca8bb6fcb7a32f88 (diff)
downloadandroid-node-v8-3dc30632755713179f345f4af024bd904c6162d0.tar.gz
android-node-v8-3dc30632755713179f345f4af024bd904c6162d0.tar.bz2
android-node-v8-3dc30632755713179f345f4af024bd904c6162d0.zip
tools: move eslint from tools to tools/node_modules
This is required because we need to add the babel-eslint dependency and it has to be able to resolve "eslint". babel-eslint is required to support future ES features such as async iterators and import.meta. Refs: https://github.com/nodejs/node/pull/17755 PR-URL: https://github.com/nodejs/node/pull/17820 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/vars-on-top.js')
-rw-r--r--tools/node_modules/eslint/lib/rules/vars-on-top.js149
1 files changed, 149 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/vars-on-top.js b/tools/node_modules/eslint/lib/rules/vars-on-top.js
new file mode 100644
index 0000000000..f74db905b1
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/vars-on-top.js
@@ -0,0 +1,149 @@
+/**
+ * @fileoverview Rule to enforce var declarations are only at the top of a function.
+ * @author Danny Fritz
+ * @author Gyandeep Singh
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "require `var` declarations be placed at the top of their containing scope",
+ category: "Best Practices",
+ recommended: false
+ },
+
+ schema: []
+ },
+
+ create(context) {
+ const errorMessage = "All 'var' declarations must be at the top of the function scope.";
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @param {ASTNode} node - any node
+ * @returns {boolean} whether the given node structurally represents a directive
+ */
+ function looksLikeDirective(node) {
+ return node.type === "ExpressionStatement" &&
+ node.expression.type === "Literal" && typeof node.expression.value === "string";
+ }
+
+ /**
+ * Check to see if its a ES6 import declaration
+ * @param {ASTNode} node - any node
+ * @returns {boolean} whether the given node represents a import declaration
+ */
+ function looksLikeImport(node) {
+ return node.type === "ImportDeclaration" || node.type === "ImportSpecifier" ||
+ node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier";
+ }
+
+ /**
+ * Checks whether a given node is a variable declaration or not.
+ *
+ * @param {ASTNode} node - any node
+ * @returns {boolean} `true` if the node is a variable declaration.
+ */
+ function isVariableDeclaration(node) {
+ return (
+ node.type === "VariableDeclaration" ||
+ (
+ node.type === "ExportNamedDeclaration" &&
+ node.declaration &&
+ node.declaration.type === "VariableDeclaration"
+ )
+ );
+ }
+
+ /**
+ * Checks whether this variable is on top of the block body
+ * @param {ASTNode} node - The node to check
+ * @param {ASTNode[]} statements - collection of ASTNodes for the parent node block
+ * @returns {boolean} True if var is on top otherwise false
+ */
+ function isVarOnTop(node, statements) {
+ const l = statements.length;
+ let i = 0;
+
+ // skip over directives
+ for (; i < l; ++i) {
+ if (!looksLikeDirective(statements[i]) && !looksLikeImport(statements[i])) {
+ break;
+ }
+ }
+
+ for (; i < l; ++i) {
+ if (!isVariableDeclaration(statements[i])) {
+ return false;
+ }
+ if (statements[i] === node) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether variable is on top at the global level
+ * @param {ASTNode} node - The node to check
+ * @param {ASTNode} parent - Parent of the node
+ * @returns {void}
+ */
+ function globalVarCheck(node, parent) {
+ if (!isVarOnTop(node, parent.body)) {
+ context.report({ node, message: errorMessage });
+ }
+ }
+
+ /**
+ * Checks whether variable is on top at functional block scope level
+ * @param {ASTNode} node - The node to check
+ * @param {ASTNode} parent - Parent of the node
+ * @param {ASTNode} grandParent - Parent of the node's parent
+ * @returns {void}
+ */
+ function blockScopeVarCheck(node, parent, grandParent) {
+ if (!(/Function/.test(grandParent.type) &&
+ parent.type === "BlockStatement" &&
+ isVarOnTop(node, parent.body))) {
+ context.report({ node, message: errorMessage });
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Public API
+ //--------------------------------------------------------------------------
+
+ return {
+ VariableDeclaration(node) {
+ const ancestors = context.getAncestors();
+ let parent = ancestors.pop();
+ let grandParent = ancestors.pop();
+
+ if (node.kind === "var") { // check variable is `var` type and not `let` or `const`
+ if (parent.type === "ExportNamedDeclaration") {
+ node = parent;
+ parent = grandParent;
+ grandParent = ancestors.pop();
+ }
+
+ if (parent.type === "Program") { // That means its a global variable
+ globalVarCheck(node, parent);
+ } else {
+ blockScopeVarCheck(node, parent, grandParent);
+ }
+ }
+ }
+ };
+
+ }
+};