boolean.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. 'use strict';
  2. const isLogicalExpression = require('./is-logical-expression.js');
  3. const isLogicNot = node =>
  4. node
  5. && node.type === 'UnaryExpression'
  6. && node.operator === '!';
  7. const isLogicNotArgument = node =>
  8. isLogicNot(node.parent)
  9. && node.parent.argument === node;
  10. const isBooleanCallArgument = node =>
  11. isBooleanCall(node.parent)
  12. && node.parent.arguments[0] === node;
  13. const isBooleanCall = node =>
  14. node
  15. && node.type === 'CallExpression'
  16. && node.callee
  17. && node.callee.type === 'Identifier'
  18. && node.callee.name === 'Boolean'
  19. && node.arguments.length === 1;
  20. const isVueBooleanAttributeValue = node =>
  21. node
  22. && node.type === 'VExpressionContainer'
  23. && node.parent.type === 'VAttribute'
  24. && node.parent.directive
  25. && node.parent.value === node
  26. && node.parent.key.type === 'VDirectiveKey'
  27. && node.parent.key.name.type === 'VIdentifier'
  28. && (
  29. node.parent.key.name.rawName === 'if'
  30. || node.parent.key.name.rawName === 'else-if'
  31. || node.parent.key.name.rawName === 'show'
  32. );
  33. /**
  34. Check if the value of node is a `boolean`.
  35. @param {Node} node
  36. @returns {boolean}
  37. */
  38. function isBooleanNode(node) {
  39. if (
  40. isLogicNot(node)
  41. || isLogicNotArgument(node)
  42. || isBooleanCall(node)
  43. || isBooleanCallArgument(node)
  44. ) {
  45. return true;
  46. }
  47. const {parent} = node;
  48. if (isVueBooleanAttributeValue(parent)) {
  49. return true;
  50. }
  51. if (
  52. (
  53. parent.type === 'IfStatement'
  54. || parent.type === 'ConditionalExpression'
  55. || parent.type === 'WhileStatement'
  56. || parent.type === 'DoWhileStatement'
  57. || parent.type === 'ForStatement'
  58. )
  59. && parent.test === node
  60. ) {
  61. return true;
  62. }
  63. if (isLogicalExpression(parent)) {
  64. return isBooleanNode(parent);
  65. }
  66. return false;
  67. }
  68. /**
  69. Get the boolean type-casting ancestor.
  70. @typedef {{ node: Node, isNegative: boolean }} Result
  71. @param {Node} node
  72. @returns {Result}
  73. */
  74. function getBooleanAncestor(node) {
  75. let isNegative = false;
  76. // eslint-disable-next-line no-constant-condition
  77. while (true) {
  78. if (isLogicNotArgument(node)) {
  79. isNegative = !isNegative;
  80. node = node.parent;
  81. } else if (isBooleanCallArgument(node)) {
  82. node = node.parent;
  83. } else {
  84. break;
  85. }
  86. }
  87. return {node, isNegative};
  88. }
  89. module.exports = {isBooleanNode, getBooleanAncestor};