Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
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 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. messages: {
  21. top: "All 'var' declarations must be at the top of the function scope."
  22. }
  23. },
  24. create(context) {
  25. //--------------------------------------------------------------------------
  26. // Helpers
  27. //--------------------------------------------------------------------------
  28. // eslint-disable-next-line jsdoc/require-description
  29. /**
  30. * @param {ASTNode} node any node
  31. * @returns {boolean} whether the given node structurally represents a directive
  32. */
  33. function looksLikeDirective(node) {
  34. return node.type === "ExpressionStatement" &&
  35. node.expression.type === "Literal" && typeof node.expression.value === "string";
  36. }
  37. /**
  38. * Check to see if its a ES6 import declaration
  39. * @param {ASTNode} node any node
  40. * @returns {boolean} whether the given node represents a import declaration
  41. */
  42. function looksLikeImport(node) {
  43. return node.type === "ImportDeclaration" || node.type === "ImportSpecifier" ||
  44. node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier";
  45. }
  46. /**
  47. * Checks whether a given node is a variable declaration or not.
  48. * @param {ASTNode} node any node
  49. * @returns {boolean} `true` if the node is a variable declaration.
  50. */
  51. function isVariableDeclaration(node) {
  52. return (
  53. node.type === "VariableDeclaration" ||
  54. (
  55. node.type === "ExportNamedDeclaration" &&
  56. node.declaration &&
  57. node.declaration.type === "VariableDeclaration"
  58. )
  59. );
  60. }
  61. /**
  62. * Checks whether this variable is on top of the block body
  63. * @param {ASTNode} node The node to check
  64. * @param {ASTNode[]} statements collection of ASTNodes for the parent node block
  65. * @returns {boolean} True if var is on top otherwise false
  66. */
  67. function isVarOnTop(node, statements) {
  68. const l = statements.length;
  69. let i = 0;
  70. // skip over directives
  71. for (; i < l; ++i) {
  72. if (!looksLikeDirective(statements[i]) && !looksLikeImport(statements[i])) {
  73. break;
  74. }
  75. }
  76. for (; i < l; ++i) {
  77. if (!isVariableDeclaration(statements[i])) {
  78. return false;
  79. }
  80. if (statements[i] === node) {
  81. return true;
  82. }
  83. }
  84. return false;
  85. }
  86. /**
  87. * Checks whether variable is on top at the global level
  88. * @param {ASTNode} node The node to check
  89. * @param {ASTNode} parent Parent of the node
  90. * @returns {void}
  91. */
  92. function globalVarCheck(node, parent) {
  93. if (!isVarOnTop(node, parent.body)) {
  94. context.report({ node, messageId: "top" });
  95. }
  96. }
  97. /**
  98. * Checks whether variable is on top at functional block scope level
  99. * @param {ASTNode} node The node to check
  100. * @param {ASTNode} parent Parent of the node
  101. * @param {ASTNode} grandParent Parent of the node's parent
  102. * @returns {void}
  103. */
  104. function blockScopeVarCheck(node, parent, grandParent) {
  105. if (!(/Function/u.test(grandParent.type) &&
  106. parent.type === "BlockStatement" &&
  107. isVarOnTop(node, parent.body))) {
  108. context.report({ node, messageId: "top" });
  109. }
  110. }
  111. //--------------------------------------------------------------------------
  112. // Public API
  113. //--------------------------------------------------------------------------
  114. return {
  115. "VariableDeclaration[kind='var']"(node) {
  116. if (node.parent.type === "ExportNamedDeclaration") {
  117. globalVarCheck(node.parent, node.parent.parent);
  118. } else if (node.parent.type === "Program") {
  119. globalVarCheck(node, node.parent);
  120. } else {
  121. blockScopeVarCheck(node, node.parent, node.parent.parent);
  122. }
  123. }
  124. };
  125. }
  126. };