Permalink
Cannot retrieve contributors at this time
157 lines (136 sloc)
5.17 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/eslint/lib/rules/vars-on-top.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @fileoverview Rule to enforce var declarations are only at the top of a function. | |
* @author Danny Fritz | |
* @author Gyandeep Singh | |
*/ | |
"use strict"; | |
//------------------------------------------------------------------------------ | |
// Rule Definition | |
//------------------------------------------------------------------------------ | |
/** @type {import('../shared/types').Rule} */ | |
module.exports = { | |
meta: { | |
type: "suggestion", | |
docs: { | |
description: "Require `var` declarations be placed at the top of their containing scope", | |
recommended: false, | |
url: "https://eslint.org/docs/latest/rules/vars-on-top" | |
}, | |
schema: [], | |
messages: { | |
top: "All 'var' declarations must be at the top of the function scope." | |
} | |
}, | |
create(context) { | |
//-------------------------------------------------------------------------- | |
// Helpers | |
//-------------------------------------------------------------------------- | |
/** | |
* Has AST suggesting a directive. | |
* @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 and imports. Static blocks don't have either. | |
if (node.parent.type !== "StaticBlock") { | |
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, messageId: "top" }); | |
} | |
} | |
/** | |
* Checks whether variable is on top at functional block scope level | |
* @param {ASTNode} node The node to check | |
* @returns {void} | |
*/ | |
function blockScopeVarCheck(node) { | |
const { parent } = node; | |
if ( | |
parent.type === "BlockStatement" && | |
/Function/u.test(parent.parent.type) && | |
isVarOnTop(node, parent.body) | |
) { | |
return; | |
} | |
if ( | |
parent.type === "StaticBlock" && | |
isVarOnTop(node, parent.body) | |
) { | |
return; | |
} | |
context.report({ node, messageId: "top" }); | |
} | |
//-------------------------------------------------------------------------- | |
// Public API | |
//-------------------------------------------------------------------------- | |
return { | |
"VariableDeclaration[kind='var']"(node) { | |
if (node.parent.type === "ExportNamedDeclaration") { | |
globalVarCheck(node.parent, node.parent.parent); | |
} else if (node.parent.type === "Program") { | |
globalVarCheck(node, node.parent); | |
} else { | |
blockScopeVarCheck(node); | |
} | |
} | |
}; | |
} | |
}; |