NumberToNumericalExpressionTransformer.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import { inject, injectable, } from 'inversify';
  2. import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
  3. import * as ESTree from 'estree';
  4. import { TNumberNumericalExpressionData } from '../../types/analyzers/number-numerical-expression-analyzer/TNumberNumericalExpressionData';
  5. import { INumberNumericalExpressionAnalyzer } from '../../interfaces/analyzers/number-numerical-expression-analyzer/INumberNumericalExpressionAnalyzer';
  6. import { IOptions } from '../../interfaces/options/IOptions';
  7. import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
  8. import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
  9. import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
  10. import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
  11. import { NodeGuards } from '../../node/NodeGuards';
  12. import { NodeFactory } from '../../node/NodeFactory';
  13. import { NumberNumericalExpressionAnalyzer } from '../../analyzers/number-numerical-expression-analyzer/NumberNumericalExpressionAnalyzer';
  14. import { NumberUtils } from '../../utils/NumberUtils';
  15. import { NumericalExpressionDataToNodeConverter } from '../../node/NumericalExpressionDataToNodeConverter';
  16. /**
  17. * replaces:
  18. * var number = 123;
  19. *
  20. * on:
  21. * var number = 50 + (100 * 2) - 127;
  22. */
  23. @injectable()
  24. export class NumberToNumericalExpressionTransformer extends AbstractNodeTransformer {
  25. /**
  26. * @type {INumberNumericalExpressionAnalyzer}
  27. */
  28. private readonly numberNumericalExpressionAnalyzer: INumberNumericalExpressionAnalyzer;
  29. /**
  30. * @param {INumberNumericalExpressionAnalyzer} numberNumericalExpressionAnalyzer
  31. * @param {IRandomGenerator} randomGenerator
  32. * @param {IOptions} options
  33. */
  34. public constructor (
  35. @inject(ServiceIdentifiers.INumberNumericalExpressionAnalyzer)
  36. numberNumericalExpressionAnalyzer: INumberNumericalExpressionAnalyzer,
  37. @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
  38. @inject(ServiceIdentifiers.IOptions) options: IOptions
  39. ) {
  40. super(randomGenerator, options);
  41. this.numberNumericalExpressionAnalyzer = numberNumericalExpressionAnalyzer;
  42. }
  43. /**
  44. * @param {NodeTransformationStage} nodeTransformationStage
  45. * @returns {IVisitor | null}
  46. */
  47. public getVisitor (nodeTransformationStage: NodeTransformationStage): IVisitor | null {
  48. if (!this.options.numbersToExpressions) {
  49. return null;
  50. }
  51. switch (nodeTransformationStage) {
  52. case NodeTransformationStage.Converting:
  53. return {
  54. leave: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | undefined => {
  55. if (parentNode && NodeGuards.isLiteralNode(node)) {
  56. return this.transformNode(node, parentNode);
  57. }
  58. }
  59. };
  60. default:
  61. return null;
  62. }
  63. }
  64. /**
  65. * @param {Literal} literalNode
  66. * @param {NodeGuards} parentNode
  67. * @returns {NodeGuards}
  68. */
  69. public transformNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): ESTree.Node {
  70. if (typeof literalNode.value !== 'number') {
  71. return literalNode;
  72. }
  73. if (NodeGuards.isPropertyNode(parentNode) && !parentNode.computed) {
  74. return literalNode;
  75. }
  76. const baseNumber: number = literalNode.value;
  77. const [integerPart, decimalPart] = NumberUtils.extractIntegerAndDecimalParts(baseNumber);
  78. const integerNumberNumericalExpressionData: TNumberNumericalExpressionData = this.numberNumericalExpressionAnalyzer
  79. .analyze(
  80. integerPart,
  81. NumberNumericalExpressionAnalyzer.defaultAdditionalPartsCount
  82. );
  83. if (decimalPart) {
  84. return NumericalExpressionDataToNodeConverter.convertFloatNumberData(
  85. integerNumberNumericalExpressionData,
  86. decimalPart,
  87. this.getNumberNumericalExpressionLiteralNode
  88. );
  89. } else {
  90. return NumericalExpressionDataToNodeConverter.convertIntegerNumberData(
  91. integerNumberNumericalExpressionData,
  92. this.getNumberNumericalExpressionLiteralNode
  93. );
  94. }
  95. }
  96. /**
  97. * @param {number} number
  98. * @param {boolean} isPositiveNumber
  99. * @returns {Expression}
  100. */
  101. private getNumberNumericalExpressionLiteralNode (number: number, isPositiveNumber: boolean): ESTree.Expression {
  102. const numberLiteralNode: ESTree.Literal = NodeFactory.literalNode(number);
  103. return isPositiveNumber
  104. ? numberLiteralNode
  105. : NodeFactory.unaryExpressionNode(
  106. '-',
  107. numberLiteralNode
  108. );
  109. }
  110. }