boolean.js 2.1 KB

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