All files / src/node-transformers/control-flow-transformers/control-flow-replacers AbstractControlFlowReplacer.ts

96.43% Statements 27/28
88.89% Branches 8/9
100% Functions 2/2
96.3% Lines 26/27
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 1161x 1x                     1x     1x                           5042x                   5042x 5042x                       8665x   8665x 3071x   5594x     8665x                                               8665x 8665x   8665x   8665x         1496x     7169x 7169x   7169x       7169x   7169x   7169x 7169x 7169x   7169x      
import { injectable, inject } from 'inversify';
import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
import * as ESTree from 'estree';
 
import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
 
import { IControlFlowReplacer } from '../../../interfaces/node-transformers/IControlFlowReplacer';
import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../../interfaces/options/IOptions';
import { IStorage } from '../../../interfaces/storages/IStorage';
 
import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 
@injectable()
export abstract class AbstractControlFlowReplacer implements IControlFlowReplacer {
    /**
     * @type {TCustomNodeFactory}
     */
    protected readonly customNodeFactory: TCustomNodeFactory;
 
    /**
     * @type {IOptions}
     */
    protected readonly options: IOptions;
 
    /**
     * @type {Map<string, Map<string, string[]>>}
     */
    protected readonly replacerDataByControlFlowStorageId: Map <string, Map<string, string[]>> = new Map();
 
    /**
     * @param customNodeFactory
     * @param options
     */
    constructor (
        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
        @inject(ServiceIdentifiers.IOptions) options: IOptions
    ) {
        this.customNodeFactory = customNodeFactory;
        this.options = options;
    }
 
    /**
     * @param identifierDataByControlFlowStorageId
     * @param controlFlowStorageId
     * @returns {Map<string, string[]>}
     */
    protected static getStorageKeysByIdForCurrentStorage (
        identifierDataByControlFlowStorageId: Map<string, Map<string, string[]>>,
        controlFlowStorageId: string
    ): Map<string, string[]> {
        let storageKeysById: Map<string, string[]>;
 
        if (identifierDataByControlFlowStorageId.has(controlFlowStorageId)) {
            storageKeysById = <Map<string, string[]>>identifierDataByControlFlowStorageId.get(controlFlowStorageId);
        } else {
            storageKeysById = new Map <string, string[]> ();
        }
 
        return storageKeysById;
    }
 
    /**
     * @param node
     * @param parentNode
     * @param controlFlowStorage
     * @returns {ESTree.Node}
     */
    public abstract replace (node: ESTree.Node, parentNode: ESTree.Node, controlFlowStorage: IStorage <ICustomNode>): ESTree.Node;
 
    /**
     * @param customNode
     * @param controlFlowStorage
     * @param replacerId
     * @param usingExistingIdentifierChance
     * @returns {string}
     */
    protected insertCustomNodeToControlFlowStorage (
        customNode: ICustomNode,
        controlFlowStorage: IStorage <ICustomNode>,
        replacerId: string,
        usingExistingIdentifierChance: number
    ): string {
        const controlFlowStorageId: string = controlFlowStorage.getStorageId();
        const storageKeysById: Map<string, string[]> = AbstractControlFlowReplacer
            .getStorageKeysByIdForCurrentStorage(this.replacerDataByControlFlowStorageId, controlFlowStorageId);
        const storageKeysForCurrentId: string[] | undefined = storageKeysById.get(replacerId);
 
        if (
            RandomGeneratorUtils.getMathRandom() > usingExistingIdentifierChance &&
            storageKeysForCurrentId &&
            storageKeysForCurrentId.length
        ) {
            return RandomGeneratorUtils.getRandomGenerator().pickone(storageKeysForCurrentId);
        }
 
        const generateStorageKey: (length: number) => string = (length: number) => {
            const storageKey: string = RandomGeneratorUtils.getRandomString(length);
 
            Iif (controlFlowStorage.getStorage().has(storageKey)) {
                return generateStorageKey(length);
            }
 
            return storageKey;
        };
        const storageKey: string = generateStorageKey(3);
 
        storageKeysById.set(replacerId, [storageKey]);
        this.replacerDataByControlFlowStorageId.set(controlFlowStorageId, storageKeysById);
        controlFlowStorage.set(storageKey, customNode);
 
        return storageKey;
    }
}