All files / src/node-transformers/node-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                           1261x                   1261x 1261x                       1848x   1848x 677x   1171x     1848x                                               1848x 1848x   1848x   1848x         341x     1507x 1507x   1507x       1507x   1507x   1507x 1507x 1507x   1507x      
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.getRandomFloat(0, 1) > 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;
    }
}