Ohm-Management - Projektarbeit B-ME
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.

vars-on-top.js 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /**
  2. * @fileoverview Rule to enforce var declarations are only at the top of a function.
  3. * @author Danny Fritz
  4. * @author Gyandeep Singh
  5. */
  6. "use strict";
  7. //------------------------------------------------------------------------------
  8. // Rule Definition
  9. //------------------------------------------------------------------------------
  10. module.exports = {
  11. meta: {
  12. type: "suggestion",
  13. docs: {
  14. description: "require `var` declarations be placed at the top of their containing scope",
  15. category: "Best Practices",
  16. recommended: false,
  17. url: "https://eslint.org/docs/rules/vars-on-top"
  18. },
  19. schema: []
  20. },
  21. create(context) {
  22. const errorMessage = "All 'var' declarations must be at the top of the function scope.";
  23. //--------------------------------------------------------------------------
  24. // Helpers
  25. //--------------------------------------------------------------------------
  26. /**
  27. * @param {ASTNode} node - any node
  28. * @returns {boolean} whether the given node structurally represents a directive
  29. */
  30. function looksLikeDirective(node) {
  31. return node.type === "ExpressionStatement" &&
  32. node.expression.type === "Literal" && typeof node.expression.value === "string";
  33. }
  34. /**
  35. * Check to see if its a ES6 import declaration
  36. * @param {ASTNode} node - any node
  37. * @returns {boolean} whether the given node represents a import declaration
  38. */
  39. function looksLikeImport(node) {
  40. return node.type === "ImportDeclaration" || node.type === "ImportSpecifier" ||
  41. node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier";
  42. }
  43. /**
  44. * Checks whether a given node is a variable declaration or not.
  45. *
  46. * @param {ASTNode} node - any node
  47. * @returns {boolean} `true` if the node is a variable declaration.
  48. */
  49. function isVariableDeclaration(node) {
  50. return (
  51. node.type === "VariableDeclaration" ||
  52. (
  53. node.type === "ExportNamedDeclaration" &&
  54. node.declaration &&
  55. node.declaration.type === "VariableDeclaration"
  56. )
  57. );
  58. }
  59. /**
  60. * Checks whether this variable is on top of the block body
  61. * @param {ASTNode} node - The node to check
  62. * @param {ASTNode[]} statements - collection of ASTNodes for the parent node block
  63. * @returns {boolean} True if var is on top otherwise false
  64. */
  65. function isVarOnTop(node, statements) {
  66. const l = statements.length;
  67. let i = 0;
  68. // skip over directives
  69. for (; i < l; ++i) {
  70. if (!looksLikeDirective(statements[i]) && !looksLikeImport(statements[i])) {
  71. break;
  72. }
  73. }
  74. for (; i < l; ++i) {
  75. if (!isVariableDeclaration(statements[i])) {
  76. return false;
  77. }
  78. if (statements[i] === node) {
  79. return true;
  80. }
  81. }
  82. return false;
  83. }
  84. /**
  85. * Checks whether variable is on top at the global level
  86. * @param {ASTNode} node - The node to check
  87. * @param {ASTNode} parent - Parent of the node
  88. * @returns {void}
  89. */
  90. function globalVarCheck(node, parent) {
  91. if (!isVarOnTop(node, parent.body)) {
  92. context.report({ node, message: errorMessage });
  93. }
  94. }
  95. /**
  96. * Checks whether variable is on top at functional block scope level
  97. * @param {ASTNode} node - The node to check
  98. * @param {ASTNode} parent - Parent of the node
  99. * @param {ASTNode} grandParent - Parent of the node's parent
  100. * @returns {void}
  101. */
  102. function blockScopeVarCheck(node, parent, grandParent) {
  103. if (!(/Function/.test(grandParent.type) &&
  104. parent.type === "BlockStatement" &&
  105. isVarOnTop(node, parent.body))) {
  106. context.report({ node, message: errorMessage });
  107. }
  108. }
  109. //--------------------------------------------------------------------------
  110. // Public API
  111. //--------------------------------------------------------------------------
  112. return {
  113. "VariableDeclaration[kind='var']"(node) {
  114. if (node.parent.type === "ExportNamedDeclaration") {
  115. globalVarCheck(node.parent, node.parent.parent);
  116. } else if (node.parent.type === "Program") {
  117. globalVarCheck(node, node.parent);
  118. } else {
  119. blockScopeVarCheck(node, node.parent, node.parent.parent);
  120. }
  121. }
  122. };
  123. }
  124. };