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                           6061x                   6061x 6061x                       8648x   8648x 3073x   5575x     8648x                                               8648x 8648x   8648x   8648x         1526x     7122x 7122x   7122x       7122x   7122x   7122x 7122x 7122x   7122x      
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;
    }
}