<commit_before>require 'tree'

module Orbacle
  class GenerateClassHierarchy
    KlassNode = Struct.new(:name, :real, :inheritance)

    def initialize(db)
      @db = db
    end

    def call
      klasslikes = @db
        .find_all_klasslikes
        .select {|kl| kl.type == "klass" }
        .map do |kl|
          {
            scope: kl.scope,
            name: kl.name,
            inheritance: kl.inheritance,
            nesting: kl.nesting,
          }
        end

      klasstree_hash = {}
      klasstree_hash["Object"] = KlassNode.new("Object", false, nil)

      klasslikes.each do |kl|
        if kl[:inheritance].nil?
          kl[:real_inheritance] = "Object"
          full_name = [kl[:scope], kl[:name]].compact.join("::")
          klasstree_hash[full_name] = KlassNode.new(full_name, true, kl[:real_inheritance])
        elsif kl[:inheritance].start_with?("::")
          kl[:real_inheritance] = kl[:inheritance][2..-1]
          full_name = [kl[:scope], kl[:name]].compact.join("::")
          klasstree_hash[full_name] = KlassNode.new(full_name, true, kl[:real_inheritance])

          scope = kl[:real_inheritance].split("::")[0..-2].join("::")
          scope = nil if scope == ""
          name = kl[:real_inheritance].split("::").last
          result = klasslikes.find do |kkl|
            kkl[:scope] == scope && kkl[:name] == name
          end
          if !result
            kl[:inheritance_faked] = true
            klasstree_hash[kl[:real_inheritance]] = KlassNode.new(kl[:real_inheritance], false, "Object")
          end
        else
          possible_parents = kl[:nesting].each_index.map do |i|
            [nesting_to_scope(kl[:nesting][0..i]), kl[:inheritance]].compact.join("::")
          end
          possible_parents.unshift(kl[:inheritance])
          possible_parents2 = possible_parents.map do |parent|
            scope = parent.split("::")[0..-2].join("::")
            scope = nil if scope == ""
            name = parent.split("::").last
            klasslikes.find do |kkl|
              kkl[:scope] == scope && kkl[:name] == name
            end
          end.compact
          chosen_real_inheritance = possible_parents2.last

          full_name = [kl[:scope], kl[:name]].compact.join("::")
          if chosen_real_inheritance
            kl[:real_inheritance] = [chosen_real_inheritance[:scope], chosen_real_inheritance[:name]].compact.join("::")
            klasstree_hash[full_name] = KlassNode.new(full_name, true, kl[:real_inheritance])
          else
            kl[:real_inheritance] = kl[:inheritance].dup
            kl[:inheritance_faked] = true
            klasstree_hash[full_name] = KlassNode.new(full_name, true, kl[:real_inheritance])
            klasstree_hash[kl[:real_inheritance]] = KlassNode.new(kl[:real_inheritance], false, "Object")
          end
        end
      end

      tree = Tree::TreeNode.new("Object", klasstree_hash["Object"])
      build_queue = [tree]
      while !build_queue.empty?
        current_node = build_queue.shift
        klasstree_hash
          .values
          .select {|kn| kn.inheritance == current_node.name }
          .each do |kn|
            tree_node = Tree::TreeNode.new(kn.name, kn)<commit_msg>Use real objects instead of hashes<commit_after>require 'tree'

module Orbacle
  class GenerateClassHierarchy
    KlassNode = Struct.new(:name, :real, :inheritance)

    def initialize(db)
      @db = db
    end

    def call
      klasslikes = @db
        .find_all_klasslikes
        .select {|kl| kl.type == "klass" }

      klasstree_hash = {}
      klasstree_hash["Object"] = KlassNode.new("Object", false, nil)

      klasslikes.each do |kl|
        if kl.inheritance.nil?
          real_inheritance = "Object"
          full_name = [kl.scope, kl.name].compact.join("::")
          klasstree_hash[full_name] = KlassNode.new(full_name, true, real_inheritance)
        elsif kl.inheritance.start_with?("::")
          real_inheritance = kl.inheritance[2..-1]
          full_name = [kl.scope, kl.name].compact.join("::")
          klasstree_hash[full_name] = KlassNode.new(full_name, true, real_inheritance)

          scope = real_inheritance.split("::")[0..-2].join("::")
          scope = nil if scope == ""
          name = real_inheritance.split("::").last
          result = klasslikes.find do |kkl|
            kkl.scope == scope && kkl.name == name
          end
          if !result
            klasstree_hash[real_inheritance] = KlassNode.new(real_inheritance, false, "Object")
          end
        else
          possible_parents = kl.nesting.each_index.map do |i|
            [nesting_to_scope(kl.nesting[0..i]), kl.inheritance].compact.join("::")
          end
          possible_parents.unshift(kl.inheritance)
          possible_parents2 = possible_parents.map do |parent|
            scope = parent.split("::")[0..-2].join("::")
            scope = nil if scope == ""
            name = parent.split("::").last
            klasslikes.find do |kkl|
              kkl.scope == scope && kkl.name == name
            end
          end.compact
          chosen_real_inheritance = possible_parents2.last

          full_name = [kl.scope, kl.name].compact.join("::")
          if chosen_real_inheritance
            real_inheritance = [chosen_real_inheritance.scope, chosen_real_inheritance.name].compact.join("::")
            klasstree_hash[full_name] = KlassNode.new(full_name, true, real_inheritance)
          else
            real_inheritance = kl.inheritance.dup
            klasstree_hash[full_name] = KlassNode.new(full_name, true, real_inheritance)
            klasstree_hash[real_inheritance] = KlassNode.new(real_inheritance, false, "Object")
          end
        end
      end

      tree = Tree::TreeNode.new("Object", klasstree_hash["Object"])
      build_queue = [tree]
      while !build_queue.empty?
        current_node = build_queue.shift
        klasstree_hash
          .values
          .select {|kn| kn.inheritance == current_node.name }
          .each do |kn|
            tree_node = Tree::TreeNode.new(kn.name, kn)
{'fraction_non_alphanumeric': 0.13360790774299836, 'fraction_numerical': 0.0029654036243822075, 'mean_word_length': 2.2622246104245027, 'pattern_counts': {'":': 24, '<': 3, '<?xml version=': 0, '>': 3, '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': '3298487', 'n_tokens_mistral': 1928, 'n_tokens_neox': 1911, 'n_words': 334}