123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- "use strict";
- 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) {
-
-
-
-
- function looksLikeDirective(node) {
- return node.type === "ExpressionStatement" &&
- node.expression.type === "Literal" && typeof node.expression.value === "string";
- }
-
- function looksLikeImport(node) {
- return node.type === "ImportDeclaration" || node.type === "ImportSpecifier" ||
- node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier";
- }
-
- function isVariableDeclaration(node) {
- return (
- node.type === "VariableDeclaration" ||
- (
- node.type === "ExportNamedDeclaration" &&
- node.declaration &&
- node.declaration.type === "VariableDeclaration"
- )
- );
- }
-
- function isVarOnTop(node, statements) {
- const l = statements.length;
- let i = 0;
-
- 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;
- }
-
- function globalVarCheck(node, parent) {
- if (!isVarOnTop(node, parent.body)) {
- context.report({ node, messageId: "top" });
- }
- }
-
- 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" });
- }
-
-
-
- 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);
- }
- }
- };
- }
- };
|