RenamePropertiesReplacer.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import { inject, injectable, } from 'inversify';
  2. import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
  3. import * as ESTree from 'estree';
  4. import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
  5. import { IIdentifierNamesGenerator } from '../../../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
  6. import { IRenamePropertiesReplacer } from '../../../interfaces/node-transformers/rename-properties-transformers/replacer/IRenamePropertiesReplacer';
  7. import { IOptions } from '../../../interfaces/options/IOptions';
  8. import { ReservedDomProperties } from '../../../constants/ReservedDomProperties';
  9. import { NodeGuards } from '../../../node/NodeGuards';
  10. import { NodeFactory } from '../../../node/NodeFactory';
  11. @injectable()
  12. export class RenamePropertiesReplacer implements IRenamePropertiesReplacer {
  13. /**
  14. * @type {IIdentifierNamesGenerator}
  15. */
  16. private readonly identifierNamesGenerator: IIdentifierNamesGenerator;
  17. /**
  18. * @type {Map<string, string>}
  19. * @private
  20. */
  21. private readonly propertyNamesMap: Map<string, string> = new Map();
  22. /**
  23. * @type {IOptions}
  24. */
  25. private readonly options: IOptions;
  26. /**
  27. * @type {Set<string>}
  28. */
  29. private readonly reservedDomPropertiesList: Set<string> = new Set(ReservedDomProperties);
  30. /**
  31. * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
  32. * @param {IOptions} options
  33. */
  34. public constructor (
  35. @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
  36. identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
  37. @inject(ServiceIdentifiers.IOptions) options: IOptions
  38. ) {
  39. this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
  40. this.options = options;
  41. }
  42. /**
  43. * @param {ESTree.Identifier | ESTree.Literal} node
  44. * @returns {ESTree.Identifier | ESTree.Literal}
  45. */
  46. public replace (node: ESTree.Identifier | ESTree.Literal): ESTree.Identifier | ESTree.Literal {
  47. if (NodeGuards.isIdentifierNode(node)) {
  48. return NodeFactory.identifierNode(
  49. this.replacePropertyName(node.name)
  50. );
  51. }
  52. if (NodeGuards.isLiteralNode(node) && typeof node.value === 'string') {
  53. return NodeFactory.literalNode(
  54. this.replacePropertyName(node.value)
  55. );
  56. }
  57. return node;
  58. }
  59. /**
  60. * @param {string} propertyName
  61. * @returns {string}
  62. * @private
  63. */
  64. private replacePropertyName (propertyName: string): string {
  65. if (this.isReservedName(propertyName)) {
  66. return propertyName;
  67. }
  68. let renamedPropertyName: string | null = this.propertyNamesMap.get(propertyName) ?? null;
  69. if (renamedPropertyName !== null) {
  70. return renamedPropertyName;
  71. }
  72. renamedPropertyName = this.identifierNamesGenerator.generateNext();
  73. this.propertyNamesMap.set(propertyName, renamedPropertyName);
  74. return renamedPropertyName;
  75. }
  76. /**
  77. * @param {string} name
  78. * @returns {boolean}
  79. */
  80. private isReservedName (name: string): boolean {
  81. return this.isReservedOptionName(name)
  82. || this.isReservedDomPropertyName(name);
  83. }
  84. /**
  85. * @param {string} name
  86. * @returns {boolean}
  87. */
  88. private isReservedOptionName (name: string): boolean {
  89. if (!this.options.reservedNames.length) {
  90. return false;
  91. }
  92. return this.options.reservedNames
  93. .some((reservedName: string) => {
  94. return new RegExp(reservedName, 'g').exec(name) !== null;
  95. });
  96. }
  97. /**
  98. * @param {string} name
  99. * @returns {boolean}
  100. */
  101. private isReservedDomPropertyName (name: string): boolean {
  102. return this.reservedDomPropertiesList.has(name);
  103. }
  104. }