lib/code-path-analysis/code-path-analyzer.js
function processCodePathToEnter(analyzer, node) {
    let codePath = analyzer.codePath;
    let state = codePath && CodePath.getState(codePath);
    const parent = node.parent;

    switch (node.type) {
        case "Program":
        case "FunctionDeclaration":
        case "FunctionExpression":
        case "ArrowFunctionExpression":
            if (codePath) {

                // Emits onCodePathSegmentStart events if updated.
                forwardCurrentToHead(analyzer, node);
                debug.dumpState(node, state, false);
            }

            // Create the code path of this scope.
            codePath = analyzer.codePath = new CodePath(
                analyzer.idGenerator.next(),
                codePath,
                analyzer.onLooped
            );
            state = CodePath.getState(codePath);

            // Emits onCodePathStart events.
            debug.dump(`onCodePathStart ${codePath.id}`);
            analyzer.emitter.emit("onCodePathStart", codePath, node);
            break;

        case "LogicalExpression":
            if (isHandledLogicalOperator(node.operator)) {
                state.pushChoiceContext(
                    node.operator,
                    isForkingByTrueOrFalse(node)
                );
            }
            break;

        case "ConditionalExpression":
        case "IfStatement":
            state.pushChoiceContext("test", false);
            break;

        case "SwitchStatement":
            state.pushSwitchContext(
                node.cases.some(isCaseNode),
                astUtils.getLabel(node)
            );
            break;

        case "TryStatement":
            state.pushTryContext(Boolean(node.finalizer));
            break;

        case "SwitchCase":

            /*
             * Fork if this node is after the 2st node in `cases`.
             * It's similar to `else` blocks.
             * The next `test` node is processed in this path.
             */
            if (parent.discriminant !== node && parent.cases[0] !== node) {
                state.forkPath();
            }
            break;

        case "WhileStatement":
        case "DoWhileStatement":
        case "ForStatement":
        case "ForInStatement":
        case "ForOfStatement":
            state.pushLoopContext(node.type, astUtils.getLabel(node));
            break;

        case "LabeledStatement":
            if (!astUtils.isBreakableStatement(node.body)) {
                state.pushBreakContext(false, node.label.name);
            }
            break;

        default:
            break;
    }

    // Emits onCodePathSegmentStart events if updated.
    forwardCurrentToHead(analyzer, node);
    debug.dumpState(node, state, false);
}
function processCodePathToEnter(analyzer, node) {
    let codePath = analyzer.codePath;
    let state = codePath && CodePath.getState(codePath);
    const parent = node.parent;

    switch (node.type) {
        case "Program":
        case "FunctionDeclaration":
        case "FunctionExpression":
        case "ArrowFunctionExpression":
            if (codePath) {

                // Emits onCodePathSegmentStart events if updated.
                forwardCurrentToHead(analyzer, node);
                debug.dumpState(node, state, false);
            }

            // Create the code path of this scope.
            codePath = analyzer.codePath = new CodePath(
                analyzer.idGenerator.next(),
                codePath,
                analyzer.onLooped
            );
            state = CodePath.getState(codePath);

            // Emits onCodePathStart events.
            debug.dump(`onCodePathStart ${codePath.id}`);
            analyzer.emitter.emit("onCodePathStart", codePath, node);
            break;

        case "LogicalExpression":
            if (isHandledLogicalOperator(node.operator)) {
                state.pushChoiceContext(
                    node.operator,
                    isForkingByTrueOrFalse(node)
                );
            }
            break;

        case "ConditionalExpression":
        case "IfStatement":
            state.pushChoiceContext("test", false);
            break;

        case "SwitchStatement":
            state.pushSwitchContext(
                node.cases.some(isCaseNode),
                astUtils.getLabel(node)
            );
            break;

        case "TryStatement":
            state.pushTryContext(Boolean(node.finalizer));
            break;

        case "SwitchCase":

            /*
             * Fork if this node is after the 2st node in `cases`.
             * It's similar to `else` blocks.
             * The next `test` node is processed in this path.
             */
            if (parent.discriminant !== node && parent.cases[0] !== node) {
                state.forkPath();
            }
            break;

        case "WhileStatement":
        case "DoWhileStatement":
        case "ForStatement":
        case "ForInStatement":
        case "ForOfStatement":
            state.pushLoopContext(node.type, astUtils.getLabel(node));
            break;

        case "LabeledStatement":
            if (!astUtils.isBreakableStatement(node.body)) {
                state.pushBreakContext(false, node.label.name);
            }
            break;

        default:
            break;
    }

    // Emits onCodePathSegmentStart events if updated.
    forwardCurrentToHead(analyzer, node);
    debug.dumpState(node, state, false);
}
function processCodePathToEnter ( analyzer , node ) { let codePath = analyzer . codePath ; let state = codePath && CodePath . getState ( codePath ) ; const parent = node . parent ; switch ( node . type ) { case "Program" : case "FunctionDeclaration" : case "FunctionExpression" : case "ArrowFunctionExpression" : if ( codePath ) { // Emits onCodePathSegmentStart events if updated. forwardCurrentToHead ( analyzer , node ) ; debug . dumpState ( node , state , false ) ; } // Create the code path of this scope. codePath = analyzer . codePath = new CodePath ( analyzer . idGenerator . next ( ) , codePath , analyzer . onLooped ) ; state = CodePath . getState ( codePath ) ; // Emits onCodePathStart events. debug . dump ( ` ${ codePath . id } ` ) ; analyzer . emitter . emit ( "onCodePathStart" , codePath , node ) ; break ; case "LogicalExpression" : if ( isHandledLogicalOperator ( node . operator ) ) { state . pushChoiceContext ( node . operator , isForkingByTrueOrFalse ( node ) ) ; } break ; case "ConditionalExpression" : case "IfStatement" : state . pushChoiceContext ( "test" , false ) ; break ; case "SwitchStatement" : state . pushSwitchContext ( node . cases . some ( isCaseNode ) , astUtils . getLabel ( node ) ) ; break ; case "TryStatement" : state . pushTryContext ( Boolean ( node . finalizer ) ) ; break ; case "SwitchCase" : /*
             * Fork if this node is after the 2st node in `cases`.
             * It's similar to `else` blocks.
             * The next `test` node is processed in this path.
             */ if ( parent . discriminant !== node && parent . cases [ 0 ] !== node ) { state . forkPath ( ) ; } break ; case "WhileStatement" : case "DoWhileStatement" : case "ForStatement" : case "ForInStatement" : case "ForOfStatement" : state . pushLoopContext ( node . type , astUtils . getLabel ( node ) ) ; break ; case "LabeledStatement" : if ( ! astUtils . isBreakableStatement ( node . body ) ) { state . pushBreakContext ( false , node . label . name ) ; } break ; default : break ; } // Emits onCodePathSegmentStart events if updated. forwardCurrentToHead ( analyzer , node ) ; debug . dumpState ( node , state , false ) ; }
Updates the code path due to the type of a given node in entering.

@param {CodePathAnalyzer} analyzer - The instance.
@param {ASTNode} node - The current AST node.
@returns {void}
Updates the code path due to the type of a given node in entering .