<commit_before>import {SourceCoverage} from './source-coverage';
import { SHA, MAGIC_KEY, MAGIC_VALUE } from './constants';
import {createHash} from 'crypto';
import template from 'babel-template';

// istanbul ignore comment pattern
const COMMENT_RE = /^\s*istanbul\s+ignore\s+(if|else|next)(?=\W|$)/;
// source map URL pattern
const SOURCE_MAP_RE = /[#@]\s*sourceMappingURL=(.*)\s*$/m;

// generate a variable name from hashing the supplied file path
function genVar(filename) {
    var hash = createHash(SHA);
    hash.update(filename);
    return 'cov_' + parseInt(hash.digest('hex').substr(0, 12), 16).toString(36);
}

// VisitState holds the state of the visitor, provides helper functions
// and is the `this` for the individual coverage visitors.
class VisitState {
    constructor(types, sourceFilePath, inputSourceMap) {
        this.varName = genVar(sourceFilePath);
        this.attrs = {};
        this.nextIgnore = null;
        this.cov = new SourceCoverage(sourceFilePath);

        if (typeof (inputSourceMap) !== "undefined") {
            this.cov.inputSourceMap(inputSourceMap);
        }
        this.types = types;
        this.sourceMappingURL = null;
    }

    // should we ignore the node? Yes, if specifically ignoring
    // or if the node is generated.
    shouldIgnore(path) {
        return this.nextIgnore || !path.node.loc;
    }

    // extract the ignore comment hint (next|if|else) or null
    hintFor(node) {
        let hint = null;
        if (node.leadingComments) {
            node.leadingComments.forEach(function (c) {
                const v = (c.value || /* istanbul ignore next: paranoid check */ "").trim();
                const groups = v.match(COMMENT_RE);
                if (groups) {
                    hint = groups[1];
                }
            });
        }
        return hint;
    }

    // extract a source map URL from comments and keep track of it
    maybeAssignSourceMapURL(node) {
        const that = this;
        const extractURL = (comments) => {
            if (!comments) {
                return;
            }
            comments.forEach(function (c) {
                const v = (c.value || /* istanbul ignore next: paranoid check */ "").trim();
                const groups = v.match(SOURCE_MAP_RE);
                if (groups) {
                    that.sourceMappingURL = groups[1];
                }
            });
        };
        extractURL(node.leadingComments);
        extractURL(node.trailingComments);
    }

    // all the generic stuff that needs to be done on enter for every node
    onEnter(path) {
        const n = path.node;

        this.maybeAssignSourceMapURL(n);

        // if already ignoring, nothing more to do
        if (this.nextIgnore !== null) {
            return;
        }
        // check hint to see if ignore should be turned on
        const hint = this.hintFor(n);
        if (hint === 'next') {
            this.nextIgnore = n;
            return;
        }
        // else check custom node attribute set by a prior visitor
        if (this.getAttr(path.node, 'skip-all') !== null) {
            this.nextIgnore = n;
        }
    }

    // all the generic stuff on exit of a node,
    // including reseting ignores and custom node attrs
    onExit(path) {
        // restore ignore status, if needed
        if (path.node === this.nextIgnore) {
            this.nextIgnore = null;
        }
        // nuke all attributes for the node
        delete(path.node.__cov__);
    }

    // set a node attribute for the supplied node
    setAttr(node, name, value) {
        node.__cov__ = node.__cov__ || {};
        node.__cov__[name] = value;
    }

    // retrieve a node attribute for the supplied node or null
    getAttr(node, name) {
        const c = node.__cov__;
        if (!c) {
            return null;
        }
        return c[name];
    }

    //
    increase(type, id, index) {
        const T = this.types;
        const wrap = (index !== null
                // If `index` present, turn `x` into `x[index]`.
                ? (x) => T.memberExpression(x, T.numericLiteral(index), true)
                : (x) => x
        );
        return T.unaryExpression('++',
            wrap(
                T.memberExpression(
                    T.memberExpression(T.identifier(this.varName), T.identifier(type)),
                    T.numericLiteral(id),
                    true
                )
            )
        );
    }

    insertCounter(path, increment) {
        const T = this.types;
        if (path.isBlockStatement()) {
            path.node.body.unshift(T.expressionStatement(increment));
        } else if (path.isStatement()) {
            path.insertBefore(T.expressionStatement(increment));
        } else if ((path.isFunctionExpression() || path.isArrowFunctionExpression()) && T.isVariableDeclarator(path.parentPath)) {
            path.parentPath.parentPath.insertBefore(T.expressionStatement(
                increment
            ));
        } else /* istanbul ignore else: not expected */ if (path.isExpression()) {
            path.replaceWith(T.sequenceExpression([increment, path.node]));
        } else {
            console.error('Unable to insert counter for node type:', path.node.type);
        }
    }

    insertStatementCounter(path) {<commit_msg>fix: address regression discussed in https://github.com/istanbuljs/babel-plugin-istanbul/issues/78 (#40)<commit_after>import {SourceCoverage} from './source-coverage';
import { SHA, MAGIC_KEY, MAGIC_VALUE } from './constants';
import {createHash} from 'crypto';
import template from 'babel-template';

// istanbul ignore comment pattern
const COMMENT_RE = /^\s*istanbul\s+ignore\s+(if|else|next)(?=\W|$)/;
// source map URL pattern
const SOURCE_MAP_RE = /[#@]\s*sourceMappingURL=(.*)\s*$/m;

// generate a variable name from hashing the supplied file path
function genVar(filename) {
    var hash = createHash(SHA);
    hash.update(filename);
    return 'cov_' + parseInt(hash.digest('hex').substr(0, 12), 16).toString(36);
}

// VisitState holds the state of the visitor, provides helper functions
// and is the `this` for the individual coverage visitors.
class VisitState {
    constructor(types, sourceFilePath, inputSourceMap) {
        this.varName = genVar(sourceFilePath);
        this.attrs = {};
        this.nextIgnore = null;
        this.cov = new SourceCoverage(sourceFilePath);

        if (typeof (inputSourceMap) !== "undefined") {
            this.cov.inputSourceMap(inputSourceMap);
        }
        this.types = types;
        this.sourceMappingURL = null;
    }

    // should we ignore the node? Yes, if specifically ignoring
    // or if the node is generated.
    shouldIgnore(path) {
        return this.nextIgnore || !path.node.loc;
    }

    // extract the ignore comment hint (next|if|else) or null
    hintFor(node) {
        let hint = null;
        if (node.leadingComments) {
            node.leadingComments.forEach(function (c) {
                const v = (c.value || /* istanbul ignore next: paranoid check */ "").trim();
                const groups = v.match(COMMENT_RE);
                if (groups) {
                    hint = groups[1];
                }
            });
        }
        return hint;
    }

    // extract a source map URL from comments and keep track of it
    maybeAssignSourceMapURL(node) {
        const that = this;
        const extractURL = (comments) => {
            if (!comments) {
                return;
            }
            comments.forEach(function (c) {
                const v = (c.value || /* istanbul ignore next: paranoid check */ "").trim();
                const groups = v.match(SOURCE_MAP_RE);
                if (groups) {
                    that.sourceMappingURL = groups[1];
                }
            });
        };
        extractURL(node.leadingComments);
        extractURL(node.trailingComments);
    }

    // all the generic stuff that needs to be done on enter for every node
    onEnter(path) {
        const n = path.node;

        this.maybeAssignSourceMapURL(n);

        // if already ignoring, nothing more to do
        if (this.nextIgnore !== null) {
            return;
        }
        // check hint to see if ignore should be turned on
        const hint = this.hintFor(n);
        if (hint === 'next') {
            this.nextIgnore = n;
            return;
        }
        // else check custom node attribute set by a prior visitor
        if (this.getAttr(path.node, 'skip-all') !== null) {
            this.nextIgnore = n;
        }
    }

    // all the generic stuff on exit of a node,
    // including reseting ignores and custom node attrs
    onExit(path) {
        // restore ignore status, if needed
        if (path.node === this.nextIgnore) {
            this.nextIgnore = null;
        }
        // nuke all attributes for the node
        delete(path.node.__cov__);
    }

    // set a node attribute for the supplied node
    setAttr(node, name, value) {
        node.__cov__ = node.__cov__ || {};
        node.__cov__[name] = value;
    }

    // retrieve a node attribute for the supplied node or null
    getAttr(node, name) {
        const c = node.__cov__;
        if (!c) {
            return null;
        }
        return c[name];
    }

    //
    increase(type, id, index) {
        const T = this.types;
        const wrap = (index !== null
                // If `index` present, turn `x` into `x[index]`.
                ? (x) => T.memberExpression(x, T.numericLiteral(index), true)
                : (x) => x
        );
        return T.unaryExpression('++',
            wrap(
                T.memberExpression(
                    T.memberExpression(T.identifier(this.varName), T.identifier(type)),
                    T.numericLiteral(id),
                    true
                )
            )
        );
    }

    insertCounter(path, increment) {
        const T = this.types;
        if (path.isBlockStatement()) {
            path.node.body.unshift(T.expressionStatement(increment));
        } else if (path.isStatement()) {
            path.insertBefore(T.expressionStatement(increment));
        } else if ((path.isFunctionExpression() || path.isArrowFunctionExpression()) && T.isVariableDeclarator(path.parentPath)) {
            const parent = path.findParent((path) => path.parentPath.isProgram());
            if (parent) {
                parent.insertBefore(T.expressionStatement(
                    increment
                ));
            }
        } else /* istanbul ignore else: not expected */ if (path.isExpression()) {
            path.replaceWith(T.sequenceExpression([increment, path.node]));
        } else {
            console.error('Unable to insert counter for node type:', path.node.type);
        }
    }

    insertStatementCounter(path) {
{'fraction_non_alphanumeric': 0.11782616718951835, 'fraction_numerical': 0.002029894814541428, 'mean_word_length': 1.8682191055834878, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 10, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1624281', 'n_tokens_mistral': 3030, 'n_tokens_neox': 2926, 'n_words': 800}