项目原始demo,不改动
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 

114 lines
3.4 KiB

  1. /**
  2. * @fileoverview Rule to flag blocks with no reason to exist
  3. * @author Brandon Mills
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Rule Definition
  8. //------------------------------------------------------------------------------
  9. module.exports = {
  10. meta: {
  11. docs: {
  12. description: "disallow unnecessary nested blocks",
  13. category: "Best Practices",
  14. recommended: false,
  15. url: "https://eslint.org/docs/rules/no-lone-blocks"
  16. },
  17. schema: []
  18. },
  19. create(context) {
  20. // A stack of lone blocks to be checked for block-level bindings
  21. const loneBlocks = [];
  22. let ruleDef;
  23. /**
  24. * Reports a node as invalid.
  25. * @param {ASTNode} node - The node to be reported.
  26. * @returns {void}
  27. */
  28. function report(node) {
  29. const message = node.parent.type === "BlockStatement" ? "Nested block is redundant." : "Block is redundant.";
  30. context.report({ node, message });
  31. }
  32. /**
  33. * Checks for any ocurrence of a BlockStatement in a place where lists of statements can appear
  34. * @param {ASTNode} node The node to check
  35. * @returns {boolean} True if the node is a lone block.
  36. */
  37. function isLoneBlock(node) {
  38. return node.parent.type === "BlockStatement" ||
  39. node.parent.type === "Program" ||
  40. // Don't report blocks in switch cases if the block is the only statement of the case.
  41. node.parent.type === "SwitchCase" && !(node.parent.consequent[0] === node && node.parent.consequent.length === 1);
  42. }
  43. /**
  44. * Checks the enclosing block of the current node for block-level bindings,
  45. * and "marks it" as valid if any.
  46. * @returns {void}
  47. */
  48. function markLoneBlock() {
  49. if (loneBlocks.length === 0) {
  50. return;
  51. }
  52. const block = context.getAncestors().pop();
  53. if (loneBlocks[loneBlocks.length - 1] === block) {
  54. loneBlocks.pop();
  55. }
  56. }
  57. // Default rule definition: report all lone blocks
  58. ruleDef = {
  59. BlockStatement(node) {
  60. if (isLoneBlock(node)) {
  61. report(node);
  62. }
  63. }
  64. };
  65. // ES6: report blocks without block-level bindings
  66. if (context.parserOptions.ecmaVersion >= 6) {
  67. ruleDef = {
  68. BlockStatement(node) {
  69. if (isLoneBlock(node)) {
  70. loneBlocks.push(node);
  71. }
  72. },
  73. "BlockStatement:exit"(node) {
  74. if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) {
  75. loneBlocks.pop();
  76. report(node);
  77. }
  78. }
  79. };
  80. ruleDef.VariableDeclaration = function(node) {
  81. if (node.kind === "let" || node.kind === "const") {
  82. markLoneBlock();
  83. }
  84. };
  85. ruleDef.FunctionDeclaration = function() {
  86. if (context.getScope().isStrict) {
  87. markLoneBlock();
  88. }
  89. };
  90. ruleDef.ClassDeclaration = markLoneBlock;
  91. }
  92. return ruleDef;
  93. }
  94. };