<commit_before>import {isAstMatch, extract} from '../../../utils/matchesAst';
import RequireUtilDetector from './RequireUtilDetector';
import RequireUtilInheritsDetector from './RequireUtilInheritsDetector';

/**
 * Processes nodes to detect super classes and return information for later
 * transformation.
 *
 * Detects:
 *
 *   var util = require('util');
 *   ...
 *   util.inherits(Class1, Class2);
 */
export default class UtilInherits {
  constructor() {
    this.inheritsNode = undefined;
  }

  /**
   * Process a node and return inheritance details if found.
   * @param {Object} node
   * @param {Object} parent
   * @returns {Object/undefined} m
   *                    {String}   m.className
   *                    {Node}     m.superClass
   *                    {Object[]} m.relatedExpressions
   */
  process(node, parent) {
    let m;
    if ((m = new RequireUtilDetector().detect(node)) && parent.type === 'Program') {
      this.inheritsNode = m;
    }
    else if ((m = new RequireUtilInheritsDetector().detect(node)) && parent.type === 'Program') {
      this.inheritsNode = m;
    }
    else if (this.inheritsNode && (m = this.matchUtilInherits(node))) {
      return {
        className: m.className,
        superClass: m.superClass,
        relatedExpressions: [{node, parent}]
      };
    }
  }

  // Discover usage of this.inheritsNode
  //
  // Matches: <this.utilInherits>(<className>, <superClass>);
  matchUtilInherits(node) {
    return isAstMatch(node, {
      type: 'ExpressionStatement',
      expression: {
        type: 'CallExpression',<commit_msg>Loop over all possible detectors<commit_after>import {isAstMatch, extract} from '../../../utils/matchesAst';
import RequireUtilDetector from './RequireUtilDetector';
import RequireUtilInheritsDetector from './RequireUtilInheritsDetector';

/**
 * Processes nodes to detect super classes and return information for later
 * transformation.
 *
 * Detects:
 *
 *   var util = require('util');
 *   ...
 *   util.inherits(Class1, Class2);
 */
export default class UtilInherits {
  constructor() {
    this.inheritsNode = undefined;
    this.detectors = [
      new RequireUtilDetector(),
      new RequireUtilInheritsDetector(),
    ];
  }

  /**
   * Process a node and return inheritance details if found.
   * @param {Object} node
   * @param {Object} parent
   * @returns {Object/undefined} m
   *                    {String}   m.className
   *                    {Node}     m.superClass
   *                    {Object[]} m.relatedExpressions
   */
  process(node, parent) {
    let m;
    if (parent && parent.type === 'Program' && (m = this.detectInheritsNode(node))) {
      this.inheritsNode = m;
    }
    else if (this.inheritsNode && (m = this.matchUtilInherits(node))) {
      return {
        className: m.className,
        superClass: m.superClass,
        relatedExpressions: [{node, parent}]
      };
    }
  }

  detectInheritsNode(node) {
    for (const detector of this.detectors) {
      let inheritsNode;
      if ((inheritsNode = detector.detect(node))) {
        return inheritsNode;
      }
    }
  }

  // Discover usage of this.inheritsNode
  //
  // Matches: <this.utilInherits>(<className>, <superClass>);
  matchUtilInherits(node) {
    return isAstMatch(node, {
      type: 'ExpressionStatement',
      expression: {
        type: 'CallExpression',
{'fraction_non_alphanumeric': 0.1305382099316087, 'fraction_numerical': 0.0011894142134998512, 'mean_word_length': 2.601713062098501, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, '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': '521657', 'n_tokens_mistral': 1020, 'n_tokens_neox': 991, 'n_words': 234}