StringLiteralControlFlowReplacer.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { injectable, inject } from 'inversify';
  2. import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
  3. import * as ESTree from 'estree';
  4. import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
  5. import { TStatement } from '../../../types/node/TStatement';
  6. import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
  7. import { IOptions } from '../../../interfaces/options/IOptions';
  8. import { IStorage } from '../../../interfaces/storages/IStorage';
  9. import { CustomNodes } from '../../../enums/container/custom-nodes/CustomNodes';
  10. import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
  11. import { Node } from '../../../node/Node';
  12. @injectable()
  13. export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplacer {
  14. /**
  15. * @type {number}
  16. */
  17. private static readonly usingExistingIdentifierChance: number = 1;
  18. /**
  19. * @param customNodeFactory
  20. * @param options
  21. */
  22. constructor (
  23. @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
  24. @inject(ServiceIdentifiers.IOptions) options: IOptions
  25. ) {
  26. super(customNodeFactory, options);
  27. }
  28. /**
  29. * @param literalNode
  30. * @param parentNode
  31. * @param controlFlowStorage
  32. * @returns {ESTree.Node}
  33. */
  34. public replace (
  35. literalNode: ESTree.Literal,
  36. parentNode: ESTree.Node,
  37. controlFlowStorage: IStorage <ICustomNode>
  38. ): ESTree.Node {
  39. if (Node.isPropertyNode(parentNode) && parentNode.key === literalNode) {
  40. return literalNode;
  41. }
  42. if (typeof literalNode.value !== 'string' || literalNode.value.length < 3) {
  43. return literalNode;
  44. }
  45. const replacerId: string = String(literalNode.value);
  46. const literalFunctionCustomNode: ICustomNode = this.customNodeFactory(CustomNodes.StringLiteralNode);
  47. literalFunctionCustomNode.initialize(literalNode.value);
  48. const storageKey: string = this.insertCustomNodeToControlFlowStorage(
  49. literalFunctionCustomNode,
  50. controlFlowStorage,
  51. replacerId,
  52. StringLiteralControlFlowReplacer.usingExistingIdentifierChance
  53. );
  54. return this.getControlFlowStorageCallNode(controlFlowStorage.getStorageId(), storageKey);
  55. }
  56. /**
  57. * @param controlFlowStorageId
  58. * @param storageKey
  59. * @returns {ESTree.Node}
  60. */
  61. protected getControlFlowStorageCallNode (
  62. controlFlowStorageId: string,
  63. storageKey: string
  64. ): ESTree.Node {
  65. const controlFlowStorageCallCustomNode: ICustomNode = this.customNodeFactory(
  66. CustomNodes.StringLiteralControlFlowStorageCallNode
  67. );
  68. controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey);
  69. const statementNode: TStatement = controlFlowStorageCallCustomNode.getNode()[0];
  70. if (!statementNode || !Node.isExpressionStatementNode(statementNode)) {
  71. throw new Error(`\`controlFlowStorageCallCustomNode.getNode()[0]\` should returns array with \`ExpressionStatement\` node`);
  72. }
  73. return statementNode.expression;
  74. }
  75. }