Code coverage report for src/node-transformers/control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts

# 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

    8638x

    8638x
    3074x

    5564x

    8638x

    8638x
    8638x

    8638x

    8638x

    1534x

    7104x
    7104x

    7104x

    7104x

    7104x

    7104x
    7104x
    7104x

    7104x

     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;
        }
    }